ResponseEntity继承了HttpEntity类,HttpEntity代表一个http请求或者响应实体,其内部有两个成员变量:header及body,代表http请求或响应的header及body,其中的body是泛化的。
ResponseEntity类,扩展了HttpEntity类,新增了status成员变量,这样,一个ResponseEntity基本可以代表完整的http的请求或响应了。这其实就是ResponseEntity类的作用。
public class ResponseEntity<T> extends HttpEntity<T> { private final Object status; public ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, HttpStatus status) { super(body, headers); Assert.notNull(status, "HttpStatus must not be null"); this.status = status; } // 省略其他代码 }
1、只响应:状态码,不响应数据,如insert、update、delete操作时:
//方式一,使用ResponseEntiry的静态方法 return ResponseEntity.status(HttpStatus.BAD_REQUEST); //方式二,使用ResponseEntiry的静态方法 return ResponseEntity.status(400); //方式三,使用ResponseEntity的构造函数,通过数字状态码解析 return new ResponseEntity<>(HttpStatus.resolve(400)); //方式四,使用ResponseEntity的构造函数,通过枚举类型获取 return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
以下状态码获取都可以通过这两种方式获得。(数字状态码解析、枚举类型获取)
2、只响应:数据
//使用ResponseEntiry的静态方法,默认状态码200,pageinfo是分页数据 return ResponseEntity.ok(pageInfo);
3、响应:数据 和 状态码
//使用ResponseEntity的构造函数 return new ResponseEntity<>(pageInfo,HttpStatus.resolve(200));
4、响应:状态码 和 头信息
//创建响应头对象,并添加头信息 HttpHeaders headers = new HttpHeaders(); headers.add("Custom-Header", "foo"); //使用ResponseEntity的构造函数 return new ResponseEntity<>(headers,HttpStatus.resolve(200));
5、响应:状态码 、数据 和 头信息
方式一
//创建响应头对象,并添加头信息 HttpHeaders headers = new HttpHeaders(); headers.add("Custom-Header", "foo"); //使用ResponseEntity的构造函数 return new ResponseEntity<>(pageInfo,headers,HttpStatus.resolve(200));
方式二
//创建响应头对象,并添加头信息 HttpHeaders headers = new HttpHeaders(); headers.add("Custom-Header", "foo"); //使用ResponseEntiry的静态方法,默认状态码200 return ResponseEntity.ok().header("Custom-Header", "001").body(pageInfo);
HttpStaus是一个枚举类,包含了所有的状态码信息
public enum HttpStatus
常用状态码对应表:其他的自行去HttpStatus枚举中查看
枚举属性 | 状态码 |
---|---|
CONTINUE | 100 |
OK | 200 |
CREATED | 201 |
NO_CONTENT | 204 |
PARTIAL_CONTENT | 206 |
MOVED_PERMANENTLY | 301 |
FOUND | 302 |
NOT_MODIFIED | 304 |
BAD_REQUEST | 400 |
UNAUTHORIZED | 401 |
FORBIDDEN | 403 |
NOT_FOUND | 404 |
INTERNAL_SERVER_ERROR | 500 |
SERVICE_UNAVAILABLE | 503 |
public class ResponseEntity<T> extends HttpEntity<T> { public ResponseEntity(HttpStatus status) { this((Object)null, (MultiValueMap)null, (HttpStatus)status); } public ResponseEntity(@Nullable T body, HttpStatus status) { this(body, (MultiValueMap)null, (HttpStatus)status); } public ResponseEntity(MultiValueMap<String, String> headers, HttpStatus status) { this((Object)null, headers, (HttpStatus)status); } public ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, HttpStatus status) { super(body, headers); Assert.notNull(status, "HttpStatus must not be null"); this.status = status; } private ResponseEntity(@Nullable T body, @Nullable MultiValueMap<String, String> headers, Object status) { super(body, headers); Assert.notNull(status, "HttpStatus must not be null"); this.status = status; } }
可以看到这个类提供了五个构造方法,返回的状态码是必传的外,头部信息以及响应体内容都是可选择的。当我们需要使用的时候,直接new一个ResponseEntity对象作为API返回值即可,这就是它的第一种使用方式。
需要注意的是,在有headers作为参数的构造方法中,需要传入一个类型为MultiValueMap<String, String>的参数。MultiValueMap继承自Map这个抽象类,其中拥有一个叫做HttpHeaders的子类,我们可以当它为一个key和value都为String类型的HashMap使用。HttpHeaders里面保存了一些常用的Header的key值,例如"Accept-Charset"。当然也可以自定义一些特殊的key。
HttpHeaders headers = new HttpHeaders(); headers.add("Access-Control-Expose-Headers", "AMP-Access-Control-Allow-Source-Origin"); return new ResponseEntity<>(resultBody, headers, HttpStatus.OK);
继续看源码,发现了好多返回值为ResponseEntity.BodyBuilder的方法有木有
public static ResponseEntity.BodyBuilder status(HttpStatus status) { Assert.notNull(status, "HttpStatus must not be null"); return new ResponseEntity.DefaultBuilder(status); } public static ResponseEntity.BodyBuilder status(int status) { return new ResponseEntity.DefaultBuilder(status); } public static ResponseEntity.BodyBuilder ok() { return status(HttpStatus.OK); } public static ResponseEntity.BodyBuilder created(URI location) { ResponseEntity.BodyBuilder builder = status(HttpStatus.CREATED); return (ResponseEntity.BodyBuilder)builder.location(location); } public static ResponseEntity.BodyBuilder accepted() { return status(HttpStatus.ACCEPTED); } public static ResponseEntity.HeadersBuilder<?> noContent() { return status(HttpStatus.NO_CONTENT); } public static ResponseEntity.BodyBuilder badRequest() { return status(HttpStatus.BAD_REQUEST); } public static ResponseEntity.HeadersBuilder<?> notFound() { return status(HttpStatus.NOT_FOUND); } public static ResponseEntity.BodyBuilder unprocessableEntity() { return status(HttpStatus.UNPROCESSABLE_ENTITY); } .........
事实证明,越是伟大的软件工程师是越“懒惰”的,为了节约时间增加效率,我们可以用Builder的方式去生成ResponseEntity对象并返回:
Map<String, String> resultBody = new HashMap<>(); resultBody.put("name":"Lucas"); resultBody.put("school":"harvard university"); return ResponseEntity.status(HttpStatus.OK) .body(resultBody);
@RestController = @Controller + @ResponseBody
@ResponseBody是将controller的方法返回的对象通过适当的转换器转换为指定的格式之后,写入到response对象的body区,通常用来返回JSON数据或者是XML数据。
注意:在使用此注解之后不会再走视图处理器(ModelAndView),而是直接将数据写入到输入流中,他的效果等同于通过response对象输出指定格式的数据。
这个注解主要用在自定义的Exception 上,或者直接用在controller层的API方法上也可,当发生异常/方法执行结束时,会返回相应的Http状态码和msg。
@ResponseStatus(value=HttpStatus.FORBIDDEN,reason="不允许访问")
注:
ResponseEntity的优先级高于@ResponseBody。只有在返回值不为ResponseEntity的情况下才去检查有没有@ResponseBody注解;如果响应类型是ResponseEntity则会忽略@ResponseBody注解。
ResponseEntity能够非常方便的修改返回值的状态码,但最优秀的用法仍然是能够为不同API设置不同的返回响应头。