设置属性时是否出现NullPointerException?

xyb*_*rek 8 java jsp servlets

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

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

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

这是我得到的堆栈跟踪:

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)
Run Code Online (Sandbox Code Playgroud)

Bal*_*usC 10

rd.forward(this.request, this.response);
Run Code Online (Sandbox Code Playgroud)

这(双关语intented)建议您分配requestresponse作为一个类的实例变量.反过来,您的具体问题表明类本身的实例不是线程安全的.

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

永远不应将请求或会话范围数据分配为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.
    } 
}
Run Code Online (Sandbox Code Playgroud)

将HTTP请求本身分配为servlet的实例变量实际上是一个史诗般的错误.当用户Y在触发该servlet在处理用户X的请求,同时另一个请求,那么用户X会立即得到requestresponse用户Y的对象在手中.这绝对是线程安全的.导致NPE是因为当时request正在"完成"处理用户Y并因此释放/销毁.

也可以看看: