如果我们要给其它系统提供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系统内部错误