关于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