Miles' Blog

Welcome 2 My Planet

Available categories: [/] [development. ~]

关于servlet的线程模式 [Permalink]

Mon Nov 29 10:25:06 CST 2004

昨天做refactoring时候差点犯错误。因为目前的设计,是所有servlet继承公共基类,而基类中进行一些例如错误处理之类的系统级操作(参看这里),所以两者都要用到request/response。以前的做法,是从基类传入request/response,而在子类中调用各个方法时候,也是统统传入。

本来这样做是没什么问题的,可是昨天却怎么看都不舒服。到处都是HttpServletRequest request HttpServletResponse response,看着都烦。结果可想而知:在基类中弄一个private HttpServletRequest requestprivate HttpServletResponse response,一进入主方法先就设置成员变量,以后就再也不用传递request/response了。

看上去完美了很多,可是仔细一想,如果这样能行,为什么容器还要传递这些玩意??一定有问题!!这时候突然想到了SingleThreadModal这个接口(真的是突然阿。。 /images/emoticons/plain.gif )。。恍然大悟。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





Author (*):
Verify Code (*):8 9 7 9
E-mail:
URL:
Comment (*):
Remember me?

Available categories: [/] [development. ~]

Powered By blojsom   RSS Feed  RSS2 Feed  RDF Feed