• Spring MVC 使用介绍(六)—— 注解式控制器(二):请求映射与参数绑定


    一、概述

        

    注解式控制器支持:

    • 请求的映射和限定
    • 参数的自动绑定
    • 参数的注解绑定

    二、请求的映射和限定

    http请求信息包含六部分信息:

    ①请求方法;
    ②URL;
    ③协议及版本;
    ④请求头信息(包括Cookie信息);
    ⑤回车换行(CRLF);
    ⑥请求内容区;

    其中,①、②、④、⑥一般是可变的,可根据这些信息对处理方法进行映射,具体分为:

    • URL路径映射:使用URL映射请求到处理器的功能处理方法
    • 请求方法映射限定:如限定功能处理方法只处理GET请求
    • 请求参数映射限定:如限定只处理包含“abc”请求参数的请求
    • 请求头映射限定:如限定只处理“Accept=application/json”的请求

    1、URL路径映射

    i)普通URL路径映射

    @RequestMapping(value="/user/create")
    @RequestMapping(value={"/test1", "/user/create"})

    ii)URI模板模式映射,可通过@PathVariable提取模板变量

    @RequestMapping(value="/users/{userId}"):请求的URL可以是 “/users/123456”或“/users/abcd”
    @RequestMapping(value="/users/{userId}/create"):请求的URL可以是“/users/123/create”。
    @RequestMapping(value="/users/{userId}/topics/{topicId}"):请求的URL可以是“/users/123/topics/123”

    iii)Ant风格的URL路径映射(最长匹配优先)

    @RequestMapping(value="/users/**"):可以匹配“/users/abc/abc”,但“/users/123”将会被URI模板模式映射中的“/users/{userId}”模式优先映射到
    @RequestMapping(value="/product?"):可匹配“/product1”或“/producta”,但不匹配“/product”或“/productaa”
    @RequestMapping(value="/product*"):可匹配“/productabc”或“/product”,但不匹配“/productabc/abc”
    @RequestMapping(value="/product/*"):可匹配“/product/abc”,但不匹配“/productabc”
    @RequestMapping(value="/products/**/{productId}"):可匹配“/products/abc/abc/123”或“/products/123”,也就是Ant风格和URI模板变量风格可混用

    iv)正则表达式风格的URL路径映射,可通过@PathVariable提取模板变量

    @RequestMapping(value="/products/{categoryCode:\d+}-{pageNumber:\d+}"):格式为{变量名:正则表达式},可以匹配“/products/123-1”,但不能匹配“/products/abc-1”

    2、请求方法映射限定

    @RequestMapping(value="/hello", method = RequestMethod.POST)
    @RequestMapping(value="/hello", method = {RequestMethod.POST, RequestMethod.GET})

    DispatcherServlet默认开启对 GET、POST、PUT、DELETE、HEAD的支持

    3、请求参数映射限定

    @RequestMapping(value = "/hello", params = "create"):表示请求中有“create”的参数名即可匹配,如可匹配的请求URL“http://×××/parameter1?create”
    @RequestMapping(value = "/hello", params = "!create"):表示请求中没有“create”参数名即可匹配
    @RequestMapping(value = "/hello", params = "submitFlag=create"):表示请求中有“submitFlag=create”请求参数即可匹配
    @RequestMapping(value = "/hello", params = "submitFlag!=create"):表示请求中有submitFlag但不等于create即可匹配
    @RequestMapping(value = "/hello", params = {"test1", "test2=create"}):表示请求中的有“test1”参数名 且 有“test2=create”参数即可匹配

    4、请求头映射限定

    @RequestMapping(value="/hello", headers = "Accept"):表示请求的URL必须为“/hello”且请求头中必须有Accept参数才能匹配
    @RequestMapping(value="/hello", headers = "!abc"):表示请求的URL必须为“/hello”且请求头中必须没有abc参数才能匹配
    @RequestMapping(value="/hello", headers = "Content-Type=application/json"):表示请求的URL必须为“/hello”且请求头中必须有“Content-Type=application/json”参数才能匹配
    @RequestMapping(value="/hello", headers = "Accept!=text/vnd.wap.wml"):表示请求的URL必须为“/hello”且请求头中必须有Accept但不等于“text/vnd.wap.wml”才能匹配
    @RequestMapping(value="/hello", headers = {"Accept!=text/vnd.wap.wml","abc=123"}):表示请求的URL必须为“/hello”且请求头中必须有Accept但不等于“text/vnd.wap.wml”且请求中必须有参数“abc=123”才能匹配

    三、参数的自动绑定

    当功能方法参数列表中包含特定类型的参数时,Spring Web MVC框架会自动帮助我们把相应的参数传递过来,如HttpServletRequest 或HttpServletResponse,从而可以获取输入参数或输出数据,但使用不方便,推荐使用注解方式

    1、HttpServletRequest 和HttpServletResponse

    public String requestOrResponse (HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { ... }

    2、InputStream/OutputStream 和 Reader/Writer

    public void inputOrOutBody(InputStream requestBodyIn, OutputStream responseBodyOut) throws IOException {  
        responseBodyOut.write("success".getBytes());  
    }  
    
    public void readerOrWriteBody(Reader reader, Writer writer) throws IOException {  
        writer.write("hello");  
    }  

    InputStream、OutputStream:等价于request.getInputStream()与response.getOutputStream()

    Reader、Writer:等价于request.getReader()与response.getWriter()

    3、HttpSession 

    public String session(HttpSession session) {  
        System.out.println(session);  
        return "success";  
    }

    4、Model、Map、ModelMap

    三者继承关系

                         

    @RequestMapping(value = "/model")  
    public void createUser(Model model, Map model2, ModelMap model3) {  
        System.out.println(model == model2);  
        System.out.println(model2 == model3); 
        System.out.println(model.getClass().getName());
    }  

    输出:

    true
    true
    org.springframework.validation.support.BindingAwareModelMap

    5、命令/表单对象

    public class UserInfo {
        private String name;
        private Integer age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    }
    @RestController
    public class TestController {
        @RequestMapping(value = "/hello2")
        public String helloWorld2(HttpServletRequest request, UserInfo userInfo) {
            System.out.println(userInfo.getName());
            return "选择比努力更重要!";
        }
    }

    启动后,访问http://localhost:8080/myweb/hello2?name=matt&age=29

    四、参数的注解绑定

    参数的注解绑定是指通过注解方式实现功能方法参数的自动赋值,具体如下:

    1、@RequestParam  绑定单个请求参数值
    2、@PathVariable   绑定URI模板变量值
    3、@CookieValue   绑定Cookie数据值
    4、@RequestHeader  绑定请求头数据
    5、@ModelAttribute  绑定请求参数到命令对象
    6、@SessionAttributes  绑定命令对象到session
    7、@Value  绑定SpEL表示式
    8、@RequestBody  绑定请求内容数据

    1、@RequestParam

    @RequestParam注解有三个参数:

    • value:参数名字,即入参的请求参数名字,如username表示请求的参数区中的名字为username的参数的值将传入
    • required:是否必须,默认是true,表示请求中一定要有相应的参数,否则将报400错误码
    • defaultValue:默认值,表示如果请求中没有同名参数时的默认值,默认值可以是SpEL表达式,如“#{systemProperties['java.vm.version']}”

    使用示例

    @RestController
    public class TestController2 {
        @RequestMapping(value="/test1")
        public String test1(@RequestParam("name") String username) {
            return username;
        }
        
        @RequestMapping(value="/test2")
        public String test2(@RequestParam(value = "name", defaultValue = "#{systemProperties['java.vm.version']}") String username) {
            return username;
        }
        
        @RequestMapping(value="/test3")
        public String test3(@RequestParam("role") String roles) {
            return roles;
        }
        
        @RequestMapping(value="/test4")
        public String[] test4(@RequestParam("role") String[] roles) {
            return roles;
        }
        
        @RequestMapping(value="/test5")
        public List<String> test5(@RequestParam("role") List<String> roles) {
            return roles;
        }
    }

    测试:

    输入: http://localhost:8080/myweb/test1?name=matt
    输出: "matt"
    
    输入: http://localhost:8080/myweb/test1
    输出: 400
    
    输入: http://localhost:8080/myweb/test2
    输出: "24.51-b03"
    
    输入: http://localhost:8080/myweb/test3?role=admin&role=user
    输出: "admin,user"
    
    输入: http://localhost:8080/myweb/test4?role=admin&role=user
    输出: ["admin","user"]
    
    输入: http://localhost:8080/myweb/test5?role=admin&role=user
    输出: ["admin","user"]

    2、@PathVariable

    @RequestMapping(value="/test6/{pageNum}")
    public int test6(@PathVariable("pageNum") int pageNum) {
        return pageNum;
    }

    启动后,访问http://localhost:8080/myweb/test6/10

    3、@CookieValue

    @RequestMapping(value="/test7")
    public String test7(@CookieValue("name") String name) {
        return name;
    }
    
    @RequestMapping(value="/test8")
    public Cookie test8(@CookieValue("name") Cookie cookie) {
        return cookie;
    }

    @CookieValue有与@RequestParam相同的三个属性,含义相同

    4、@RequestHeader

    @RequestMapping(value="/test9")
    public String test9(@RequestHeader("User-Agent") String userAgent, @RequestHeader(value="Accept") String[] accepts) {
        return userAgent;
    }

    @RequestHeader有与@RequestParam相同的三个属性,含义相同

     5、@ModelAttribute

    i)@ModelAttribute可绑定请求参数到命令对象,示例如下:

    @RequestMapping("/model1")
    public String testModel1(@ModelAttribute("user") UserInfo userInfo) {
        return "hello";
    }

    hello.jsp

    <%@ page language="java" %>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>Insert title here</title>
    </head>
    <body>
        ${user.name} ${user.age}
    </body>
    </html>

    启动后,访问http://localhost:8080/myweb/model1?name=matt&age=29,页面输出:matt 29

    ii)添加数据到Model,并从Model中绑定数据到处理方法参数,示例如下

    @ModelAttribute("user")
    public UserInfo getUser() {
        UserInfo user = new UserInfo();
        user.setName("cheng");
        user.setAge(30);
        System.out.println("getUser invoked");
        return user;
    }
    
    @RequestMapping("/model2")
    public String testModel2(@ModelAttribute("user") UserInfo userInfo, ModelMap model) {
        System.out.println(model.containsKey("user"));
        return "hello";
    }

    hello.jsp如上

    启动后,访问http://localhost:8080/myweb/model1,并刷新一次,页面输出:cheng 30,console输出如下:

    getUser invoked
    true
    getUser invoked
    true

    从输出结果可以看出,每次请求均须重新添加数据

    补充:

    • 添加数据的一般方法中,可包含参数,并且可用@RequestParam绑定数据,如:
    @ModelAttribute("user")
    public UserInfo getUser(@RequestParam("name") String userName )
    { ... }
    • 当命令参数的自动绑定存在时,自动绑定最后执行,即优先级更高,如访问:http://localhost:8080/myweb/model1?name=matt,输出结果为:matt 30

    6、@SessionAttributes用处不大,略

    7、@Value:绑定SpEL表达式

    public String test(@Value("#{systemProperties['java.vm.version']}") String jvmVersion)  

     8、@RequestBody

    @RequestBody用于绑定Content-Type: application/json的请求内容区数据,示例如下:

    jackson依赖

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.4.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.4.3</version>
    </dependency>

    控制器

    @RequestMapping("/json")
    @ResponseBody
    public String testJson(@RequestBody UserInfo userInfo) {
        System.out.println(userInfo.getName() + " " + userInfo.getAge());
        return "testConverter";
    }

    测试(http请求包,使用Fiddler发生请求)

    POST http://localhost:8080/myweb/json HTTP/1.1
    Content-Type: application/json;charset=UTF-8
    
    {"name":"matt","age":30}

    参考:

    请求映射规则详解 —— 跟着开涛学SpringMVC

    数据绑定(1)—— 跟着开涛学SpringMVC

    数据绑定(2)—— 跟着开涛学SpringMVC

  • 相关阅读:
    闭包概念集合
    对象的基本方法
    webpack始出来
    elasticsearch性能调优
    elasticsearch 倒排索引学习
    elasticearch 归并策略
    更加详细的Log4net的配置
    第一篇博客关于Log4net的配置记录
    js数组小结
    javascript在不同的浏览器处理事件
  • 原文地址:https://www.cnblogs.com/MattCheng/p/9174421.html
Copyright © 2020-2023  润新知