SpringMvc中獲取Request

Controller中加參數

複製代碼
@Controller
public class TestController {
    @RequestMapping("/test")
    public void test(HttpServletRequest request) {
        ......
    }
}
複製代碼

Controller中獲取request對象後,若是要在其餘方法中(如service方法、工具類方法等)使用request對象,須要在調用這些方法時將request對象做爲參數傳入java

此時request對象是方法參數,至關於局部變量,毫無疑問是線程安全的。 安全

自動注入

複製代碼
@Controller
public class TestController{
     
    @Autowired
    private HttpServletRequest request; //自動注入request
     
    @RequestMapping("/test")
    public void test() throws InterruptedException{
        ......
    }
}
複製代碼

使用這種方式,當Bean(本例的TestController)初始化時,Spring並無注入一個request對象,而是注入了一個代理(proxy);當Bean中須要使用request對象時,經過該代理獲取request對象。request其實是一個代理:代理的實現參見AutowireUtils的內部類ObjectFactoryDelegatingInvocationHandler。app

調用request的方法method時,其實是調用了由objectFactory.getObject()生成的對象的method方法;objectFactory.getObject()生成的對象纔是真正的request對象。工具

objectFactory的類型爲WebApplicationContextUtils的內部類RequestObjectFactory;而RequestObjectFactory要得到request對象須要先調用currentRequestAttributes()方法得到RequestAttributes對象,生成RequestAttributes對象的核心代碼在類RequestContextHolder中,生成的RequestAttributes對象是線程局部變量(ThreadLocal),所以request對象也是線程局部變量;這就保證了request對象的線程安全性。this

基類中自動注入

複製代碼
public class BaseController {
    @Autowired
    protected HttpServletRequest request;     
}
@Controller
public class TestController extends BaseController {
}
複製代碼

與方法2相比,避免了在不一樣的Controller中重複注入request;可是考慮到java只容許繼承一個基類,因此若是Controller須要繼承其餘類時,該方法便再也不好用。spa

手動調用

複製代碼
@Controller
public class TestController {
    @RequestMapping("/test")
    public void test() throws InterruptedException {
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
            .......
    }
}
複製代碼

經過自動注入實現與經過手動方法調用實現原理差很少。所以本方法也是線程安全的。線程

優勢:能夠在非Bean中直接獲取。缺點:若是使用的地方較多,代碼很是繁瑣;所以能夠與其餘方法配合使用。代理

@ModelAttribute方法

複製代碼
@Controller
public class TestController {
    private HttpServletRequest request; 此處線程不安全
    @ModelAttribute
    public void bindRequest(HttpServletRequest request) {
        this.request = request;  此處request線程安全
    }
    @RequestMapping("/test")
    public void test() throws InterruptedException {
        ......
    }
}
複製代碼

@ModelAttribute註解用在Controller中修飾方法時,其做用是Controller中的每一個@RequestMapping方法執行前,該方法都會執行。bindRequest()的做用是在test()執行前爲request對象賦值。雖然bindRequest()中的參數request自己是線程安全的,但因爲TestController是單例的,request做爲TestController的一個域,沒法保證線程安全。code

相關文章
相關標籤/搜索