zoukankan      html  css  js  c++  java
  • spring mvc:注解@ModelAttribute妙用

    在Spring mvc中,注解@ModelAttribute是一个非常常用的注解,其功能主要在两方面:

    1. 运用在参数上,会将客户端传递过来的参数按名称注入到指定对象中,并且会将这个对象自动加入ModelMap中,便于View层使用;
    2. 运用在方法上,会在每一个@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     @Resource
    2     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      * 设置model
    13      * 
    14      * @param model
    15      */
    16     @ModelAttribute
    17     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 response
    11      */
    12     @ModelAttribute
    13     private final void initResponse(HttpServletResponse response) {
    14         responseContainer.set(response);
    15     }
    16 
    17     /**
    18      * 获取当前线程的response对象
    19      * 
    20      * @return
    21      */
    22     protected final HttpServletResponse getResponse() {
    23         return responseContainer.get();
    24     }
    25 
    26     /**
    27      * 初始化request
    28      * 
    29      * @param request
    30      */
    31     @ModelAttribute
    32     private final void initRequest(HttpServletRequest request) {
    33         requestContainer.set(request);
    34     }
    35 
    36     /**
    37      * 获取当前线程的request对象
    38      * 
    39      * @return
    40      */
    41     protected final HttpServletRequest getRequest() {
    42         return requestContainer.get();
    43     }
    44 
    45     /**
    46      * 设置model
    47      * 
    48      * @param model
    49      */
    50     @ModelAttribute
    51     private final void initModelMap(ModelMap model) {
    52         modelContainer.set(model);
    53     }
    54 
    55     /**
    56      * 获取当前线程的modelMap对象
    57      * 
    58      * @return
    59      */
    60     protected final ModelMap getModelMap() {
    61         return modelContainer.get();
    62     }
    复制代码
  • 相关阅读:
    Linux合并iso
    Oracle中使用escape关键字实现like匹配特殊字符,以及&字符的转义
    hash算法-time33算法
    理解JMS规范中消息的传输模式和消息持久化
    Oracle启动
    Weblogic缓存
    shell
    Hibernate 延迟载入
    Android获取cpu使用率,剩余内存和硬盘容量
    TestNG的组測试和组中组測试
  • 原文地址:https://www.cnblogs.com/jpfss/p/10438636.html
Copyright © 2011-2022 走看看