1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Spring 中獲取 request 的幾種方法及其線程安全性分析

        共 3676字,需瀏覽 8分鐘

         ·

        2021-08-11 03:05

        0x01: 概述

        在使用Spring MVC開發(fā)Web系統(tǒng)時(shí),經(jīng)常需要在處理請(qǐng)求時(shí)使用request對(duì)象,比如獲取客戶端ip地址、請(qǐng)求的url、header中的屬性(如cookie、授權(quán)信息)、body中的數(shù)據(jù)等。由于在Spring MVC中,處理請(qǐng)求的Controller、Service等對(duì)象都是單例的,因此獲取request對(duì)象時(shí)最需要注意的問題,便是request對(duì)象是否是線程安全的:當(dāng)有大量并發(fā)請(qǐng)求時(shí),能否保證不同請(qǐng)求/線程中使用不同的request對(duì)象。

        這里還有一個(gè)問題需要注意:前面所說(shuō)的“在處理請(qǐng)求時(shí)”使用request對(duì)象,究竟是在哪里使用呢?考慮到獲取request對(duì)象的方法有微小的不同,大體可以分為兩類:

        1) 在Spring的Bean中使用request對(duì)象:既包括Controller、Service、Repository等MVC的Bean,也包括了Component等普通的Spring Bean。為了方便說(shuō)明,后文中Spring中的Bean一律簡(jiǎn)稱為Bean。

        2) 在非Bean中使用request對(duì)象:如普通的Java對(duì)象的方法中使用,或在類的靜態(tài)方法中使用。

        此外,本文討論是圍繞代表請(qǐng)求的request對(duì)象展開的,但所用方法同樣適用于response對(duì)象、InputStream/Reader、OutputStream/ Writer等;其中InputStream/Reader可以讀取請(qǐng)求中的數(shù)據(jù),OutputStream/ Writer可以向響應(yīng)寫入數(shù)據(jù)。

        0x02:Controller方法中加參數(shù)

        代碼示例

        這種方法實(shí)現(xiàn)最簡(jiǎn)單,直接上Controller代碼:

        @Controller
        public class TestController {
        @RequestMapping("/test")
        public void test(HttpServletRequest request) throws InterruptedException {
        // 模擬程序執(zhí)行了一段時(shí)間
        Thread.sleep(1000);
        }
        }

        該方法實(shí)現(xiàn)的原理是,在Controller方法開始處理請(qǐng)求時(shí),Spring會(huì)將request對(duì)象賦值到方法參數(shù)中。除了request對(duì)象,可以通過這種方法獲取的參數(shù)還有很多,

        線程安全性

        測(cè)試結(jié)果:線程安全

        分析:此時(shí)request對(duì)象是方法參數(shù),相當(dāng)于局部變量,毫無(wú)疑問是線程安全的。

        優(yōu)缺點(diǎn)

        這種方法的主要缺點(diǎn)是request對(duì)象寫起來(lái)冗余太多,主要體現(xiàn)在兩點(diǎn):

        1) 如果多個(gè)controller方法中都需要request對(duì)象,那么在每個(gè)方法中都需要添加一遍request參數(shù)

        2) request對(duì)象的獲取只能從controller開始,如果使用request對(duì)象的地方在函數(shù)調(diào)用層級(jí)比較深的地方,那么整個(gè)調(diào)用鏈上的所有方法都需要添加request參數(shù)

        實(shí)際上,在整個(gè)請(qǐng)求處理的過程中,request對(duì)象是貫穿始終的;也就是說(shuō),除了定時(shí)器等特殊情況,request對(duì)象相當(dāng)于線程內(nèi)部的一個(gè)全局變量。而該方法,相當(dāng)于將這個(gè)全局變量,傳來(lái)傳去。

        0x03:自動(dòng)注入

        代碼示例

        @Controller
        public class TestController{

        @Autowired
        private HttpServletRequest request; //自動(dòng)注入request

        @RequestMapping("/test")
        public void test() throws InterruptedException{
        //模擬程序執(zhí)行了一段時(shí)間
        Thread.sleep(1000);
        }
        }

        線程安全性

        測(cè)試結(jié)果:線程安全

        分析:在Spring中,Controller的scope是singleton(單例),也就是說(shuō)在整個(gè)web系統(tǒng)中,只有一個(gè)TestController;但是其中注入的request卻是線程安全的,原因在于:使用這種方式,當(dāng)Bean(本例的TestController)初始化時(shí),Spring并沒有注入一個(gè)request對(duì)象,而是注入了一個(gè)代理(proxy);當(dāng)Bean中需要使用request對(duì)象時(shí),通過該代理獲取request對(duì)象。

        代理對(duì)象中用到了 ThreadLocal , 因此request對(duì)象也是線程局部變量;這就保證了request對(duì)象的線程安全性。

        優(yōu)缺點(diǎn)

        該方法的主要優(yōu)點(diǎn):

        1) 注入不局限于Controller中:在方法1中,只能在Controller中加入request參數(shù)。而對(duì)于方法2,不僅可以在Controller中注入,還可以在任何Bean中注入,包括Service、Repository及普通的Bean。

        2) 注入的對(duì)象不限于request:除了注入request對(duì)象,該方法還可以注入其他scope為request或session的對(duì)象,如response對(duì)象、session對(duì)象等;并保證線程安全。

        3) 減少代碼冗余:只需要在需要request對(duì)象的Bean中注入request對(duì)象,便可以在該Bean的各個(gè)方法中使用,與方法1相比大大減少了代碼冗余。

        但是,該方法也會(huì)存在代碼冗余??紤]這樣的場(chǎng)景:web系統(tǒng)中有很多controller,每個(gè)controller中都會(huì)使用request對(duì)象(這種場(chǎng)景實(shí)際上非常頻繁),這時(shí)就需要寫很多次注入request的代碼;如果還需要注入response,代碼就更繁瑣了。下面說(shuō)明自動(dòng)注入方法的改進(jìn)方法,并分析其線程安全性及優(yōu)缺點(diǎn)。

        0x04:基類中自動(dòng)注入

        代碼示例

        基類代碼:

        public class BaseController {
        @Autowired
        protected HttpServletRequest request;
        }

        線程安全性

        測(cè)試結(jié)果:線程安全

        分析:在理解了方法2的線程安全性的基礎(chǔ)上,很容易理解方法3是線程安全的:當(dāng)創(chuàng)建不同的派生類對(duì)象時(shí),基類中的域(這里是注入的request)在不同的派生類對(duì)象中會(huì)占據(jù)不同的內(nèi)存空間,也就是說(shuō)將注入request的代碼放在基類中對(duì)線程安全性沒有任何影響;測(cè)試結(jié)果也證明了這一點(diǎn)。

        優(yōu)缺點(diǎn)

        與方法2相比,避免了在不同的Controller中重復(fù)注入request;但是考慮到j(luò)ava只允許繼承一個(gè)基類,所以如果Controller需要繼承其他類時(shí),該方法便不再好用。

        無(wú)論是方法2和方法3,都只能在Bean中注入request;如果其他方法(如工具類中static方法)需要使用request對(duì)象,則需要在調(diào)用這些方法時(shí)將request參數(shù)傳遞進(jìn)去。下面介紹的方法4,則可以直接在諸如工具類中的static方法中使用request對(duì)象(當(dāng)然在各種Bean中也可以使用)。

        0x05:手動(dòng)調(diào)用

        代碼示例

        @Controller
        public class TestController {
        @RequestMapping("/test")
        public void test() throws InterruptedException {
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        // 模擬程序執(zhí)行了一段時(shí)間
        Thread.sleep(1000);
        }
        }

        線程安全性

        測(cè)試結(jié)果:線程安全

        分析:該方法與方法2(自動(dòng)注入)類似,只不過方法2中通過自動(dòng)注入實(shí)現(xiàn),本方法通過手動(dòng)方法調(diào)用實(shí)現(xiàn)。因此本方法也是線程安全的。

        優(yōu)缺點(diǎn)

        優(yōu)點(diǎn):可以在非Bean中直接獲取。缺點(diǎn):如果使用的地方較多,代碼非常繁瑣;因此可以與其他方法配合使用。

        0x06:總結(jié)

        綜上所述,Controller中加參數(shù)(方法1)、自動(dòng)注入(方法2和方法3)、手動(dòng)調(diào)用(方法4)都是線程安全的,都可以用來(lái)獲取request對(duì)象。如果系統(tǒng)中request對(duì)象使用較少,則使用哪種方式均可;如果使用較多,建議使用自動(dòng)注入(方法2 和方法3)來(lái)減少代碼冗余。如果需要在非Bean中使用request對(duì)象,既可以在上層調(diào)用時(shí)通過參數(shù)傳入,也可以直接在方法中通過手動(dòng)調(diào)用(方法4)獲得。

        source:http://www.cnblogs.com/kismetv/p/8757260.html

        喜歡,在看

        瀏覽 23
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            蜜穴视频 | 老司机精品免费视频 | 黑人大鷄巴一級 | 婷婷亚洲婷婷综合色香五月 | 92久久久 | 欧美熟妇精品一区 | 第一色影院 | 国产操逼无码视频 | 韩国久久精品 | 国产精品自拍自视频图片小说 |