2014-12-04 221 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變量?