我感到困惑的是,当我确实在请求中包含参数时,HttpServletRequest.getParameter有时会返回null。

测试程序如下:

HelloServlet.java:

public class HelloServlet extends HttpServlet {
    private static Executor logExecutor = Executors.newFixedThreadPool(5);

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        logExecutor.execute(new Task(req));
    }
}

class Task implements Runnable {
    private HttpServletRequest req;

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

    @Override
    public void run() {
        System.out.println(String.format("a=%s b=%s c=%s",
                req.getParameter("a"), req.getParameter("b"),
                req.getParameter("c")));
    }
}


将此servlet映射到web.xml中的/ hello

在tomcat或jetty中启动servlet,使用shell脚本启动请求:

#/bin/sh

for i in {1..100}
do
        curl -i -X GET "http://localhost:8080/hello?a=a&b=b&c=c"
done


服务器日志显示某些请求中的某些参数可能为空,并且这种情况是在没有常规模式的情况下发生的。如:

a=a b=b c=c
a=a b=b c=c
a=null b=null c=null
a=null b=null c=null
a=null b=null c=null
a=null b=b c=c
a=null b=null c=c
a=a b=b c=c
a=a b=b c=c
a=a b=b c=c
a=a b=b c=c
a=null b=null c=null
a=a b=b c=c
a=null b=b c=c


我发现原因是我无法为我的执行器保存HttpServletRequest实例。
所以我想知道原因!为什么我在一个请求中持有HttpServletRequest实例的操作可能会影响其他请求。

最佳答案

据我所知,我认为一旦完成请求请求参数就无法访问。

您正在将HttpServletRequest传递给Thread。有时,它会在请求完成之前执行,有时会在请求执行之后执行。因此,有时您会得到参数,有时它们是null

避免在HttpServletRequestdoGet之外处理doPost。您应该将信息从原始请求复制到单独的数据结构中,以供以后处理。

例如:

public class HelloServlet extends HttpServlet {
    private static Executor logExecutor = Executors.newFixedThreadPool(5);

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        String data = String.format("a=%s b=%s c=%s",
                req.getParameter("a"), req.getParameter("b"),
                req.getParameter("c"));
        logExecutor.execute(new Task(data));
    }
}

class Task implements Runnable {
    private String data;

    public Task(String data) {
        this.data = data;
    }

    @Override
    public void run() {
        System.out.println(data);
    }
}


编辑:

Java Servlet Specification中摘录:


  3.11请求对象的生存期
  
  每个请求对象仅在servlet的服务方法范围内或在过滤器的doFilter方法范围内有效,
  除非为组件启用了异步处理,否则
  在请求对象上调用startAsync方法。在这种情况下
  在发生异步处理的地方,请求对象仍然有效
  直到在AsyncContext上调用complete为止。普通容器
  回收请求对象以避免性能开销
  请求创建对象。开发人员必须意识到
  维护对startAsync还没有的请求对象的引用
  不建议在上述范围之外调用它,因为它
  可能会有不确定的结果。

关于java - HttpServletRequest.getParameter丢失参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27290524/

10-11 18:50