Spring MVC之RequestMapping:各个映射详解

2019/7/24 13:12:12 人评论 次浏览 分类:学习教程

1、URL路径映射

    1)普通URL路径映射
        @RequestMapping(value="/test")
        @RequestMapping("/hello")
            注解中只出现一个参数且参数名为value的话,可以将参数名去掉
        @RequestMapping(value={"/test", "/user/hello"})
            多个URL路径可以映射到同一个处理器的功能处理方法。
    
    2)URI模板模式映射
        @RequestMapping(value="/users/{userId}")
            {XXX}占位符, 请求的URL可以是"/users/123456"或"/users/abcd",之后可以通过@PathVariable可以提取URI模板模式中的{XXX}中的值
        @RequestMapping(value="/users/{userId}/create") 
            这样也是可以的,请求的URL可以是"/users/123/create"
        @RequestMapping(value="/users/{userId}/topics/{topicId}")
            这样也是可以的,请求的URL可以是"/users/123/topics/123"

    3)Ant风格的URL路径映射
        @RequestMapping(value="/users/**")
            可以匹配"/users/abc/abc",但"/users/123"将会被【URI模板模式映射中的"/users/{userId}"模式优先映射到】
        @RequestMapping(value="/product/?")
            可匹配"/product/1"或"/product/a",但不匹配"/product"或"/product/aa";
            ?代表有且只有一个字符
        @RequestMapping(value="/product*")
            可匹配"/productabc"或"/product",但不匹配"/productabc/abc";
            *代表0~n个字符
        @RequestMapping(value="/product/*")
            可匹配"/product/abc",但不匹配"/productabc";
        @RequestMapping(value="/products/**/{productId}")
            可匹配"/products/abc/abc/123"或"/products/123",也就是Ant风格和URI模板变量风格可混用;
            **代表所有的子路径

    4)正则表达式风格的URL路径映射
        从Spring3.0 开始支持正则表达式风格的URL路径映射,格式为{变量名:正则表达式},之后通过@PathVariable可以提取{XXX:正则表达式匹配的值}中的XXX这个变量的值。

        @RequestMapping(value="/products/{categoryCode:\\d+}-{pageNumber:\\d+}")
            可以匹配"/products/123-1",但不能匹配"/products/abc-1",这样可以设计更加严格的规则。
        @RequestMapping(value="/user/{userId:^\\d{4}-[a-z]{2}$}")
            可以匹配"/user/1234-ab"
        
        注意:\d表示数字,但是\在java的字符串中是特殊字符,所以需要再加一个\进行转义即可
        (js和java的正则几乎一致,js正则中的一个\变为java中的俩个\即可)
            括号:
                [abc]     查找方括号之间的任何字符。
                [^abc]     查找任何不在方括号之间的字符。
                [0-9]     查找任何从 0 至 9 的数字。
                [a-z]     查找任何从小写 a 到小写 z 的字符。
                [A-Z]     查找任何从大写 A 到大写 Z 的字符。
                [A-z]     查找任何从大写 A 到小写 z 的字符。
                (red|blue|green)     查找任何指定的选项。
            
            元字符:
                .     查找单个任意字符,除了换行和行结束符.如果要表示.这个字符,需要转义
                \w     查找单词字符。     字母 数字 _
                \W     查找非单词字符。非 字母 数字 _
                \d     查找数字。
                \D     查找非数字字符。
                \s     查找空白字符。
                \S     查找非空白字符。
                \b     匹配单词边界。
                \B     匹配非单词边界。
                \0     查找 NUL 字符。
                \n     查找换行符。
                \f     查找换页符。
                \r     查找回车符。
                \t     查找制表符。
                \v     查找垂直制表符。

            量词:
                n+         匹配任何包含至少一个 n 的字符串。
                n*         匹配任何包含零个或多个 n 的字符串。
                n?         匹配任何包含零个或一个 n 的字符串。
                n{X}     匹配包含 X 个 n 的序列的字符串。
                n{X,Y}     匹配包含 X 到 Y 个 n 的序列的字符串。
                n{X,}     匹配包含至少 X 个 n 的序列的字符串。
                n$         匹配任何结尾为 n 的字符串。
                ^n         匹配任何开头为 n 的字符串。
                ?=n     匹配任何其后紧接指定字符串 n 的字符串。
                ?!n     匹配任何其后没有紧接指定字符串 n 的字符串。


        正则表达式风格的URL路径映射是一种特殊的URI模板模式映射
        URI模板模式映射不能指定模板变量的数据类型,如是数字还是字符串;
        正则表达式风格的URL路径映射,可以指定模板变量的数据类型,可以将规则写的相当复杂。


2、请求方法映射限定

    一般获取数据为GET请求方法,提交表单一般为POST请求方法。但之前URL路径映射方式对任意请求方法都是接受的,因此我们需要某种方式来告诉相应的功能处理方法只处理如GET方式的请求或POST方式的请求。

    @RequestMapping(value="/user/{userId:\\d+}",method=RequestMethod.GET)
        可以匹配"/user/100",并且请求方式只能是GET
    
    @RequestMapping(value="/hello", method={RequestMethod.POST,RequestMethod.GET})
        可以匹配"/hello",并且请求方式只能是POST或者GET
    
    注意:
    1、一般浏览器只支持GET、POST请求方法,如想浏览器支持PUT、DELETE 等请求方法只能模拟。(jquery中的ajax函数可以发送这些方式的请求)
    2、除了GET、POST,还有HEAD、OPTIONS、PUT、DELETE、TRACE(观察servlet源码也可获知)
    3、DispatcherServlet默认开启对GET、POST、PUT、DELETE、HEAD 的支持;
    4、如果需要支持OPTIONS、TRACE,请添加DispatcherServlet 在web.xml 的初始化参数:dispatchOptionsRequest 和
    dispatchTraceRequest 为true。(查看源码,在DispatcherServlet的父类中可以找到这个俩个属性)


3、请求参数映射限定

    1)请求数据中有指定参数名
    

@RequestMapping("/test")
    @Controller
    public class HomeController {
        @RequestMapping(params="create",method=RequestMethod.GET)
        public ModelAndView test1(){

            return null;
        }
        @RequestMapping(params="create",method=RequestMethod.POST)
        public ModelAndView test2(){

            return null;
        }
    }

    可以匹配的路径为:/test?create
    如果是get 方式的请求则访问test1方法
    如果是post方式的请求则访问test2方法


    2)请求数据中没有指定参数名
    @RequestMapping(params="!create", method=RequestMethod.GET)


    3)请求数据中指定参数名=值
    @RequestMapping(params="username=tom")    


    4)请求数据中指定参数名!=值
    username参数名可以不出现,但是如果出现了,那么参数值一定不能等于tom
    @RequestMapping(params="username!=tom")

    5)组合使用是"且"的关系
    @RequestMapping(params={"create","username=tom"})

4.请求头数据映射限定
    1)请求头数据中有指定参数名
    @RequestMapping(value="/header/test1", headers="Accept")
        表示请求的URL必须为"/header/test1"且请求头中必须有Accept参数才能匹配。

    @RequestMapping(value="/header/test1", headers="my_test")
        表示请求的URL必须为"/header/test1"且请求头中必须有my_test参数才能匹配
    
    2)请求头数据中没有指定参数名
    @RequestMapping(value="/header/test2", headers="!abc")
        表示请求的URL必须为"/header/test2"且请求头中必须没有abc参数才能匹配


    3)请求头数据中指定参数名=值
    @RequestMapping(value="/header/test3", headers="Content-Type=application/json")
    表示请求的URL必须为"/header/test3"且请求头中必须有"Content-Type=application/json"参数即可匹配。


    4)请求头数据中指定参数名!=值
    @RequestMapping(value="/header/test4", headers="Accept!=text/html")
    表示请求的URL必须为"/header/test4"且请求头中必须有Accept参数,但是值不等于text/html即可
    例如:
    @RequestMapping(value="/test1",headers="Content-Type!=application/json")
    表示请求头信息中要么不出现Content-Type属性,如果出现了那么它的值一定不能等于application/json

    5)组合使用是"且"的关系
    @RequestMapping(value="/header/test5", headers={"Accept!=text/html", "abc=123"}):
    表示请求的URL必须为"/header/test5"且请求头中必须有"Accept"参数但值不等于"text/html"且请求中必须有参数"abc=123"即可匹配。


    6)consumes属性和produces属性
    consumes 指定处理请求的提交内容类型(消费)
    @RequestMapping(value="/test",consumes="application/json")  
        方法仅处理请求中,Content-Type为"application/json"的情况

    produces 指定返回的内容类型(生产)
    @RequestMapping(value= "/test", produces="application/json")
        表示该功能处理方法将产生json格式的数据,此时根据请求头中的Accept进行匹配,如请求头"Accept=application/json"时即可匹配;


    例如:
    

@RequestMapping(value="test6",consumes="application/json")
    public String test6(){
        System.out.println("test6...");
        return "test";
    }
    
    @RequestMapping(value="test7",produces="application/json")
    public String test7(){
        System.out.println("test7...");
        return "test";
}


    
    测试类中的main函数代码:
    此处我们使用Spring提供的Http客户端API创建了请求并设置了请求的Content-Type和编码并在响应体中写回了json数据
    

public static void main(String[] args) {
        try {
            String url = "http://127.0.0.1:8989/XXX/XXX";
            //创建HttpRequest
            ClientHttpRequest request =
            new SimpleClientHttpRequestFactory().
            createRequest(new URI(url), HttpMethod.POST);
            //设置请求头的内容类型头和内容编码
            //request.getHeaders().set("Content-Type", "application/json;charset=UTF-8");
            request.getHeaders().set("Accept", "application/json");
            //写出请求内容体
            String jsonData = "{\"username\":\"zhang\", \"password\":\"123\"}";
            request.getBody().write(jsonData.getBytes("UTF-8"));
            //发送请求并得到响应
            ClientHttpResponse response = request.execute();
            System.out.println(response.getStatusCode());
            System.out.println(response.getHeaders());
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }

    注意:在上面代码中,如果想获得响应正文中的数据,可以编写一下代码:
    //得到响应体的编码方式
    Charset charset = response.getHeaders().getContentType().getCharSet();
    //得到响应体的内容
    InputStream is = response.getBody();
    byte bytes[] = new byte[(int)response.getHeaders().getContentLength()];
    is.read(bytes);
    String data = new String(bytes, charset);
    System.out.println("charset="+charset);
    System.out.println("data : " + data);
 

相关资讯

  • 那些我们不愿意承认的事

    很久没有见的老朋友,准确的说应该是很久没有见过的老师,一个比我大两岁的老师,我上初中的时候他从高中回来教我了一年。后来又回去上高中,我上高中的时候他上大学,现在我刚大学毕业他创办了公司。昨日一见依然如故,他还是热爱销售,而我却成了纯粹的技术人员。 看到他…

    2015/6/22 13:12:47

学习教程

共有访客发表了评论 网友评论

验证码: 看不清楚?
    -->