首页 > 解决方案 > 如何从新线程中的会话中删除属性?

问题描述

我写网络应用程序。有验证码,保存在会话中。创建验证码后,我启动新线程,其中作为参数,我从 servlet 传递 HttpServletRequest。接下来,转发发生在 servlet 中。线程休眠 1 分钟,并从会话中删除验证码属性。但我得到 NullPointerExeption。我认为这是因为前锋被召唤了。如何从该线程中的会话中删除属性?

我的代码:

public class RegisterServlet extends HttpServlet {
    private CaptchaHandler captchaHandler = new CaptchaHandler();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        captchaHandler.createCaptcha(req, resp);
        new MyThread(req).start();
        req.getRequestDispatcher("./register.jsp").forward(req, resp);
    }
}


public class MyThread extends Thread{
        
        private HttpServletRequest req;

        public MyThread(HttpServletRequest req) {
            this.req = req;
        }

        @Override
        public void run() {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            req.getSession().removeAttribute("captcha");
        }
    }

标签: javatomcat

解决方案


HttpServletRequest对象仅在service您的 servlet(调用该doGet方法)的方法内有效。请参阅Servlet 规范的第 3.13 节:

开发人员必须意识到,startAsync不建议维护对未在上述范围之外调用的请求对象的引用,因为它可能会产生不确定的结果。

大多数 servlet 容器回收请求对象。这就是为什么该getSession()方法为您提供null. (几乎)您从 a 获得的所有对象HttpServletRequest都具有相同的寿命,因此传递对该HttpSession对象的引用也不是解决方案。

我猜您的最终目的是限制未解决验证码的会话数量。为此,您可以致电:

req.getSession().setMaxInactiveInterval(60);

在您的doGet方法中并在验证码求解器中恢复更高的值。这样,在 60 秒内未解决验证码的所有会话都将被删除。


推荐阅读