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")

posted on   Milton  阅读(2182)  评论(0编辑  收藏  举报

编辑推荐:
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 全网最简单!3分钟用满血DeepSeek R1开发一款AI智能客服,零代码轻松接入微信、公众号、小程

导航

< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8
点击右上角即可分享
微信分享提示