2014-12-04 49 views
0

我很困惑,HttpServletRequest.getParameter有时会返回null,而我真的在请求中包含参数。HttpServletRequest.getParameter丢失参数

测试下面的程序:

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

开始在Tomcat或码头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实例的操作可能会影响其他请求。

回答

1

就我所知,我认为一旦它完成后就无法访问请求参数。您正在将HttpServletRequest传递给Thread。有时它会在请求完成之前执行,有时会在稍后执行。因此,有时你会得到参数,有时它们是null

避免处理HttpServletRequest外部doGetdoPost。您应该将原始请求中的信息复制到一个单独的数据结构中供以后处理。

例如:

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。请求对象

每个请求对象是有效的只有一个servlet的服务的方法的范围内,或一个过滤器的doFilter方法, 的范围之内,除非所述异步处理的组分和 启用的11寿命在请求对象上调用startAsync方法。在 发生异步处理的情况下,请求对象保持有效 ,直到在AsyncContext上调用完成为止。 容器通常为 回收请求对象,以避免 请求对象创建的性能开销。显影剂必须意识到 维持引用,以请求其startAsync未 被称为上述的范围外的对象不推荐,因为它 可以具有不确定的结果。

+0

我很好奇为什么一个HttpServletRequest的实例的值可以由其他请求的影响。 – terry 2014-12-05 07:38:46

+0

我并不是说HttpServletRequest可能会受到另一个的影响。但是一旦请求完成(响应发送给客户端),应用程序服务器(tomcat,jetty ...)就可以清除它的数据。 – 2014-12-05 08:22:16

0

的问题是,你重新声明变量reqTask类在这里:

private HttpServletRequest req; 
  • 所以在这里你req变量甚至没有初始化,并没有任何 做这个servlet请求。

  • 此外,我不能看到你在哪里设置这些参数的请求,所以你在哪里设置参数a,b and c到请求或req变量?