spring mvc:注解@ModelAttribute妙用
在Spring mvc中,注解@ModelAttribute是一个非常常用的注解,其功能主要在两方面:
- 运用在参数上,会将客户端传递过来的参数按名称注入到指定对象中,并且会将这个对象自动加入ModelMap中,便于View层使用;
- 运用在方法上,会在每一个@RequestMapping标注的方法前执行,如果有返回值,则自动将该返回值加入到ModelMap中;
一般开发中,第一种用法居多,本次我将使用第二种用法以期节省controller层的一些代码:
目前使用spring mvc开发的controller层方法一般类似于:
1 @RequestMapping("/{encodeId}/detail")2 public String detail(ModelMap model, @PathVariable String encodeId) {3 .....4 }
几乎在每一个@RequestMapping标注的方法的参数中都会有 ModelMap model的参数,既然这是一个大概率事件,为什么不可以像注入request那样,直接在类的开始使用@Resource进行自动注入呢?
另外一个,就是response,response也不能像request那样进行自动注入。
类似的可能还有很多,既然这些都是controller层常用的代码,如果能将其在一个basecontroller层自动注入,然后controller层继承这个basecontroller,那样就没有必要再@RequestMapping标注的方法中写上这些参数,使得参数个数减少,清晰。
我的思路正是使用@ModelAttribute注解,编写一个basecontroller类,预定义一些项目中controller层常用的对象,如下:
1 @Resource2 protected HttpServletRequest request;3 4 protected ModelMap model;5 6 protected HttpServletResponse response;
request不用解释,可以直接使用@Resource直接注入,response和model的注入方式如下:
1 /** 2 * 设置response 3 * 4 * @param response 5 */ 6 @ModelAttribute 7 private final void initResponse(HttpServletResponse response) { 8 this.response = response; 9 }10 11 /**12 * 设置model13 * 14 * @param model15 */16 @ModelAttribute17 private final void initModelMap(ModelMap model) {18 this.model = model;19 }
spring在执行@RequestMapping前会执行上述方法,spring会和平常一样,每次请求重新生成一个model和response,然后注入到方法的参数中,这样就变相在继承了这个basecontroller的controller中自动注入了response和model,在这个controller层中再也不必每次写ModelMap和response参数,整体代码整洁了不少。
我在项目中这样使用暂无问题,如果哪位高手知道这种做法会有弊端或者有更好的方法,求指正!
修正:
非常感谢eBusinessMan的提醒,确实有可能在spring mvc单例模式下会出现访问对象不一致的情况,为了防止该问题,而又能保持这种代码的简洁性以及确保使用spring mvc性能问题不太严重,我决定使用ThreadLocal来处理。(后期验证是否会出现该问题在本文进行补充)
(验证结果:request采用spring的自动注入方式是线程安全的,response、model是不安全的,采用ThreadLocal可以解决该问题)
request对象不再使用注解自动注入(也可以继续使用注解方式注入),而使用同response和model初始化的方式,取消request、response、model三个类变量,具体如下:
1 private static final ThreadLocal<HttpServletRequest> requestContainer = new ThreadLocal<HttpServletRequest>(); 2 3 private static final ThreadLocal<HttpServletResponse> responseContainer = new ThreadLocal<HttpServletResponse>(); 4 5 private static final ThreadLocal<ModelMap> modelContainer = new ThreadLocal<ModelMap>(); 6 7 /** 8 * 初始化response 9 * 10 * @param response11 */12 @ModelAttribute13 private final void initResponse(HttpServletResponse response) {14 responseContainer.set(response);15 }16 17 /**18 * 获取当前线程的response对象19 * 20 * @retu21 */22 protected final HttpServletResponse getResponse() {23 retu responseContainer.get();24 }25 26 /**27 * 初始化request28 * 29 * @param request30 */31 @ModelAttribute32 private final void initRequest(HttpServletRequest request) {33 requestContainer.set(request);34 }35 36 /**37 * 获取当前线程的request对象38 * 39 * @retu40 */41 protected final HttpServletRequest getRequest() {42 retu requestContainer.get();43 }44 45 /**46 * 设置model47 * 48 * @param model49 */50 @ModelAttribute51 private final void initModelMap(ModelMap model) {52 modelContainer.set(model);53 }54 55 /**56 * 获取当前线程的modelMap对象57 * 58 * @retu59 */60 protected final ModelMap getModelMap() {61 retu modelContainer.get();62 }
作者:雨中漫步,惟情而已
来源链接:https://www.cnblogs.com/liaochong/p/spring_modelattribute.html
版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。
2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。