标签:
现在主流的java的前端框架有:struts1,struts2,springmvc 还有最根本的servlet;
前些天一个朋友问我这方面的问题,就研究一番:
1.关于struts1:
Struts1使用的ActionServlet是单例的,由这一个servlet处理所有.do请求。RequestProcessor也是单例。
RequestProcessor的processActionCreate方法:
/** * <p>Return an <code>Action</code> instance that will be used to process * the current request, creating a new one if necessary.</p> * * @param request The servlet request we are processing * @param response The servlet response we are creating * @param mapping The mapping we are using * @return An <code>Action</code> instance that will be used to process * the current request. * @throws IOException if an input/output error occurs */ protected Action processActionCreate(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws IOException { // Acquire the Action instance we will be using (if there is one) String className = mapping.getType(); if (log.isDebugEnabled()) { log.debug(" Looking for Action instance for class " + className); } Action instance; // 这个同步快保证了Action的单例 synchronized (actions) { // Return any existing Action instance of this class instance = (Action) actions.get(className); if (instance != null) { if (log.isTraceEnabled()) { log.trace(" Returning existing Action instance"); } return (instance); } // Create and return a new Action instance if (log.isTraceEnabled()) { log.trace(" Creating new Action instance"); } try { instance = (Action) RequestUtils.applicationInstance(className); // Maybe we should propagate this exception // instead of returning null. } catch (Exception e) { log.error(getInternal().getMessage("actionCreate", mapping.getPath()), e); response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, getInternal().getMessage("actionCreate", mapping.getPath())); return (null); } actions.put(className, instance); if (instance.getServlet() == null) { instance.setServlet(this.servlet); } } return (instance); }
从结果可以知道,是单例,既然是单例,如果当使用实例变量的时候就会有线程安全的问题;
2.关于struts2
我们知道我们使用struts2的时候,都是使用actionContext ;都是使用里面的实例变量,让struts2自动匹配成对象的。如果不是线程安全那全完了;所以struts2必须是线程安全的;因为每次处理一个请求,struts就会实例化一个对象;这样就不会有线程安全的问题了;
哦,忘记了一种情况,struts2+spring来管理注入的时候;如果把action设置为单例模式,就会出现问题;可以把action设置为prototype类型,还有一个办法是设置作用域(具体没有实验过)
3.关于SpringMVC
SpringMVC的controller默认是单例模式的,所以也会有多线程并发的问题;
参考代码:
@RequestMapping("/user") @Controller Class UserController { @Resource UserService userService; @RequestMapping("/add") public void testA(User user){ userService.add(user); } @RequestMapping("/get") public void testA(int id){ userService.get(id); } } @Service("userService") Class UserService{ public static Map<Integer,User> usersCache = new HashMap<String,User>(); public void add(User user){ usersCache.put(user.getId(),user); } public void get(int id){ usersCache.get(id); } }
usersCache就是非线程安全的。
解决方法:
1)同步共享数据
2)不使用成员实例变量;
3)使用只读数据
参考文章:
关于java Servlet,Struts,springMVC 的线程安全问题
标签:
原文地址:http://my.oschina.net/Tonyjingzhou/blog/514345