一篇文章搞定springMVC中的请求映射

本文中的内容大都来自spring官方文档,官方文档的访问地址为spring官方文档地址
本文中所有的demo代码在https://github.com/singedli/request_mapping_demo.git可以下载。

实验的项目是采用默认配置的spring boot项目,使用的工具为IDEA和POSTMAN。

希望这些案例能够帮助你理解和思考。

talk is cheap,show me the code!

1、从最简单的hello world开始

这里写图片描述

@Controller
public class HelloController {
    @RequestMapping("/helloWorld")
    @ResponseBody
    public String helloWorld(){
        return "hello world";
    }
}

上例也许就是一个最简单的springmvc代码了,当请求的uri为”/helloWorld”时,将会得到字符串”hello world”,下图是用postman模拟请求的结果。

这里写图片描述

简单介绍几个基础的注解,因为后面的实验中可能会用到:

  • @Controller 声明HelloController类为springMVC中的一个controller,优点是不需要继承任何类或者实现任何的接口。在配置了注解扫描后,头上有@Controller注解的类将会被spring容器自动的加载。
    spring 注解扫描的配置方式(java config)如下:
@Configuration
@ComponentScan("org.example.web")
public class WebConfig {

    // ...
}
  • @RequestMapping: 用于提供的请求映射信息。@RequestMapping注解即可以用在class级别中也可以用在方法级别中。
  • @ResponseBody: 表示该方法的返回结果直接写入 HTTP response body 中。
  • @GetMapping、@PostMapping、@PutMapping等:他们相当于RequestMapping(value = “/xxx” , method = RequestMethod.GET)或 RequestMapping(value = “/xxx” , method = RequestMethod.POST),即限定请求方法的简写。
  • @RestController :官方文档的描述如下,即@RestController 注解相当于@Controller和@ResponseBody两个注解的组合。
    @RestController is a composed annotation that is itself annotated with @Controller and @ResponseBody

2、通过指定HTTP请求方法来限定请求

URI为”/testShortcut”的接口将请求的方法限定为GET请求,也就以为着请求地址和请求方法都必须正确才会返回字符串”success”。

代码如下:

这里写图片描述

@Controller
public class MyRequestMappingDemo {

    @RequestMapping(value = "/testShortcut",method =  RequestMethod.GET)
    @ResponseBody
    public String testShortcut(){
        return "success";
    }

}

使用postman请求接口”/testShortcut”如下,可以看到,使用的HTTP METHOD为GET请求,并且成功返回了字符串”success”。

这里写图片描述

下面使用HTTP METHOD为POST请求同样的接口

这里写图片描述
可以看到,同样的接口只是请求的方式不同得到的结果也就不相同。达到了通过请求方式来限定请求的目的。

再此顺便试一下@GetMapping、@PostMapping、@PutMapping等注解好不好用。

这里写图片描述

@Controller
public class GETMappingDemo {
    @GetMapping(value= "/testGetMapping")
    @ResponseBody
    public String testGetMapping(){
        return "testGetMapping";
    }
}

这里写图片描述

这里写图片描述

由上面两张图可以看到,@GetMapping、@PostMapping等注解对于通过请求方式来限定也是贼好用的。

3、url pattern

springMVC也是支持在请求的url中使用通配符的,具体规则如下:
  • ?通配符表示匹配一个字符(matches one character)。
    • 通配符表示在一个路径分段中匹配一个或者多个字符(matches zero or more characters within a path segment)。
  • ** 统配符表示匹配零个或者多个路径分段(match zero or more path segments)。

相关代码和实验如下:

这里写图片描述

@RestController
public class URIPatternsDemo {

    @RequestMapping("/testURIPatterns/?")
    public String testURIPatterns(){
        return "?通配符表示匹配一个字符!";
    }

    @RequestMapping("/testURIPatterns1/*")
    public String testURIPatterns1(){
        return "*通配符表示匹配零个或者多个字符,但必须是在一个路径分段中!";
    }

    @RequestMapping("/testURIPatterns2/**")
    public String testURIPatterns2(){
        return "**通配符表示匹配零个或者多个路径分段!";
    }

}

上述代码中,URIPatternsDemo类里定义了三个方法,分别用于测试三种通配符的使用。使用postman测试如下:

1、测试?通配符,路径中输入一个字符a,信息成功返回。
这里写图片描述
2、测试?通配符,路径中输入一个字符b,信息成功返回。
这里写图片描述
3、测试?通配符,路径中输入多个字符,报错。
这里写图片描述
结论,?通配符只能匹配一个随机的字符
4、测试*通配符,路径中输入多个字符,正确返回。
这里写图片描述
5、测试*通配符,路径中输入零个字符,正确返回。
这里写图片描述
6、测试*通配符,在多个路径分段中输入多个字符,报错。
这里写图片描述
结论,* 通配符表示在一个路径分段中匹配一个或者多个字符
7、测试**通配符,在一个路径分段中输入多个字符,正确返回。
这里写图片描述
8、测试**通配符,在多个路径分段中输入多个字符,正确返回。
这里写图片描述
8、测试**通配符,零个路径分段,正确返回。
这里写图片描述
结论,** 统配符表示匹配零个或者多个路径分段。

4、URI Template Patterns

URI templates can be used for convenient access to selected parts of a URL in a @RequestMapping method.

URI模板可以很方便的用于获取@RequestMapping方法里的URL的一部分。(本屌的渣渣翻译)
意思就是说可以使用URI Template获取URL路径中的变量。在sprngMVC中使用的是@PathVariable注解。talk is cheap,上代码。
这里写图片描述

@Controller
public class TestUrlPatterns {
    //演示一个URL路径变量的情况
    @RequestMapping("/UrlPatternDemo/{pathVar}")
    @ResponseBody
    public String UrlPatternDemo(@PathVariable String pathVar){
        return pathVar;
    }

    //演示两个路径变量的情况
    @RequestMapping("/multiUrlPatternDemo/{pathVar1}/{pathVar2}")
    @ResponseBody
    public String multiUrlPatternDemo(@PathVariable String pathVar1 , @PathVariable String pathVar2){
        return "this is first path variable:" + pathVar1+", this is second path variable:" + pathVar2;
    }

    //演示路径变量支持多种基本数据类型,而不是只有String一种
    @RequestMapping("/multiUrlPatternDemo2/{pathVar1}/{pathVar2}")
    @ResponseBody
    public String multiUrlPatternDemo2(@PathVariable Integer pathVar1 , @PathVariable Integer pathVar2){
        return "第一个参数是:" + pathVar1+",第二个参数是:" + pathVar2 +"。两个参数的和是:"+ (pathVar1 + pathVar2);
    }
}

下面测试一下这三个方法:
这里写图片描述

这里写图片描述

这里写图片描述

结论:@PathVariable注解可以获取请求URL中的路径参数,并且也可以用基本数据类型来接收参数的值。

下面来讨论一些特殊情况:
如果一个请求的URL同时匹配了多个通配符怎么办?
springMVC中有一些规则用于处理这种特殊情况,规则是:

  • 例如,/hotel/{hotel}/*/hotel/{hotel}/**,前者具有一个路径变量和一个通配符,而后者同样是具有一个路径变量,但是后者却有两个通配符。此时,springMVC认为前者更加的明确,所以前者的优先级会更高一些。
  • /foo/bar*/foo/* springMVC认为前者的指向更加明确,所以前者的优先级更高。
  • /hotels/{hotel}/hotels/*springMVC认为前者的指向更加明确,原因是前者没有用到通配符。
  • /** 在springMVC中被认为是优先级最低的。

    具体的规则在AntPathMatcher类的AntPatternComparator()方法中有完整的体现。

URI Template另外还有两种用法,即与正则表达式一起使用和与Placeholders一起使用。
第一种:与正则一起使用
这里写图片描述

@RestController
public class RegexExpressionDemo {

    @RequestMapping("/testRegexExpressionPattern/{name:[a-z-]+}")
    public String testRegexExpressionPattern(@PathVariable String name){
        return "正则表达式匹配的变量为:" + name;
    }

}

这里写图片描述

第二种,与Placeholders一起使用
这里写图片描述

@Controller
@RequestMapping(value="${demo.path.variable}")
public class PropertiesPlaceholderDemo {

    @RequestMapping("/testPropertiesPlaceholder")
    @ResponseBody
    public String testPropertiesPlaceholder(){
        return "asd";
    }
}

如上面代码所示,@RequestMapping注解中的参数来自properties配置文件,当路径正确匹配时,将会返回字符串”asd”。所以我们在properties文件中创建一个key为demo.path.variable的属性。在这里就直接写在application.properties中,如下图所示。
这里写图片描述

所以我们访问的路径应该为”/haha/testPropertiesPlaceholder”,下面为测试:
这里写图片描述
成功返回字符串“asd”。

5、Matrix Variables

Matrix Variables意味矩阵变量,说白了就是名值对。解释名词是很蛋疼的事,直接上代码和实验结果,对着代码和结果进行解释。

要使用矩阵变量,首先需要将RequestMappingHandlerMapping类中的removeSemicolonContent属性设为false,默认情况下为true。设置的方法也很简单,下面是通过java config的方式配置该属性。
这里写图片描述

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        urlPathHelper.setRemoveSemicolonContent(false);
        configurer.setUrlPathHelper(urlPathHelper);
    }
}

实验代码如下:

这里写图片描述
完整代码如下,其中有个没见过的注解@MatrixVariable,下面通过实验结果来说说这个注解到底是干什么。

@RestController
public class MatrixVariablesDemo {

    @RequestMapping("/testMatrixVariables/{pathVar1}")
    public String testMatrixVariables(@PathVariable String pathVar1,@MatrixVariable int matrixVariable1,@MatrixVariable int matrixVariable2){
        return "pathVar1的值为:" + pathVar1 + "; matrixVariable1的值为:" + matrixVariable1 + "; matrixVariable2的值为:" + matrixVariable2;
    }

    @RequestMapping("/testMatrixVariables2/{pathVar1}/{pathVar2}")
    public String testMatrixVariables2(@MatrixVariable(name = "matrixVariable",pathVar = "pathVar1") int matrixVariable1,@MatrixVariable(name = "matrixVariable",pathVar = "pathVar2") int matrixVariable2){
        return " pathVar1变量中的matrixVariable的值为:" + matrixVariable1 + "; pathVar2变量中的matrixVariable的值为:" + matrixVariable2;
    }

    @RequestMapping("/testMatrixVariables3/{pathVar}")
    public String testMatrixVariables3(@PathVariable String pathVar,@MatrixVariable(name = "matrixVariable",pathVar = "pathVar",required = false,defaultValue = "222233" ) String matrixVariable){
        return "pathVar变量的值是:"+pathVar+",matrixVariable变量什么值也没传,默认值是:" + matrixVariable;
    }

    @RequestMapping("/testMatrixVariables4/{pathVar1}/{pathVar2}")
    public String testMatrixVariables4(@MatrixVariable MultiValueMap<String,String> matrixMap){
        return matrixMap.toString();
    }

    @RequestMapping("/testMatrixVariables5/{pathVar1}/{pathVar2}")
    public String testMatrixVariables5(@MatrixVariable(pathVar = "pathVar1") MultiValueMap<String,String> matrixMap){
        return matrixMap.toString();
    }
}

1、测试第一个接口“/testMatrixVariables/{pathVar1}”,实验中请求的URL为http://localhost:8080//testMatrixVariables/20;matrixVariable1=1;matrixVariable2=2
结果如下:这里写图片描述
先观察URL,在{pathVar1}中有三个用分号分隔的部分,分别为20、matrixVariable1=1和matrixVariable2=2。回想Matrix Variable矩阵变量的定义,说它是明值对。这是可以大概明白所谓的矩阵变量就是写在路径变量{pathVar1}中的用分号“;”隔开的name=value对,即本例中的matrixVariable1=1和matrixVariable2=2。结合代码和实验结果可知,@MatrixVariable注解的作用就是用来获取路径变量中的矩阵的变量的,并且可以用基本数据类型来接收。

2、测试第二个接口,URLhttp://localhost:8080//testMatrixVariables2/matrixVariable=1/matrixVariable=2,结合代码可知,我们可以用@MatrixVariable注解,并通过指定pathVar属性来获取两个不同路径变量中同名的矩阵变量。
这里写图片描述
3、第三个接口用于测试@MatrixVariable注解的默认值,URLhttp://localhost:8080//testMatrixVariables3/1,结果为:
这里写图片描述
4、第四个和第五个接口都是用于测试@MatrixVariable注解中用Map接收参数,URL分别为http://localhost:8080/testMatrixVariables4/a=a;b=b;c=c/a=aa;b=bb

http://localhost:8080/testMatrixVariables5/a=a;b=b;c=c/a=aa;b=bb
结果分别如下:

获取所有路径段中的矩阵变量,并用Map接收
这里写图片描述

指定获取某个路径分段中的矩阵变量,并用Map接收
这里写图片描述

6、通过限定MediaTypes、Request Parameters和Header Values来限制请求

通过Consumes,Produces注解来限定MediaTypes

consumes:指定处理请求的提交内容类型(Content-Type)。
produces:指定返回的内容类型,仅当request请求头中的(Accept)类型中包含该指定类型才返回。

这里写图片描述

@Controller
@RequestMapping(value="/test")
public class ConsumableMediaTypesDemo {

    @RequestMapping(value="/testConsumableMediaTypes",consumes = "application/json")
    public String testConsumableMediaTypes(){
        return "请求成功!";
    }

    @RequestMapping(value="/testConsumableMediaTypes1",consumes = MediaType.APPLICATION_JSON_VALUE)
    public String testConsumableMediaTypes1(){
        return "请求成功!                 MediaType.APPLICATION_JSON_VALUE";
    }

    @RequestMapping(value="/testConsumableMediaTypes2",consumes = MediaType.APPLICATION_XML_VALUE)
    @ResponseBody
    public String testConsumableMediaTypes2(){
        return "请求成功!                 MediaType.APPLICATION_XML_VALUE";
    }

}

1、第一个接口是用consumes属性来限定MediaTypes的类型,并使用了字面量的形式限定类型,后面两个接口使用了MediaType类中定义的常量。实验的结果如下:
接口1:
这里写图片描述

接口2:
这里写图片描述

接口3:
这里写图片描述

produces、params和headers的使用方式与@Consumes相同
代码如下
这里写图片描述

@Controller
public class ProducibleMediaTypesDemo {

    @RequestMapping(value = "/testProducibleMediaTypes",produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public String testProducibleMediaTypes(){
        return "请求成功";
    }
}
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值