SpringMvc中獲取Request
目錄
● Controller中加引數
● 自動注入
● 基類中自動注入
● 手動呼叫
● @ModelAttribute方法
Controller中加引數
Controller中獲取request物件後,如果要在其他方法中(如service方法、工具類方法等)使用request物件,需要在呼叫這些方法時將request物件作為引數傳入
此時request物件是方法引數,相當於區域性變數,毫無疑問是執行緒安全的。
自動注入
使用這種方式,當Bean(本例的TestController)初始化時,Spring並沒有注入一個request物件,而是注入了一個代理(proxy);當Bean中需要使用request物件時,通過該代理獲取request物件。request實際上是一個代理:代理的實現參見AutowireUtils的內部類ObjectFactoryDelegatingInvocationHandler。
呼叫request的方法method時,實際上是呼叫了由objectFactory.getObject()生成的物件的method方法;objectFactory.getObject()生成的物件才是真正的request物件。
objectFactory的型別為WebApplicationContextUtils的內部類RequestObjectFactory;而RequestObjectFactory要獲得request物件需要先呼叫currentRequestAttributes()方法獲得RequestAttributes物件,生成RequestAttributes物件的核心程式碼在類RequestContextHolder中,生成的RequestAttributes物件是執行緒區域性變數(ThreadLocal),因此request物件也是執行緒區域性變數;這就保證了request物件的執行緒安全性。
基類中自動注入
與方法2相比,避免了在不同的Controller中重複注入request;但是考慮到java只允許繼承一個基類,所以如果Controller需要繼承其他類時,該方法便不再好用。
手動呼叫
通過自動注入實現與通過手動方法呼叫實現原理差不多。因此本方法也是執行緒安全的。
優點:可以在非Bean中直接獲取。缺點:如果使用的地方較多,程式碼非常繁瑣;因此可以與其他方法配合使用。
@ModelAttribute方法
@ModelAttribute註解用在Controller中修飾方法時,其作用是Controller中的每個@RequestMapping方法執行前,該方法都會執行。bindRequest()的作用是在test()執行前為request物件賦值。雖然bindRequest()中的引數request本身是執行緒安全的,但由於TestController是單例的,request作為TestController的一個域,無法保證執行緒安全。
原文釋出時間為:2018-11-16