转载

胖哥学SpringMVC:RequestMapping注解之映射路径 上卷

个人建议重新练习一遍搭建的过程,如果感觉麻烦你可以直接复制上一个工程,但是需要修改pom.xml中的一点信息

<groupId>com.hanpang.springmvc</groupId>
<artifactId>springmvc-demo02</artifactId>
<version>0.0.1-SNAPSHOT</version>

1.基本用法

我们可以使用@RequestMapping标注来将请求URL(类似于@WebServlet),如/hanpang等,映射到 整个类上某个特定的处理器方法 上。

一般来说,类级别的标注负责将一个 特定 (或符合某种模式)的请求路径映射到一个控制器上,同时通过方法级别的标注来 细化 映射,即根据特定的HTTP请求方法(“GET”和“POST”方法等)、HTTP请求中是否携带特定参数等条件,将请求映射到匹配的方法上。

package com.hanpang.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller//告知其是一个控制器
@RequestMapping("/sys")
public class Demo01Controller {
	//映射默认的路径
	public ModelAndView test01() {
		System.out.println("该方法是访问sys执行");
		return null;
	}
	//----------------细化--------------------//

	//映射一个路径
	@RequestMapping(value="/user01")
	public ModelAndView test02() {
		System.out.println("/user01 path和value属性一样");
		return null;
	}
	//映射一个路径
	@RequestMapping(path="/user02")
	public ModelAndView test03() {
		System.out.println("/user02 path和value属性一样");
		return null;
	}

	//简写方式
	@RequestMapping("/user03")
	public ModelAndView test04() {
		System.out.println("/user03 当只有path或者value属性的时候,可以使用简写方式");
		return null;
	}

	//多个映射路径执行一个方法
	@RequestMapping(value= {"/user04","/user05"})
	public ModelAndView test05() {
		System.out.println("设置多个映射路径");
		return null;
	}
	//简写方式
	@RequestMapping({"/user06","/user07"})
	public ModelAndView test06() {
		System.out.println("设置多个映射路径");
		return null;
	}

}

2.路径模式的匹配规则

阅读一下,我们简单了解一下规则就行,主要介绍一下通配符"*"的演示,实际开发中个人基本上没有使用过.

package com.hanpang.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller//告知其是一个控制器
@RequestMapping("/web")
public class Demo02Controller {

	@RequestMapping("/*")
	public ModelAndView test01() {
		System.out.println("* 代表一层");
		return null;
	}

	@RequestMapping("/**")
	public ModelAndView test02() {
		System.out.println("** 代表任意层次");
		return null;
	}

}

NOTE:谁描述的更加准确,就执行谁

测试路径如下:

http://127.0.0.1:8001/mvc/web/user01 执行tes01方法
http://127.0.0.1:8001/mvc/web/user02 执行tes01方法
http://127.0.0.1:8001/mvc/web/user01/user02  执行tes02方法
http://127.0.0.1:8001/mvc/web/a/b/c/d  执行tes02方法
package com.hanpang.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller//告知其是一个控制器
@RequestMapping("/web")
public class Demo02Controller {

	@RequestMapping("/*")
	public ModelAndView test01() {
		System.out.println("* 代表一层");
		return null;
	}

	@RequestMapping("/role*")
	public ModelAndView test02() {
		System.out.println("role* 的描述更准确");
		return null;
	}

	@RequestMapping("/role")
	public ModelAndView test03() {
		System.out.println("role 我更准确");
		return null;
	}
}

修改之前上面的代码,我们继续测试路径

http://127.0.0.1:8001/mvc/web/user01 执行test01方法
http://127.0.0.1:8001/mvc/web/roleuser01 执行test02方法
http://127.0.0.1:8001/mvc/web/role 执行test03方法

使用通配符的方式真的很少,但是实际开发中我们经常使用URI模式,路径传递数据的方式(占位符),我们再次修改原来代码

package com.hanpang.web;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller//告知其是一个控制器
@RequestMapping("/web")
public class Demo02Controller {

	@RequestMapping("/*")
	public ModelAndView test01() {
		System.out.println("* 代表一层");
		return null;
	}

	@RequestMapping("/**")
	public ModelAndView test02() {
		System.out.println("** 代表一层");
		return null;
	}

	@RequestMapping("/{a}")
	public ModelAndView test03() {
		System.out.println("{a} 一个占位符");
		return null;
	}
	@RequestMapping("/{a}/{b}")
	public ModelAndView test04() {
		System.out.println("/{a}/{b} 多个占位符");
		return null;
	}

}

测试路径:

http://127.0.0.1:8001/mvc/web/user01 执行test03方法
http://127.0.0.1:8001/mvc/web/user01/user02 执行test04方法
http://127.0.0.1:8001/mvc/web/user01/user02//user03 执行test02方法

NOTE:发现占位符的描述性比通配符的描述更加准确

当一个URL同时匹配多个模式时,只会选择最匹配的一个:

  • URI模式变量的数目和通配符数量的总和最少的那个路径模式更准确。比如, /hotels/{hotel}/* 这个路径拥有一个URI变量和一个通配符,而 /hotels/{hotel}/** 这个路径则拥有一个URI变量和两个通配符,因此前者是更准确的路径模式。
  • 如果两个模式的URI模式数量和通配符数量总和一致,则路径更长的那个模式更准确。举个例子, /foo/bar* 就被认为比 /foo/* 更准确,因为前者的路径更长。
  • 如果两个模式的数量和长度均一致,则那个具有更少通配符的模式是更加准确的。比如, /hotels/{hotel} 就比 /hotels/* 更精确。
  • 默认的通配模式 /** 比其他所有的模式都更" 不准确 "。比方说, /api/{a}/{b}/{c} 就比默认的通配模式 /** 要更准确
  • 前缀通配(比如 /public/** )被认为比其他任何不包括双通配符的模式更不准确。例如, /public/path3/{a}/{b}/{c} 就比 /public/** 更准确

3.URI模式

请重视这种模式,URI模式为获取**@RequestMapping**中指定的URL的眸一个特定部分提供很大的方便。

URI模式是一个类似于URI的字符串,只不过其中包含了 一个或多个的变量名 。当使用实际的值去填充这些变量名的时候,模式就成为一个URI。比如说,一个这个URI模式 http://127.0.0.1/mvc/shxt/{userId} 就包含了一个变量名userId。将值1001赋给这个变量名后,它就变成了一个URI: http://127.0.0.1/mvc/shxt/1001

在Spring MVC中可以在 方法参数 上使用 @PathVariable 标注,将其与URI模式中的参数绑定起来:

浏览器访问路径如下: http://127.0.0.1:8001/mvc/shxt/1001

package com.hanpang.web;

@Controller//告知其是一个控制器
@RequestMapping("/shxt")
public class Demo03Controller {
	@RequestMapping("/{userId}")
	public ModelAndView test01(@PathVariable String userId) {
		System.out.println("获取占位符的值:"+userId);
		return null;
	}
}

会在控制台输出: 获取占位符的值:1001

URI模式" /shxt/{userId} "定义了一个变量,名为 userId 。当控制器处理这个请求的时候, userId 的值就会被URI模式中对应部分的值所填充。比如说,如果请求的URI是 /userId/1001 ,此时变量 userId 的值就是 1001

如果形参id跟占位符{userId}不一致

为了处理 @PathVariables 标注,Spring MVC必须通过变量名来找到URI模式中相对应的变量。可以在标注中直接声明:

package com.hanpang.web;

@Controller//告知其是一个控制器
@RequestMapping("/shxt")
public class Demo03Controller {
	@RequestMapping("/{userId}")
	public ModelAndView test01(@PathVariable(name="userId") String id) {
		System.out.println("获取占位符的值:"+id);
		return null;
	}
}

一个方法可以拥有任意数量的@PathVariable标注:

package com.hanpang.web;

@Controller//告知其是一个控制器
@RequestMapping("/shxt")
public class Demo03Controller {

	@RequestMapping("/{userId}/role/{roleKey}")
	public ModelAndView test01(@PathVariable(name="userId") String id,@PathVariable String roleKey) {
		System.out.println("userId:"+id);
		System.out.println("roleKey:"+roleKey);
		return null;
	}
}

@PathVariable 标注被应用于 Map<String, String> 类型的参数上时,框架会使用所有URI模式变量来填充map。

package com.hanpang.web;

@Controller//告知其是一个控制器
@RequestMapping("/shxt")
public class Demo03Controller {

	@RequestMapping("/{userId}/role/{roleKey}")
	public ModelAndView test01(@PathVariable Map<String,String> map) {
		System.out.println(map);
		return null;
	}
}

@PathVariable 可以被应用于所有简单类型的参数上,比如int、long、Date等类型。Spring会自动地帮你把参数转化成合适的类型,如果转换失败,就抛出一个 TypeMismatchException 。如果需要处理其他数据类型的转换,也可以注册自定义的类。

带正则表达式的URI模式[来自官网]

有时候可能需要更准确地描述一个URI模式的变量,比如: /spring-web/spring-web-3.0.5.jar 。要怎么把它分解成几个有意义的部分呢?

@RequestMapping 标注支持在URI模式变量中使用正则表达式。语法是 {varName:regex} ,其中第一部分定义了变量名,第二部分就是所要应用的正则表达式。比如下面的代码样例:

@RequestMapping("/spring-web/{symbolicName:[a-z-]+}-{version://d//.//d//.//d}{extension://.[a-z]+}")
    public void handle(@PathVariable String version, @PathVariable String extension) {
        // ......
    }
}

除了URI模式外,@RequestMapping标注还支持Ant风格的路径模式(如 /myPath/*.do 等)。不仅如此,还可以把URI模式变量和Ant风格的glob组合起来使用(比如 /owners/*/pets/{petId} 这样的用法等)。

原文  https://juejin.im/post/5aab5f5cf265da23826dbb18
正文到此结束
Loading...