控制器參數(shù)(Parameter)

2018-12-24 22:46 更新

WebMVC模塊不但讓編寫控制器變得非常簡單,處理請(qǐng)求參數(shù)也變得更加容易!WebMVC會(huì)根據(jù)控制器方法參數(shù)或類成員的注解配置,自動(dòng)轉(zhuǎn)換與方法參數(shù)或類成員對(duì)應(yīng)的數(shù)據(jù)類型,參數(shù)的綁定涉及以下注解:

基本參數(shù)注解
  • @RequestParam:綁定請(qǐng)求中的參數(shù);

  • @RequestHeader:綁定請(qǐng)求頭中的參數(shù)變量;

  • @CookieVariable:綁定Cookie中的參數(shù)變量;

上面三個(gè)注解擁有相同的參數(shù):

value:參數(shù)名稱,若未指定則默認(rèn)采用方法參數(shù)變量名;

prefix:參數(shù)名稱前綴,默認(rèn)為"";

defaultValue:指定參數(shù)的默認(rèn)值,默認(rèn)為"";

示例代碼:

    @Controller
    @RequestMapping("/demo")
    public class DemoController {

        @RequestMapping("/param")
        public IView testParam(@RequestParam String name,
                          @RequestParam(defaultValue = "18") Integer age,
                          @RequestParam(value = "name", prefix = "user") String username,
                          @RequestHeader(defaultValue = "BASIC") String authType,
                          @CookieVariable(defaultValue = "false") Boolean isLogin) {

            System.out.println("AuthType: " + authType);
            System.out.println("IsLogin: " + isLogin);
            return View.textView("Hi, " + name + ", UserName: " + username + ", Age: " + age);
        }
    }

通過瀏覽器訪問URL測試:

    http://localhost:8080/demo/param?name=webmvc&user.name=ymper

執(zhí)行結(jié)果:

    控制臺(tái)輸出:
    AuthType: BASIC
    IsLogin: false

    瀏覽器輸出:
    Hi, webmvc, UserName: ymper, Age: 18
特別的參數(shù)注解
  • @PathVariable:綁定請(qǐng)求映射中的路徑參數(shù)變量;

    value:參數(shù)名稱,若未指定則默認(rèn)采用方法參數(shù)變量名;

    示例代碼:

    @Controller
    @RequestMapping("/demo")
    public class DemoController {
    
        @RequestMapping("/path/{name}/{age}")
        public IView testPath(@PathVariable String name,
                          @PathVariable(value = "age") Integer age,
                          @RequestParam(prefix = "user") String sex) {
    
            return View.textView("Hi, " + name + ", Age: " + age + ", Sex: " + sex);
        }
    }
    

    通過瀏覽器訪問URL測試:

    http://localhost:8080/demo/path/webmvc/20?user.sex=F
    

    執(zhí)行結(jié)果:

    Hi, webmvc, Age: 20, Sex: F
    

    注意:基于路徑的參數(shù)變量必須是連續(xù)的,如:

    • 正確:/path/{name}/{age}

    • 錯(cuò)誤:/path/{name}/age/{sex}

  • @ModelBind:值對(duì)象參數(shù)綁定注解;

    prefix:綁定的參數(shù)名稱前綴,可選參數(shù),默認(rèn)為"";

    示例代碼:

    public class DemoVO {
    
        @PathVariable
        private String name;
    
        @RequestParam
        private String sex;
    
        @RequestParam(prefix = "ext")
        private Integer age;
    
        // 省略Get和Set方法
    }
    
    @Controller
    @RequestMapping("/demo")
    public class DemoController {
    
        @RequestMapping("/bind/{demo.name}")
        public IView testBind(@ModelBind(prefix = "demo") DemoVO vo) {
            String _str = "Hi, " + vo.getName() + ", Age: " + vo.getAge() + ", Sex: " + vo.getSex();
            return View.textView(_str);
        }
    }
    

    通過瀏覽器訪問URL測試:

    http://localhost:8080/demo/bind/webmvc?demo.sex=F&demo.ext.age=20
    

    執(zhí)行結(jié)果:

    Hi, webmvc, Age: 20, Sex: F
    
  • @ParameterEscape:控制器方法參數(shù)轉(zhuǎn)義注解;

    可以通過WebMVC模塊配置參數(shù)parameter_escape_order設(shè)定是在控制器方法參數(shù)執(zhí)行驗(yàn)證之前還是之后執(zhí)行參數(shù)轉(zhuǎn)義動(dòng)作,參數(shù)取值范圍為beforeafter,默認(rèn)為after即參數(shù)驗(yàn)證之后進(jìn)行轉(zhuǎn)義;

    scope:字符串參數(shù)轉(zhuǎn)義范圍,默認(rèn)為Type.EscapeScope.DEFAULT;

    • 取值范圍包括:JAVA, JS, HTML, XML, SQL, CSV, DEFAULT;
    • 默認(rèn)值DEFAULT,它完成了對(duì)SQL和HTML兩項(xiàng)轉(zhuǎn)義;

    skiped:通知父級(jí)注解當(dāng)前方法或參數(shù)的轉(zhuǎn)義操作將被忽略,默認(rèn)為false;

    processor:自定義字符串參數(shù)轉(zhuǎn)義處理器;

    • 可以通過IParameterEscapeProcessor接口實(shí)現(xiàn)自定義的轉(zhuǎn)義邏輯;
    • 默認(rèn)實(shí)現(xiàn)為DefaultParameterEscapeProcessor;

    示例代碼一:

    @Controller
    @RequestMapping("/demo")
    @ParameterEscape
    public class DemoController {
    
        @RequestMapping("/escape")
        public IView testEscape(@RequestParam String content,
                                @ParameterEscape(skiped = true) @RequestParam String desc) {
    
            System.out.println("Content: " + content);
            System.out.println("Desc: " + desc);
            return View.nullView();
        }
    }
    
    // 或者:(兩段代碼執(zhí)行結(jié)果相同)
    
    @Controller
    @RequestMapping("/demo")
    public class DemoController {
    
        @RequestMapping("/escape")
        @ParameterEscape
        public IView testEscape(@RequestParam String content,
                                @ParameterEscape(skiped = true) @RequestParam String desc) {
    
            System.out.println("Content: " + content);
            System.out.println("Desc: " + desc);
            return View.nullView();
        }
    }
    

    通過瀏覽器訪問URL測試:

    http://localhost:8080/demo/escape?content=<p>content$<br><script>alert("hello");</script></p>&desc=<script>alert("hello");</script>
    

    執(zhí)行結(jié)果:(控制臺(tái)輸出)

    Content: &lt;p&gt;content$&lt;br&gt;&lt;script&gt;alert(&quot;hello&quot;);&lt;/script&gt;&lt;/p&gt;
    Desc: <script>alert("hello");</script>
    

    示例一說明:

    • 由于控制器類被聲明了@ParameterEscape注解,代表整個(gè)控制器類中所有的請(qǐng)求參數(shù)都需要被轉(zhuǎn)義,因此參數(shù)content的內(nèi)容被成功轉(zhuǎn)義;
    • 由于參數(shù)desc聲明的@ParameterEscape注解中skiped值被設(shè)置為true,表示跳過上級(jí)設(shè)置,因此參數(shù)內(nèi)容未被轉(zhuǎn)義;

    示例代碼二:

    @Controller
    @RequestMapping("/demo")
    @ParameterEscape
    public class DemoController {
    
        @RequestMapping("/escape2")
        @ParameterEscape(skiped = true)
        public IView testEscape2(@RequestParam String content,
                                @ParameterEscape @RequestParam String desc) {
    
            System.out.println("Content: " + content);
            System.out.println("Desc: " + desc);
            return View.nullView();
        }
    }
    

    通過瀏覽器訪問URL測試:

    http://localhost:8080/demo/escape2?content=<p>content$<br><script>alert("hello");</script></p>&desc=<script>alert("hello");</script>
    

    執(zhí)行結(jié)果:(控制臺(tái)輸出)

    Content: <p>content$<br><script>alert("hello");</script></p>
    Desc: &lt;script&gt;alert(&quot;hello&quot;);&lt;/script&gt;
    

    示例二說明:

    • 雖然控制器類被聲明了@ParameterEscape注解,但控制器方法通過skiped設(shè)置跳過轉(zhuǎn)義,這表示被聲明的方法參數(shù)內(nèi)容不進(jìn)行轉(zhuǎn)義操作,因此參數(shù)content的內(nèi)容未被轉(zhuǎn)義;
    • 由于參數(shù)desc聲明了@ParameterEscape注解,表示該參數(shù)需要轉(zhuǎn)義,因此參數(shù)內(nèi)容被成功轉(zhuǎn)義;

    注意:當(dāng)控制器類和方法都聲明了@ParameterEscape注解時(shí),則類上聲明的注解將視為無效;

非單例控制器的特殊用法

單例控制器與非單例控制器的區(qū)別:

  • 單例控制器類在WebMVC模塊初始化時(shí)就已經(jīng)實(shí)例化;
  • 非單例控制器類則是在每次接收到請(qǐng)求時(shí)都將創(chuàng)建實(shí)例對(duì)象,請(qǐng)求結(jié)束后該實(shí)例對(duì)象被釋放;

基于以上描述,非單例控制器是可以通過類成員來接收請(qǐng)求參數(shù),示例代碼如下:

@Controller(singleton = false)
@RequestMapping("/demo")
public class DemoController {

    @RequestParam
    private String content;

    @RequestMapping("/sayHi")
    public IView sayHi(@RequestParam String name) {
        return View.textView("Hi, " + name + ", Content: " + content);
    }
}

通過瀏覽器訪問URL測試:

http://localhost:8080/demo/sayHi?name=YMPer&content=Welcome!

此示例代碼的執(zhí)行結(jié)果:

Hi, YMPer, Content: Welcome!

注意:在單例模式下,WebMVC模塊將忽略為控制器類成員賦值,同時(shí)也建議在單例模式下不要使用成員變量做為參數(shù),在并發(fā)多線程環(huán)境下會(huì)發(fā)生意想不到的問題??!

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)