当前位置:   article > 正文

30、请求处理-@RequestAttribute、@RequestBody

@requestattribute
  1. @RequestAttribute获取request请求域中的数据

使用场景:从request中取对应的属性值。 注意:属性和参数是不同的。

参数(parameter)和属性(Attribute)的区别:

参数是需要用户或者浏览器传,属性是我们拦截请求写入或者修改的。比如:httpServletRequest.setAttribute(name, value))

如果我们想在controller层中获取绑定属性值到一个参数,此时就可以使用@RequestAttribute,

具体了解参数(parameter)和属性(Attribute)的区别参考下文:

我们一般前后端分离开发每次请求都会携带一些固定的参数,例如: 租户id,坐席 id,我们会将这些固定参数放在 header 中,这时我们就可以使用过滤器来拦截请求,然后将取到的参数可以放到 request 或者 session 作用域中,在 controller 中我们就可以使用 @RequestAttribute 或者 @SessionAttribute 注解来获取值

@RequestAttribute注解的参数在项目里是自己解析出来的,并不是前端传递的。

具体一点,在项目里的拦截器里会对Token信息进行解析,解析出来的参数重新放在请求里(用httpServletRequest.setAttribute(name, value)),后边接口接收参数时就用这个注解。

接下来这句话很重要:@RequestAttribute只负责从request里面取属性值,至于你什么时候往里放值,是有多种方式的可以达到的:

1、@ModelAttribute注解预存

2、HandlerInterceptor拦截器中预存

3、请求转发带过来

扩展

在写http接口的时候,发现接口参数有两种注解,一种是@RequestAttribute,一种是@Requestparam,自己刚开始没明白区别,用postman调试的时候一直报错,后来才发现这个问题。

@RequestAttribute注解的参数在项目里是自己解析出来的,并不是前端传递的。具体一点,在项目里的拦截器里会对Token信息进行解析,解析出来的参数重新放在请求里(用httpServletRequest.setAttribute(name, value)),后边接口接收参数时就用这个注解。

@RequestParam注解则表示这个参数是通过前端传递过来的,如果请求里没有这个参数,则会报错400 Bad Request。这个注解用来解析请求路径里的参数(get请求)或者post请求中form表单格式的请求参数;

@RequestBody注解用来接收POST请求BODY里的参数,格式为JSON格式。

用例:

  1. @Controller
  2. public class RequestController {
  3. @GetMapping("/goto")
  4. public String goToPage(HttpServletRequest request){
  5. request.setAttribute("msg","成功了...");
  6. request.setAttribute("code",200);
  7. return "forward:/success"; //转发到 /success请求
  8. }
  9. @GetMapping("/params")
  10. public String testParam(Map<String,Object> map,
  11. Model model,
  12. HttpServletRequest request,
  13. HttpServletResponse response){
  14. map.put("hello","world666");
  15. model.addAttribute("world","hello666");
  16. request.setAttribute("message","HelloWorld");
  17. Cookie cookie = new Cookie("c1","v1");
  18. response.addCookie(cookie);
  19. return "forward:/success";
  20. }
  21. ///<-----------------主角@RequestAttribute在这个方法
  22. @ResponseBody
  23. @GetMapping("/success")
  24. public Map success(@RequestAttribute(value = "msg",required = false) String msg,
  25. @RequestAttribute(value = "code",required = false)Integer code,
  26. HttpServletRequest request){
  27. Object msg1 = request.getAttribute("msg");
  28. Map<String,Object> map = new HashMap<>();
  29. Object hello = request.getAttribute("hello");
  30. Object world = request.getAttribute("world");
  31. Object message = request.getAttribute("message");
  32. map.put("reqMethod_msg",msg1);
  33. map.put("annotation_msg",msg);
  34. map.put("hello",hello);
  35. map.put("world",world);
  36. map.put("message",message);
  37. return map;
  38. }
  39. }
  1. @RequestBody 获取请求体[POST]

注解@RequestBody接收的参数是来自requestBody中,即请求体。

一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。通常用于接收POST、DELETE等类型的请求数据。

@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);而最常用的使用请求体传参的无疑是POST请求了,所以使用@RequestBody接收数据时,一般都用POST方式进行提交。在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。

注:
1、一个请求,只有一个RequestBody;一个请求,可以有多个RequestParam。
2、在GET请求中,不能使用@RequestBody。

  • 当同时使用@RequestParam()和@RequestBody可以同时使用时,原SpringMVC接收参数的机制不变,只不过RequestParam接收的是key-value里面的参数,所以它会被切面进行处理从而可以用普通元素、数组、集合、对象等接收,而RequestBody 接收的是请求体里面的数据:

  • 如果参数时放在请求体中,application/json传入后台的话,那么后台要用@RequestBody才能接收到;如果不是放在请求体中的话,那么后台接收前台传过来的参数时,要用@RequestParam来接收,或则形参前 什么也不写也能接收。

如果参数前写了@RequestParam(xxx),那么前端必须有对应的xxx名字才行(不管其是否有值,当然可以通过设置该注解的required属性来调节是否必须传),如果没有xxx名的话,那么请求会出错,报400。
如果参数前不写@RequestParam(xxx)的话,那么就前端可以有可以没有对应的xxx名字才行,如果有xxx名的话,那么就会自动匹配;没有的话,请求也能正确发送。
这里与feign消费服务时不同;feign消费服务时,如果参数前什么也不写,那么会被默认是@RequestBody的。
  • 如果后端参数是一个对象,且该参数前是以@RequestBody修饰的,那么前端传递json参数时,必须满足以下要求:

  • 后端@RequestBody注解对应的类在将HTTP的输入流(含请求体)装配到目标类(即:@RequestBody后面的类)时,会根据json字符串中的key来匹配对应实体类的属性,如果匹配一致且json中的该key对应的值符合(或可转换为),这一条我会在下面详细分析,其他的都可简单略过,但是本文末的核心逻辑代码以及几个结论一定要看! 实体类的对应属性的类型要求时,会调用实体类的setter方法将值赋给该属性。

  • json字符串中,如果value为""的话,后端对应属性如果是String类型的,那么接受到的就是"",如果是后端属性的类型是Integer、Double等类型,那么接收到的就是null。

  • json字符串中,如果value为null的话,后端对应收到的就是null。

  • 如果某个参数没有value的话,在传json字符串给后端时,要么干脆就不把该字段写到json字符串中;要么写value时, 必须有值,null 或""都行。千万不能有类似 "name":, 这样的写法。

  1. @RequestBody与前端传过来的json数据的匹配规则

声明:根据不同的Content-Type等情况,Spring-MVC会采取不同的HttpMessageConverter实现来进行信息转换解析。

下面介绍的是最常用的:前端以Content-Type 为application/json,传递json字符串数据;后端以@RequestBody模型接收数据的情况。

  1. 解析json数据大体流程概述:

Http传递请求体信息,最终会被封装进com.fasterxml.jackson.core.json.UTF8StreamJsonParser中(提示:Spring采用CharacterEncodingFilter设置了默认编码为UTF-8),然后在public class BeanDeserializer extends BeanDeserializerBase implements java.io.Serializable中,通过 public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) throws IOException方法进行解析。


引用链接:https://blog.csdn.net/m0_37587418/article/details/125614343

引用链接:https://blog.csdn.net/weixin_46058921/article/details/127794325

引用链接:https://blog.csdn.net/justry_deng/article/details/80972817/

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/310116
推荐阅读
相关标签
  

闽ICP备14008679号