SpringMVC的Controller中使用线程安全的初始化

因为SpringMVC的Controller默认是单例, 在这种情况下, Controller中使用的私有变量必须也是单例, 例如各种service, 否则会有多线程访问数据互相修改的问题.

对于需要对一类Controller做相同初始化的需求, 可以通过@ModelAttribute("some-variable") public init() 这样的方法解决.

首先创建一个基类如BasicController, 构造一个拦截器, 对基类实现preHandle(), postHandle()方法

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
            Exception exception) throws Exception
    {
        RequestBean requestBean = (RequestBean)request.getAttribute(RequestBean.ATTR_KEY);
        if (requestBean != null)
        {
            requestBean.destroy();
            request.removeAttribute(RequestBean.ATTR_KEY);
            long current = System.currentTimeMillis();
            logger.debug("Page end: " + current + ", time: " + (current - requestBean.getTimestamp()) + " milliseconds");
        }
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView mav) throws Exception
    {
        if (handler instanceof HandlerMethod && mav != null)
        {
            HandlerMethod hm = (HandlerMethod)handler;
            if (BasicController.class.isAssignableFrom(hm.getBean().getClass()))
            {
                mav.addObject("sys_config", Config.getConfigs());
            }
        }
    }

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
    {
        long timestamp = System.currentTimeMillis();
        logger.debug("Page start: " + timestamp);

        if (handler instanceof HandlerMethod)
        {
            HandlerMethod hm = (HandlerMethod)handler;
            if (BasicController.class.isAssignableFrom(hm.getBean().getClass()))
            {
                RequestBean requestBean = new RequestBean(request, response, timestamp);
                request.setAttribute(RequestBean.ATTR_KEY, requestBean);
            }
        }
        return true;
    }

然后在BasicController中, 通过如下形式对每次访问作初始化

    @ModelAttribute("requestBean")
    public RequestBean initRequest(HttpServletRequest request) {
        return (RequestBean)request.getAttribute(RequestBean.ATTR_KEY);
    }

然后在Controller方法中, 就可以直接引用这个初始化好的变量了

@RequestMapping(value = {"/edit","/add"}, method = RequestMethod.GET)
public String doEdit(
        @ModelAttribute("requestBean") RequestBean rb)
{
  ...
}
@ModelAttribute("requestBean")
原文地址:https://www.cnblogs.com/milton/p/4855694.html