2014-12-04 3 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"))); 
    } 
} 

지도 web.xml을

시작 톰캣이나 부두에서 서블릿에서이 서블릿/안녕하세요이와 요청을 시작합니다 쉘 스크립트 :

#/bin/sh 

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

서버 로그에 다음과 같은 몇 가지 매개 변수가 있습니다. 일부 요청은 아마도 null이 될 수 있으며이 경우는 규칙적인 패턴없이 발생합니다. 예 :

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 

이유는 내 Executor에 대해 HttpServletRequest 인스턴스를 보유 할 수 없다는 것입니다. 그래서 이유를 알고 싶습니다! 하나의 요청에서 HttpServletRequest 인스턴스를 보유하는 동작이 다른 요청에 영향을 미칠 수있는 이유는 무엇입니까?

답변

1

필자가 아는 한, 요청 매개 변수가 끝나면 액세스 할 수 없다고 생각합니다.

HttpServletRequestThread으로 전달 중입니다. 때로는 요청이 완료되기 전에 실행되고 때로는 나중에 실행됩니다. 따라서 때로 매개 변수를 가져오고 때로는 null입니다.

doGet 또는 doPost 외부의 HttpServletRequest을 피하십시오. 나중에 처리하기 위해 원본 요청의 정보를 별도의 데이터 구조로 복사해야합니다. 예를 들어

:

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); 
    } 
} 

EDIT : Java Servlet Specification에서

추출물 :

3.요청 객체

각 요청 개체 만 서블릿의 서비스 방법의 범위 내에서 유효 또는 필터의 doFilter 방법, 의 범위 내에서 비동기 처리 컴포넌트 및 활성화되지 않는 11 일생 요청 개체에서 startAsync 메서드가 호출됩니다. 비동기 처리가 발생하는 의 경우에는 AsyncContext에서 complete가 호출 될 때까지 요청 개체가 유효한 으로 유지됩니다. 컨테이너는 일반적으로 요청 개체를 재생하여 성능 오버 헤드를 피하기 위해 요청 개체를 생성합니다. 개발자는 에서 startAsync가 0이 아닌 요청 개체에 대한 참조를 유지하는 경우 에 불확정 결과가있을 수 있으므로 위의 설명 범위 밖에서 이 호출되지 않은 것이 좋습니다.

+0

궁금한데 HttpServletRequest 인스턴스의 값이 다른 요청의 영향을받을 수있는 이유는 무엇입니까? – terry

+0

HttpServletRequest가 다른 HttpServletRequest에 영향을받을 수 있다고 말하는 것은 아닙니다. 그러나 요청이 완료되면 (응답이 클라이언트에 전송 됨) 응용 프로그램 서버 (tomcat, jetty ...)가 데이터를 지울 수 있습니다. –

0

문제는 당신이 여기 Task 클래스의 변수 req를 재 선언하는 것입니다 :

private HttpServletRequest req; 
  • 그래서 여기 req 변수도 초기화되지 않고, 그 서블릿과는 아무런 이 없습니다 의뢰.

  • 또한 요청에 대한 매개 변수 설정 위치를 볼 수 없으므로 요청 또는 req 변수에 대해 a,b and c 매개 변수를 어디에 설정 했습니까?

관련 문제