关于servlet的线程模式 [Permalink]
Mon Nov 29 10:25:06 CST 2004
昨天做refactoring时候差点犯错误。因为目前的设计,是所有servlet继承公共基类,而基类中进行一些例如错误处理之类的系统级操作(参看这里),所以两者都要用到request/response。以前的做法,是从基类传入request/response,而在子类中调用各个方法时候,也是统统传入。
本来这样做是没什么问题的,可是昨天却怎么看都不舒服。到处都是HttpServletRequest request HttpServletResponse response
,看着都烦。结果可想而知:在基类中弄一个private HttpServletRequest request
和private HttpServletResponse response
,一进入主方法先就设置成员变量,以后就再也不用传递request/response了。
看上去完美了很多,可是仔细一想,如果这样能行,为什么容器还要传递这些玩意??一定有问题!!这时候突然想到了SingleThreadModal这个接口(真的是突然阿。。 )。。恍然大悟。servlet是单实例多线程的,如果这样做,岂不是会有同步冲突??晕死。。联想到我的SessionListener:
public class SessionListener extends BaseListener implements HttpSessionListener, ServletRequestListener, Constant { private HttpServletRequest request; //Notification that a session was created public void sessionCreated(HttpSessionEvent se) { logger.debug("New session started!"); setEquipmentInfo(se.getSession()); clearAllAntiAttackRecs(); } private void setEquipmentInfo(HttpSession session) { WebStringUtil webStringUtil=WebStringUtil.getInstance(); String agent=webStringUtil.getUserAgent(request); String info=null; EquipmentService service=EquipmentServiceFactory.getService(); try { info=service.getUserEquipmentByAgent(agent); } catch( DidyException ex) { logger.warn(ex.getMessage()); } UserTracker userTracker=UserTracker.getInstance(); userTracker.setEquipmentInfo(session, info); } //Notification that a session was invalidated public void sessionDestroyed(HttpSessionEvent se) { logger.debug("Session ended!"); } private void clearAllAntiAttackRecs() { Map actAntiAttackRecs=BaseDidyServlet.getActAntiAttackRecs(); Iterator it=actAntiAttackRecs.keySet().iterator(); while(it.hasNext()) { clearAntiAttackRecs(actAntiAttackRecs, (String) it.next()); } } private void clearAntiAttackRecs(Map actAntiAttackRecs, String ip) { NumberUtil numberUtil=NumberUtil.getInstance(); Map ipAntiAttackMap=(Map) actAntiAttackRecs.get(ip); if(ipAntiAttackMap == null) { return; } Set obsoleteKeys=new HashSet(); Iterator it=ipAntiAttackMap.keySet().iterator(); while(it.hasNext()) { String key=it.next().toString(); Map myIpActAntiAttackMap=(Map) ipAntiAttackMap.get(key); long lastActTime= numberUtil.getLong(myIpActAntiAttackMap.get("TIME")); long minInterval= numberUtil.getLong( AppProp.read(ANTI_ATTACK_PREFIX_INTERVAL + "." + key) ); if(System.currentTimeMillis() - lastActTime >= minInterval) { obsoleteKeys.add(key); } } it=obsoleteKeys.iterator(); while(it.hasNext()) { ipAntiAttackMap.remove(it.next()); } if(ipAntiAttackMap.isEmpty()) { actAntiAttackRecs.remove(ip); } } /** The request is about to go out of scope of the web application. */ public void requestDestroyed(ServletRequestEvent sre) { } /** The request is about to come into scope of the web application. */ public void requestInitialized(ServletRequestEvent sre) { request=(HttpServletRequest) sre.getServletRequest(); } }这里就麻烦大了!上网找了资料,还是没有找到合适的。不行的话只能试试看加一个overall的filter来为session listener取得request了。UGLY啊!!
Posted by: miles
Comments on this entry