从原理层面掌握@RequestAttribute、@SessionAttr…
2019-08-16 12:13:14来源:博客园 阅读 ()
从原理层面掌握@RequestAttribute、@SessionAttribute的使用【一起学Spring MVC】
每篇一句
改我们就改得:取其精华,去其糟粕。否则木有意义
前言
如果说知道@SessionAttributes
这个注解的人已经很少了,那么不需要统计我就可以确定的说:知道@RequestAttribute
注解的更是少之又少。我觉得主要有如下两个原因:
@RequestAttribute
这个注解很新,Spring4.3
后才有- 我们可以使用API调用的方式(
ServletRequest.getAttribute()
)来达到目的,而不用注解。且成本也不太高
既然Spring推出了这个注解,那必然有它的优点。本文就带大家领略一下它的风骚之处。
Spring
提供的这些注解比如@ModelAttribute
、@SessionAttributes
、@RequestAttribute
都是为了简化开发,提高复用性。同时另外一个目的是希望完全屏蔽掉源生Servlet API,增加它的扩展性。
本文我以
@RequestAttribute
为例进行讲解,因为@SessionAttribute
(也是Spring4.3后推出的注解)不管从使用和原理上都是一模一样的。你可以理解成唯一区别是ServletRequest.getAttribute()
和HttpSession.getAttribute()
的区别
此处再强调一次,这里指的是:org.springframework.web.bind.annotation.SessionAttribute
,而非org.springframework.web.bind.annotation.SessionAttributes
@RequestAttribute
它比前面介绍的那些@ModelAttribute
、@SessionAttributes
等注解要简单很多,它只能使用在方法入参上。作用:从request中取对应的属性值。
很多小伙伴对
getParameter()
和getAttribute()
相关方法傻傻分不清楚。建议你可以先弄清楚param
和attribute
的区别~
// @since 4.3
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestAttribute {
@AliasFor("name")
String value() default "";
@AliasFor("value")
String name() default "";
// 默认情况下 这个属性是必须的(没有就报错了)
boolean required() default true;
}
接下来这句话很重要:@RequestAttribute
只负责从request里面取属性值,至于你什么时候往里放值,是有多种方式的可以达到的:
@ModelAttribute
注解预存HandlerInterceptor
拦截器中预存- 请求转发带过来
下面分别按照这三种使用场景,给出使用Demo
:
@ModelAttribute
注解预存
比较简单,在@ModelAttribute
标注的方法上使用源生的HttpServletRequest
放值即可
@RestController
@RequestMapping
public class HelloController {
// 放置attr属性值
@ModelAttribute
public Person personModelAttr(HttpServletRequest request) {
request.setAttribute("myApplicationName", "fsx-application");
return new Person("非功能方法", 50);
}
@GetMapping("/testRequestAttr")
public void testRequestAttr(@RequestAttribute("myApplicationName") String myApplicationName, HttpServletRequest request, ModelMap modelMap) {
System.out.println(myApplicationName); //fsx-application
// 从request里获取
System.out.println(request.getAttribute("myApplicationName")); //fsx-application
// 从model里获取
System.out.println(modelMap.get("myApplicationName")); // null 获取不到attr属性的
System.out.println(modelMap.get("person")); // Person(name=非功能方法, age=50)
}
}
请求/testRequestAttr
,结果打印如下:
fsx-application
fsx-application
null
Person(name=非功能方法, age=50)
这里务必注意:@RequestAttribute("myApplicationName")
注解如果省略,是绑定不到attr属性的哦(必须要有注解)~
但是,这样是可行的:
@RequestAttribute String myApplicationName
(若注解没有指定,Spring MVC
会再去看形参的名字来确认自动绑定)
但若你写成了这样@RequestAttribute String aaa
,那请求就直接400错误了抛出异常:org.springframework.web.bind.ServletRequestBindingException
HandlerInterceptor
拦截器中预存
简单,直接上代码:
public class SimpleInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
request.setAttribute("myApplicationName", "fsx-application");
return true;
}
...
}
测试代码:略。
forward
请求转发带过来
形如这样:
request.setAttribute("myApplicationName", "fsx-application");
request.getRequestDispatcher("/index").forward(request, response);
其实往里放置属性值只需要遵循一个原则:在调用处理器目标方法之前
(参数封装之前)任意地方放置即可,属性值是都能被取到的。
原理剖析
按照我的习惯,即使它很简单,我也会扒开来看看它的原理部分嘛。
根据经验很容易想到解析它的是一个HandlerMethodArgumentResolver
,它就是RequestAttributeMethodArgumentResolver
RequestAttributeMethodArgumentResolver
很明显,它也是@since 4.3
才出现的,命名上也很配套嘛。
public class RequestAttributeMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
// 只处理标注了@RequestAttribute注解的入参
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(RequestAttribute.class);
}
// 封装此注解的属性到NamedValueInfo 这里关于参数名的处理有这么一个处理
// info.name.isEmpty()也就说如果自己没有指定,就用形参名parameter.getParameterName()
@Override
protected NamedValueInfo createNamedValueInfo(MethodParameter parameter) {
RequestAttribute ann = parameter.getParameterAnnotation(RequestAttribute.class);
Assert.state(ann != null, "No RequestAttribute annotation");
return new NamedValueInfo(ann.name(), ann.required(), ValueConstants.DEFAULT_NONE);
}
// 从request请求域去找属性值
@Override
@Nullable
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request){
return request.getAttribute(name, RequestAttributes.SCOPE_REQUEST);
}
// 若值不存在,抛出异常ServletRequestBindingException
@Override
protected void handleMissingValue(String name, MethodParameter parameter) throws ServletException {
throw new ServletRequestBindingException("Missing request attribute '" + name +
"' of type " + parameter.getNestedParameterType().getSimpleName());
}
}
源码短小精悍,非常简单。
其实它解析入参方面的核心解析流程在其父类AbstractNamedValueMethodArgumentResolver
身上,但并不是本文的重点,请详见HandlerMethodArgumentResolver
的章节~
@RequestAttribute
属性required
默认为true,request.getAttribute
获取不到参数就会抛出异常ServletRequestBindingException
;required设置为false,即使没有从request中获取到就忽略跳过,赋值为null;
总结
这篇文章介绍了@RequestAttribute
的使用Demo
,以及它很简单的原理分析。相较于之前所有文章,这篇是非常轻松的,希望可以提供给大家一个思路,来使用@RequestAttribute
提高你的逼格,哈哈(友情提示:装逼需谨慎哦~)
说明:因为
@SessionAttribute
的使用甚至原理几乎一毛一样,所以不用再重复篇幅了
总结
这篇文章介绍了@SessionAttributes
的核心处理原理,以及也给了一个Demo
来介绍它的基本使用,不出意外阅读下来你对它应该是有很好的收获的,希望能帮助到你简化开发~
相关阅读
从原理层面掌握HandlerMethod、InvocableHandlerMethod、ServletInvocableHandlerMethod的使用【一起学Spring MVC】
从原理层面掌握@SessionAttributes的使用【一起学Spring MVC】
从原理层面掌握@ModelAttribute的使用(核心原理篇)【一起学Spring MVC】
从原理层面掌握@ModelAttribute的使用(使用篇)【一起学Spring MVC】
知识交流
==The last:如果觉得本文对你有帮助,不妨点个赞呗。当然分享到你的朋友圈让更多小伙伴看到也是被作者本人许可的~
==
若对技术内容感兴趣可以加入wx群交流:Java高工、架构师3群
。
若群二维码失效,请加wx号:fsx641385712
(或者扫描下方wx二维码)。并且备注:"java入群"
字样,会手动邀请入群
原文链接:https://www.cnblogs.com/fangshixiang/p/11324091.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:Mybatis笔记
- 掌握SpringBoot-2.3的容器探针:实战篇 2020-06-11
- Spring Boot 实现配置文件加解密原理 2020-06-08
- Java 必须掌握的 12 种 Spring 常用注解! 2020-06-08
- Java跨平台原理(字节码文件、虚拟机) 以及Java安全性 2020-06-07
- Java生鲜电商平台-生鲜电商接口幂等性原理与防重复提交方案( 2020-06-05
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash