如果我们要给其它系统提供API接口,那么我们写的方法要返回ResponseEntity<XXX>,其它系统用httpclient获取的ResponseEntity的getBody就是XXX对象的字符串形式。
如果我们给自己系统的前台提供资源,返回用@ResponseBody,返回用XXX即可。
当我们要返回状态码时, @ResponseBody下的方法返回类型要使用ResponseEntity,如ResponseEntity<User>,ResponseEntity<Void>等,这样状态码会被写到响应头中,而不是响应体中
查询:返回ResponseEntity<User>
@RequestMapping(value = "{id}", method = RequestMethod.GET)
@ResponseBody //有ResponseEntity,其实不用 @ResponseBody也能返回json的
public ResponseEntity<User> queryUserById(@PathVariable("id") Long id) {
try {
User user = userService.getUserById(id);
if (null == user) {
// 资源不存在,响应404
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
// 资源存在,响应200
// return ResponseEntity.status(HttpStatus.OK).body(user);
return ResponseEntity.ok(user);
} catch (Exception e) {
e.printStackTrace();
}
//若发生异常,就500错误
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(null);
}
新增:返回ResponseEntity<Void>
这里要注意,你的请求,请求头content-type:application/json是必须写的(编码类型)
请求体中写json字符串,比如{"key":"value"},这要配合方法中的@RequestBody
请求头中要与请求体一致
区别于表单提交,如果没有@RequestBody ,那么请求头中可以不用content-type:application/json,当传入age=20&password=123这样的参数能请求成功。
如果代码中没有@RequestBody ,但我们传入了{"key":"value"}这种格式的,那么值都为空。
一般都会有@RequestBody
@RequestMapping(method = RequestMethod.POST)
public ResponseEntity<Void> saveUser(@RequestBody User user) {
try {
Boolean bool = userService.saveUser(user);
if (bool) {
// 新增成功,响应201
return ResponseEntity.status(HttpStatus.CREATED).build();
}
} catch (Exception e) {
e.printStackTrace();
}
// 新增失败,响应500
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
更新:返回ResponseEntity<Void>
@RequestMapping(method = RequestMethod.PUT)
public ResponseEntity<Void> updateUser(@RequestBody User user) {
try {
Boolean bool = userService.updateUser(user);
if (bool) {
// 更新成功,响应204
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}
} catch (Exception e) {
e.printStackTrace();
}
// 新增失败,响应500
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
这里要注意,更新时如果使用了@RequestBody,那么用PUT请求时,不用担心PUT请求无法提交表单数据的问题的问题,因为传的参数不是表单型的(age=20&password=123),而是JSON型的({"key":"value"})。
那么如果方法中没有使用@RequestBody,那么要用表单提交时,要在web.xml中添加
<!-- 解决PUT请求无法提交表单数据的问题 -->
<filter>
<filter-name>HttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HttpPutFormContentFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
过滤器
删除:返回ResponseEntity<Void>
@RequestMapping(value = "{id}", method = RequestMethod.DELETE)
public ResponseEntity<Void> deleteUser(@PathVariable(value = "id") Long id) {
try {
User user = userService.queryUserById(id);
if (null == user) {
// 资源不存在,响应404
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}
Boolean bool = this.userService.deleteUser(id);
if (bool) {
// 删除成功,响应204
return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
}
} catch (Exception e) {
e.printStackTrace();
}
// 删除失败,响应500
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
前面方法要求我们使用httpclient时使用delete,否则报错。
如果仅仅是我们自己的前台系统调用ajax请求去删除资源,我们就不需要使用restful风格。我们使用普通的GET请求就可以了。
注意,如果想使用表单形式的删除,那么不要使用@PathVariable,用@RequestParam即可,另外,还要在web.xml中配置
<!--
将POST请求转化为DELETE或者是PUT要用_method指定真正的请求方法,可以使DELETE或PUT
-->
<filter>
<filter-name>HiddenHttpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>HiddenHttpMethodFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在请求中还要添加_method=DELETE(通过ajax请求时,type就是POST),最终的url就是/rest/...?id=xxx&_method=DELETE。后台不用去判断_method参数,只需要method = RequestMethod.DELETE 就可以进去了。
总结:使用@RequestBody XXX xxx做请求体中的值和XXX xxx做参数是有本质区别的,后者是请求参数,类似于?xxx=xxx&xxx2=xxx2,后者不是真正的REST风格,@RequestParam也不是真正的REST风格。
当有这两个过滤器时,不影响我们使用restTemplate。
200查询成功,201创建成功,204修改成功、删除成功,404资源未找到、400参数有误、500系统内部错误