在寫springMVC的Control中有不少這種代碼, 如須要獲取request對象去作某些事情java
如:spring
@Controller @RequestMapping(value = "/user") public class LoanActionPage extends AbstractAction { @RequestMapping(value = "/page/active") public String loanAaccountActivePage(HttpServletRequest request) { // get request to dosomething String pathInfo = request.getPathInfo(); return "active"; } }
貌似每次要寫個control時都得把request當住參數來傳,非常冗餘。安全
其實能夠在control裏定義一個request對象,注入,而後隨時用多線程
如:app
public class AbstractAction { @Autowired protected HttpServletRequest request; ... ...
而後在control中直接用:spa
@Controller @RequestMapping(value = "/user") public class LoanActionPage extends AbstractAction { @RequestMapping(value = "/page/active") public String loanAaccountActivePage() { // get request to dosomething String pathInfo = request.getPathInfo(); return "active"; } }
那麼問題來了,sevlet是多線程的,每次請求的request實際上是個新的對象,這樣直接共享引用,是否會形成線程不安全呢?線程
方便了,問題也來了,servelt實際上是多線程,共享一個request是否會有安全問題呢,分析下spring的代碼code
發現是注入實際上是往WebApplicationContextUtils經過RequestObjectFactory拿值,跟蹤對象
返回的是RequestContextHolder裏的值. 追蹤RequestContextHolderget
每次返回的實際上是, RequestAttributes的實現類ServletWebRequest(ServletRequestAttributes)裏的request. 由於RequestAttributes是屬於threadLocal的,因此注入的request也是線程安全的了
HttpServlet實現類 FrameworkServlet-> service()->processRequst()
每次請求都會往裏面設置最新的request, 設值