We have seen that when working with controllers, Spring automatically gives us access to the HttpServletRequest object. But what if we are in some utility class and would like to access the request ? For this Spring includes the ServletRequestAttributes class.
Consider the below method that I called from a controller instance:
Consider the below method that I called from a controller instance:
public void test() { final ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder .currentRequestAttributes(); final HttpServletRequest request = attr.getRequest(); System.out.println("Request object is " + request); } @RequestMapping(method = RequestMethod.POST, value = "test.do") public @ResponseBody Status test(final HttpServletRequest request) { System.out.println("Request object is " + request); this.test(); //..other code }The output is :
Request object is org.apache.catalina.connector.RequestFacade@b0cf230 Request object is org.apache.catalina.connector.RequestFacade@b0cf230As can be seen both statements indicate the same request object. This works becauce Spring binds the request object to the executing thread. So what if I changed threads ?
@RequestMapping(method = RequestMethod.POST, value = "login.srvc") public @ResponseBody Status signIn(final HttpServletRequest request) { System.out.println("Request object is " + request); new Thread() { @Override public void run() { UserAccountController.this.test(); }; }.start(); }The output indicates that the code still worked:
Request object is org.apache.catalina.connector.RequestFacade@7cf7e9dd Request object is org.apache.catalina.connector.RequestFacade@7cf7e9ddI looked in the code of DispatcherServlet. Actually I went up the hierarchy to FrameworkServlet:
protected final void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long startTime = System.currentTimeMillis(); Throwable failureCause = null; // Expose current LocaleResolver and request as LocaleContext. LocaleContext previousLocaleContext = LocaleContextHolder. getLocaleContext(); LocaleContextHolder.setLocaleContext(buildLocaleContext(request), this.threadContextInheritable); // Expose current RequestAttributes to current thread. RequestAttributes previousRequestAttributes = RequestContextHolder. getRequestAttributes(); ServletRequestAttributes requestAttributes = null; if (previousRequestAttributes == null || previousRequestAttributes.getClass().equals( ServletRequestAttributes.class)) { requestAttributes = new ServletRequestAttributes(request); RequestContextHolder.setRequestAttributes(requestAttributes, this.threadContextInheritable); } if (logger.isTraceEnabled()) { logger.trace("Bound request context to thread: " + request); } try { doService(request, response); } //remaining codeAs can be seen the RequestContextHolder class uses a ThreadLocal instance to hold the ServletRequestAttributes instance. The ServletRequestAttributes class includes the ServletRequest among other members:
public class ServletRequestAttributes extends AbstractRequestAttributes { private final HttpServletRequest request; private volatile HttpSession session; private final Map<String, Object> sessionAttributesToUpdate = new HashMap<String, Object>(); //other code }
No comments:
Post a Comment