java - 设置属性时出现 NullPointerException?

标签 java jsp servlets

例如,我有一个将属性设置为 HttpServletRequest 的 servlet 代码:

request.setAttribute("someValue", someValue());
        RequestDispatcher rd = getServletContext().getRequestDispatcher("/SomeJsp.jsp");
        rd.forward(this.request, this.response);
        return;

如何确保上面的代码是线程安全的?

这是我得到的堆栈跟踪:

java.lang.NullPointerException
    at org.apache.catalina.connector.Request.notifyAttributeAssigned(Request.java:1552)
    at org.apache.catalina.connector.Request.access$000(Request.java:105)
    at org.apache.catalina.connector.Request$3.set(Request.java:3342)
    at org.apache.catalina.connector.Request.setAttribute(Request.java:1504)
    at org.apache.catalina.connector.RequestFacade.setAttribute(RequestFacade.java:541)
    at org.apache.catalina.core.ApplicationHttpRequest.setAttribute(ApplicationHttpRequest.java:281)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:286)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:684)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:471)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:402)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:329)
    at com.mycompany.myapp.servlet.SomeServlet.doRequest(SomeServlet.java:103)
    at com.mycompany.myapp.servlet.SomeServlet.doGet(SomeServlet.java:159)

最佳答案

rd.forward(this.request, this.response);

这(双关语)表明您已将 requestresponse 指定为类的实例变量。您的具体问题反过来表明该类的实例本身不是线程安全的。

假设它实际上是 servlet 本身,那么您就找到了问题的原因。 Servlet 根本不是线程安全的。它只有一个实例是在 webapp 启动期间创建的,然后在应用程序范围内的所有请求之间共享。

您应该永远不要将请求或 session 范围内的数据分配为 servlet 的实例变量。只有在同一时刻发生另一个 HTTP 请求时,它才会被覆盖。正如您自己遇到的那样,这会使您的代码线程不安全。

下面是一些说明这一点的代码:

public class MyServlet extends HttpServlet {

    private Object thisIsNOTThreadSafe;

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        Object thisIsThreadSafe;

        thisIsNOTThreadSafe = request.getParameter("foo"); // BAD!! Shared among all requests!
        thisIsThreadSafe = request.getParameter("foo"); // OK, this is thread safe.
    } 
}

将 HTTP 请求本身指定为 servlet 的实例变量实际上是一个史诗般的错误。当用户 Y 在 servlet 正在处理用户 X 的请求的同时发出另一个请求时,用户 X 将立即获得用户 Y 的 requestresponse 对象手。这绝对是线程不安全的。 NPE 的产生是因为 request 在那一刻“完成”了对用户 Y 的处理,因此被释放/销毁。

另见:

关于java - 设置属性时出现 NullPointerException?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13971099/

相关文章:

javascript - jquery .load() 和 IE

c# - 从 C# 向 Java 应用程序 (Minecraft) 发送输入

java - Jsoup 将我的 javascript 字符串转换为一行

java - 如何在Servlet中插入JSP功能?

java - 打开jsp时servlet出错

java - Spring组件中如何访问HttpServletResponse?

java - 使用 Commons Net FTPSClient 连接到 FTP 服务器时出现 "Remote host closed connection during handshake"

java - 我应该使用什么数据库管理器

html - 如何在jsp中显示带有标签的文本

java - 过滤器被 Tomcat 容器多次调用