进入之前: 《Spring核心内容》《JavaWeb》《JDK9-17新特性篇》
在前面学习完Spring框架技术之后,差不多会出现两批人:一批是听得云里雾里,依然不明白这个东西是干嘛的;还有一批就是差不多理解了核心思想,但是不知道这些东西该如何去发挥它的作用。不过没有关系,在SpringMVC阶段,你一定能逐渐够体会到Spring框架为我们带来的便捷之处。
此阶段,我们将再次回到Tomcat的Web应用程序开发中,去感受Spring框架为我们带来的巨大便捷。
在之前,我们给大家讲解了三层架构,包括:
每一层都有着各自的职责,其中最关键的当属表示层,因为它相当于就是直接与用户的浏览器打交道的一层,并且所有的请求都会经过它进行解析,然后再告知业务层进行处理,任何页面的返回和数据填充也全靠表示层来完成,因此它实际上是整个三层架构中最关键的一层,而在之前的实战开发中,我们编写了大量的Servlet(也就是表示层实现)来处理来自浏览器的各种请求,但是我们发现,仅仅是几个很小的功能,以及几个很基本的页面,我们都要编写将近十个Servlet,如果是更加大型的网站系统,比如淘宝、B站,光是一个页面中可能就包含了几十甚至上百个功能,想想那样的话写起来得多恐怖。
因此,SpringMVC正是为了解决这种问题而生的,它是一个非常优秀的表示层框架,采用MVC思想设计实现。
MVC详细解释如下:
SpringMVC正是希望这三者之间进行解耦,实现各干各的,更加精细地划分对应的职责。最后再将View和Model进行渲染,得到最终的页面并返回给前端(就像之前使用Thymeleaf那样,把实体数据对象和前端页面都给到Thymeleaf,然后它会将其进行整合渲染得到最终有数据的页面,而本教程也会使用Thymeleaf作为视图解析器进行讲解)
这里我们继续使用之前的Tomcat10服务器,Spring6之后要求必须使用Tomcat10或更高版本,跟之前一样,我们直接创建一个新的JakartaEE项目。
创建完成后会自动生成相关文件,但是还是请注意检查运行配置中的URL和应用程序上下文名称是否一致。
SpringMvc项目依然支持多种配置形式,这里我们首先讲解最传统的XML配置形式。
首先我们需要添加Mvc相关依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>6.0.10</version>
</dependency>
接着我们需要配置一下web.xml,将DispatcherServlet替换掉Tomcat自带的Servlet,这里url-pattern需要写为/
,即可完成替换:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
version="5.0">
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>mvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
接着需要为整个Web应用程序配置一个Spring上下文环境(也就是容器),因为SpringMVC是基于Spring开发的,它直接利用Spring提供的容器来实现各种功能,那么第一步依然跟之前一样,需要编写一个配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
接着我们需要为DispatcherServlet配置一些初始化参数来指定刚刚创建的配置文件:
<servlet>
<servlet-name>mvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<!-- 指定我们刚刚创建在类路径下的XML配置文件 -->
<param-name>contextConfigLocation</param-name>
<param-value>classpath:application.xml</param-value>
</init-param>
</servlet>
这样我们就完成了基本的配置,现在我们可以来测试一下是否配置正确,我们删除项目自带的Servlet类,创建一个Mvc中使用的Controller类,现在还没学没关系,跟着写就行了,这里我们只是测试一下:
@Controller
public class HelloController {
@ResponseBody
@RequestMapping("/")
public String hello(){
return "HelloWorld!";
}
}
接着我们需要将这个类注册为Bean才能正常使用,我们来编写一下Spring的配置文件,这里我们直接配置包扫描,XML下的包扫描需要这样开启:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 需要先引入context命名空间,然后直接配置base-package属性就可以了 -->
<context:component-scan base-package="com.example"/>
</beans>
如果可以成功在浏览器中出现HelloWorld则说明配置成功:
聪明的小伙伴可能已经发现了,实际上我们上面编写的Controller就是负责Servlet基本功能的,比如这里我们返回的是HelloWorld字符串,那么我们在访问这个地址的时候,的到的就是这里返回的字符串,可以看到写法非常简洁,至于这是怎么做到的的,怎么使用,我们会在本章进行详细介绍。
如果你希望完完全全丢弃配置文件,使用纯注解开发,可以直接添加一个类,Tomcat会在类路径中查找实现ServletContainerInitializer 接口的类,如果发现的话,就用它来配置Servlet容器,Spring提供了这个接口的实现类 SpringServletContainerInitializer , 通过@HandlesTypes(WebApplicationInitializer.class)设置,这个类反过来会查找实现WebApplicationInitializer 的类,并将配置的任务交给他们来完成,因此直接实现接口即可:
public class MainInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{WebConfiguration.class}; //基本的Spring配置类,一般用于业务层配置
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[0]; //配置DispatcherServlet的配置类、主要用于Controller等配置,这里为了教学简单,就不分这么详细了,只使用上面的基本配置类
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"}; //匹配路径,与上面一致
}
}
接着我们需要再配置类中添加一些必要的注解:
@Configuration
@EnableWebMvc //快速配置SpringMvc注解,如果不添加此注解会导致后续无法通过实现WebMvcConfigurer接口进行自定义配置
@ComponentScan("com.example.controller")
public class WebConfiguration {
}
这样我们同样可以正常访问:
之后为了方便,我们就统一使用全注解形式编写。
如果日志科技有报错无法显示Mvc相关的日志,请添加以下依赖:
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.33</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>1.7.33</version>
</dependency>
添加后就可以正常打印日志了:
有了SpringMVC之后,我们不必再像之前那样一个请求地址创建一个Servlet了,它使用DispatcherServlet
替代Tomcat为我们提供的默认的静态资源Servlet,也就是说,现在所有的请求(除了jsp,因为Tomcat还提供了一个jsp的Servlet)都会经过DispatcherServlet
进行处理。
那么DispatcherServlet
会帮助我们做什么呢?
根据图片我们可以了解,我们的请求到达Tomcat服务器之后,会交给当前的Web应用程序进行处理,而SpringMVC使用DispatcherServlet
来处理所有的请求,也就是说它被作为一个统一的访问点,所有的请求全部由它来进行调度。
当一个请求经过DispatcherServlet
之后,会先走HandlerMapping
,它会将请求映射为HandlerExecutionChain
,依次经过HandlerInterceptor
有点类似于之前我们所学的过滤器,不过在SpringMVC中我们使用的是拦截器,然后再交给HandlerAdapter
,根据请求的路径选择合适的控制器进行处理,控制器处理完成之后,会返回一个ModelAndView
对象,包括数据模型和视图,通俗的讲就是页面中数据和页面本身(只包含视图名称即可)。
返回ModelAndView
之后,会交给ViewResolver
(视图解析器)进行处理,视图解析器会对整个视图页面进行解析,SpringMVC自带了一些视图解析器,但是只适用于JSP页面,我们也可以像之前一样使用Thymeleaf作为视图解析器,这样我们就可以根据给定的视图名称,直接读取HTML编写的页面,解析为一个真正的View。
解析完成后,就需要将页面中的数据全部渲染到View中,最后返回给DispatcherServlet
一个包含所有数据的成形页面,再响应给浏览器,完成整个过程。
因此,实际上整个过程我们只需要编写对应请求路径的的Controller以及配置好我们需要的ViewResolver即可,之后还可以继续补充添加拦截器,而其他的流程已经由SpringMVC帮助我们完成了。
首先我们需要实现最基本的页面解析并返回,第一步就是配置视图解析器,这里我们使用Thymeleaf为我们提供的视图解析器,导入需要的依赖:
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring6</artifactId>
<version>3.1.1.RELEASE</version>
</dependency>
配置视图解析器非常简单,我们只需要将对应的ViewResolver
注册为Bean即可,这里我们直接在配置类中编写:
@Configuration
@EnableWebMvc
@ComponentScan("com.example.controller")
public class WebConfiguration {
//我们需要使用ThymeleafViewResolver作为视图解析器,并解析我们的HTML页面
@Bean
public ThymeleafViewResolver thymeleafViewResolver(SpringTemplateEngine springTemplateEngine){
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setOrder(1); //可以存在多个视图解析器,并且可以为他们设定解析顺序
resolver.setCharacterEncoding("UTF-8"); //编码格式是重中之重
resolver.setTemplateEngine(springTemplateEngine); //和之前JavaWeb阶段一样,需要使用模板引擎进行解析,所以这里也需要设定一下模板引擎
return resolver;
}
//配置模板解析器
@Bean
public SpringResourceTemplateResolver templateResolver(){
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setSuffix(".html"); //需要解析的后缀名称
resolver.setPrefix("/"); //需要解析的HTML页面文件存放的位置,默认是webapp目录下,如果是类路径下需要添加classpath:前缀
return resolver;
}
//配置模板引擎Bean
@Bean
public SpringTemplateEngine springTemplateEngine(ITemplateResolver resolver){
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(resolver); //模板解析器,默认即可
return engine;
}
}
现在我们就完成了视图解析器的配置,我们接着来创建一个Controller,创建Controller也非常简单,只需在一个类上添加一个@Controller
注解即可,它会被Spring扫描并自动注册为Controller类型的Bean,然后我们只需要在类中编写方法用于处理对应地址的请求即可:
@Controller //直接添加注解即可
public class HelloController {
@RequestMapping("/index") //直接填写访问路径
public ModelAndView index(){
return new ModelAndView("index"); //返回ModelAndView对象,这里填入了视图的名称
//返回后会经过视图解析器进行处理
}
}
接着我们在类路径根目录下创建一个简单html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试</title>
</head>
<body>
<p>欢迎来到GayHub全球最大同性交友网站</p>
</body>
</html>
我们会发现,打开浏览器之后就可以直接访问我们的HTML页面了:
我们在之前,使用Thymeleaf解析后端的一些数据时,需要通过Context进行传递,而使用SpringMvc后,数据我们可以直接向Model模型层进行提供:
@RequestMapping(value = "/index")
public ModelAndView index(){
ModelAndView modelAndView = new ModelAndView("index");
modelAndView.getModel().put("name", "啊这"); //将name传递给Model
return modelAndView;
}
这样Thymeleaf就能收到我们传递的数据进行解析:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="static/test.js"></script>
</head>
<body>
HelloWorld!
<div th:text="${name}"></div>
</body>
</html>
当然,为了简便,我们可以直接返回View名称,SpringMVC会将其自动包装为ModelAndView对象:
@RequestMapping(value = "/index")
public String index(){
return "index";
}
我们还可以单独添加一个Model作为形参进行设置,SpringMVC通过依赖注入会自动帮助我们传递实例对象:
@RequestMapping(value = "/index")
public String index(Model model){ //这里不仅仅可以是Model,还可以是Map、ModelMap
model.addAttribute("name", "yyds");
return "index";
}
有了Spring框架的加持,相比我们之前编写的Web应用程序,简直方便了一个层次,你就说你爱不爱吧,你爱不爱。
注意,一定要保证视图名称下面出现横线并且按住Ctrl可以跳转,配置才是正确的(最新版IDEA)
我们的页面中可能还会包含一些静态资源,比如js、css,因此这里我们还需要配置一下,让静态资源通过Tomcat提供的默认Servlet进行解析,我们需要让配置类实现一下WebMvcConfigurer
接口,这样在Web应用程序启动时,会根据我们重写方法里面的内容进行进一步的配置:
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable(); //开启默认的Servlet
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
//配置静态资源的访问路径
}
我们编写一下前端内容:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>测试</title>
<!-- 引用静态资源,这里使用Thymeleaf的网址链接表达式,Thymeleaf会自动添加web应用程序的名称到链接前面 -->
<script th:src="@{/static/test.js}"></script>
</head>
<body>
<p>欢迎来到GayHub全球最大同性交友网站</p>
</body>
</html>
创建test.js
并编写如下内容:
window.alert("欢迎来到GayHub全球最大同性交友网站")
最后访问页面,页面在加载时就会显示一个弹窗,这样我们就完成了最基本的页面配置。相比之前的方式,这样就简单很多了,直接避免了编写大量的Servlet来处理请求。
前面我们已经了解了如何创建一个控制器来处理我们的请求,接着我们只需要在控制器添加一个方法用于处理对应的请求即可,之前我们需要完整地编写一个Servlet来实现,而现在我们只需要添加一个@RequestMapping
即可实现,其实从它的名字我们也能得知,此注解就是将请求和处理请求的方法建立一个映射关系,当收到请求时就可以根据映射关系调用对应的请求处理方法,那么我们就来先聊聊@RequestMapping
吧,注解定义如下:
@Mapping
public @interface RequestMapping {
String name() default "";
@AliasFor("path")
String[] value() default {};
@AliasFor("value")
String[] path() default {};
RequestMethod[] method() default {};
String[] params() default {};
String[] headers() default {};
String[] consumes() default {};
String[] produces() default {};
}
其中最关键的是path属性(等价于value),它决定了当前方法处理的请求路径,注意路径必须全局唯一,任何路径只能有一个方法进行处理,它是一个数组,也就是说此方法不仅仅可以只用于处理某一个请求路径,我们可以使用此方法处理多个请求路径:
@RequestMapping({"/index", "/test"})
public ModelAndView index(){
return new ModelAndView("index");
}
现在我们访问/index或是/test都会经过此方法进行处理。
我们也可以直接将@RequestMapping
添加到类名上,表示为此类中的所有请求映射添加一个路径前缀,比如:
@Controller
@RequestMapping("/yyds")
public class MainController {
@RequestMapping({"/index", "/test"})
public ModelAndView index(){
return new ModelAndView("index");
}
}
那么现在我们需要访问/yyds/index
或是/yyds/test
才可以得到此页面。我们可以直接在IDEA下方的端点板块中查看当前Web应用程序定义的所有请求映射,并且可以通过IDEA为我们提供的内置Web客户端直接访问某个路径。
路径还支持使用通配符进行匹配:
@RequestMapping("/index/x?")
可以匹配/index/xa、/index/xb等等。@RequestMapping("/index/*")
可以匹配/index/lbwnb、/index/yyds等。@RequestMapping("/index/**")
可以匹配/index、/index/xxx等。我们接着来看下一个method属性,顾名思义,它就是请求的方法类型,我们可以限定请求方式,比如:
@RequestMapping(value = "/index", method = RequestMethod.POST)
public ModelAndView index(){
return new ModelAndView("index");
}
现在我们如果直接使用浏览器访问此页面,会显示405方法不支持,因为浏览器默认是直接使用GET方法获取页面,而我们这里指定为POST方法访问此地址,所以访问失败,我们现在再去端点中用POST方式去访问,成功得到页面。
我们也可以使用衍生注解直接设定为指定类型的请求映射:
@PostMapping(value = "/index")
public ModelAndView index(){
return new ModelAndView("index");
}
这里使用了@PostMapping
直接指定为POST请求类型的请求映射,同样的,还有@GetMapping
可以直接指定为GET请求方式,这里就不一一列举了。
我们可以使用params
属性来指定请求必须携带哪些请求参数,比如:
@RequestMapping(value = "/index", params = {"username", "password"})
public ModelAndView index(){
return new ModelAndView("index");
}
比如这里我们要求请求中必须携带username
和password
属性,否则无法访问。它还支持表达式,比如我们可以这样编写:
@RequestMapping(value = "/index", params = {"!username", "password"})
public ModelAndView index(){
return new ModelAndView("index");
}
在username之前添加一个感叹号表示请求的不允许携带此参数,否则无法访问,我们甚至可以直接设定一个固定值:
@RequestMapping(value = "/index", params = {"username!=test", "password=123"})
public ModelAndView index(){
return new ModelAndView("index");
}
这样,请求参数username不允许为test,并且password必须为123,否则无法访问。
header
属性用法与params
一致,但是它要求的是请求头中需要携带什么内容,比如:
@RequestMapping(value = "/index", headers = "!Connection")
public ModelAndView index(){
return new ModelAndView("index");
}
那么,如果请求头中携带了Connection
属性,将无法访问。其他两个属性:
我们接着来看,如何获取到请求中的参数。
我们只需要为方法添加一个形式参数,并在形式参数前面添加@RequestParam
注解即可:
@RequestMapping(value = "/index")
public ModelAndView index(@RequestParam("username") String username){
System.out.println("接受到请求参数:"+username);
return new ModelAndView("index");
}
我们需要在@RequestParam
中填写参数名称,参数的值会自动传递给形式参数,我们可以直接在方法中使用,注意,如果参数名称与形式参数名称相同,即使不添加@RequestParam
也能获取到参数值。
一旦添加@RequestParam
,那么此请求必须携带指定参数,我们也可以将require属性设定为false来将属性设定为非必须:
@RequestMapping(value = "/index")
public ModelAndView index(@RequestParam(value = "username", required = false) String username){
System.out.println("接受到请求参数:"+username);
return new ModelAndView("index");
}
我们还可以直接设定一个默认值,当请求参数缺失时,可以直接使用默认值:
@RequestMapping(value = "/index")
public ModelAndView index(@RequestParam(value = "username", required = false, defaultValue = "伞兵一号") String username){
System.out.println("接受到请求参数:"+username);
return new ModelAndView("index");
}
如果需要使用Servlet原本的一些类,比如:
@RequestMapping(value = "/index")
public ModelAndView index(HttpServletRequest request){
System.out.println("接受到请求参数:"+request.getParameterMap().keySet());
return new ModelAndView("index");
}
直接添加HttpServletRequest
为形式参数即可,SpringMVC会自动传递该请求原本的HttpServletRequest
对象,同理,我们也可以添加HttpServletResponse
作为形式参数,甚至可以直接将HttpSession也作为参数传递:
@RequestMapping(value = "/index")
public ModelAndView index(HttpSession session){
System.out.println(session.getAttribute("test"));
session.setAttribute("test", "鸡你太美");
return new ModelAndView("index");
}
我们还可以直接将请求参数传递给一个实体类:
@Data
public class User {
String username;
String password;
}
注意必须携带set方法或是构造方法中包含所有参数,请求参数会自动根据类中的字段名称进行匹配:
@RequestMapping(value = "/index")
public ModelAndView index(User user){
System.out.println("获取到cookie值为:"+user);
return new ModelAndView("index");
}
@RequestHeader
与@RequestParam
用法一致,不过它是用于获取请求头参数的,这里就不再演示了。
通过使用@CookieValue
注解,我们也可以快速获取请求携带的Cookie信息:
@RequestMapping(value = "/index")
public ModelAndView index(HttpServletResponse response,
@CookieValue(value = "test", required = false) String test){
System.out.println("获取到cookie值为:"+test);
response.addCookie(new Cookie("test", "lbwnb"));
return new ModelAndView("index");
}
同样的,Session也能使用注解快速获取:
@RequestMapping(value = "/index")
public ModelAndView index(@SessionAttribute(value = "test", required = false) String test,
HttpSession session){
session.setAttribute("test", "xxxx");
System.out.println(test);
return new ModelAndView("index");
}
可以发现,通过使用SpringMVC框架,整个Web应用程序的开发变得非常简单,大部分功能只需要一个注解就可以搞定了,正是得益于Spring框架,SpringMVC才能大显身手。
重定向和请求转发也非常简单,我们只需要在视图名称前面添加一个前缀即可,比如重定向:
@RequestMapping("/index")
public String index(){
return "redirect:home";
}
@RequestMapping("/home")
public String home(){
return "home";
}
通过添加redirect:
前缀,就可以很方便地实现重定向,那么请求转发呢,其实也是一样的,使用forward:
前缀表示转发给其他请求映射:
@RequestMapping("/index")
public String index(){
return "forward:home";
}
@RequestMapping("/home")
public String home(){
return "home";
}
使用SpringMVC,只需要一个前缀就可以实现重定向和请求转发,非常方便。
在学习Spring时我们讲解了Bean的作用域,包括singleton
和prototype
,Bean分别会以单例和多例模式进行创建,而在SpringMVC中,它的作用域被继续细分:
这里我们创建一个测试类来试试看:
public class TestBean {
}
接着将其注册为Bean,注意这里需要添加@RequestScope
或是@SessionScope
表示此Bean的Web作用域:
@Bean
@RequestScope
public TestBean testBean(){
return new TestBean();
}
接着我们将其自动注入到Controller中:
@Controller
public class MainController {
@Resource
TestBean bean;
@RequestMapping(value = "/index")
public ModelAndView index(){
System.out.println(bean);
return new ModelAndView("index");
}
}
我们发现,每次发起得到的Bean实例都不同,接着我们将其作用域修改为@SessionScope
,这样作用域就上升到Session,只要清理浏览器的Cookie,那么都会被认为是同一个会话,只要是同一个会话,那么Bean实例始终不变。
实际上,它也是通过代理实现的,我们调用Bean中的方法会被转发到真正的Bean对象去执行。
中文释义为**“表现层状态转换”**(名字挺高大上的),它不是一种标准,而是一种设计风格。它的主要作用是充分并正确利用HTTP协议的特性,规范资源获取的URI路径。通俗的讲,RESTful风格的设计允许将参数通过URL拼接传到服务端,目的是让URL看起来更简洁实用,并且我们可以充分使用多种HTTP请求方式(POST/GET/PUT/DELETE),来执行相同请求地址的不同类型操作。
因此,这种风格的连接,我们就可以直接从请求路径中读取参数,比如:
http://localhost:8080/mvc/index/123456
我们可以直接将index的下一级路径作为请求参数进行处理,也就是说现在的请求参数包含在了请求路径中:
@RequestMapping("/index/{str}")
public String index(@PathVariable String str) {
System.out.println(str);
return "index";
}
注意请求路径我们可以手动添加类似占位符一样的信息,这样占位符位置的所有内容都会被作为请求参数,而方法的形参列表中必须包括一个与占位符同名的并且添加了@PathVariable
注解的参数,或是由@PathVariable
注解指定为占位符名称:
@RequestMapping("/index/{str}")
public String index(@PathVariable("str") String text){
System.out.println(text);
return "index";
}
如果没有配置正确,方法名称上会出现黄线。
我们可以按照不同功能进行划分:
我们分别编写四个请求映射:
@Controller
public class MainController {
@RequestMapping(value = "/index/{id}", method = RequestMethod.GET)
public String get(@PathVariable("id") String text){
System.out.println("获取用户:"+text);
return "index";
}
@RequestMapping(value = "/index", method = RequestMethod.POST)
public String post(String username){
System.out.println("添加用户:"+username);
return "index";
}
@RequestMapping(value = "/index/{id}", method = RequestMethod.DELETE)
public String delete(@PathVariable("id") String text){
System.out.println("删除用户:"+text);
return "index";
}
@RequestMapping(value = "/index", method = RequestMethod.PUT)
public String put(String username){
System.out.println("修改用户:"+username);
return "index";
}
}
这只是一种设计风格而已,各位小伙伴了解即可。
拦截器是整个SpringMVC的一个重要内容,拦截器与过滤器类似,都是用于拦截一些非法请求,但是我们之前讲解的过滤器是作用于Servlet之前,只有经过层层的过滤器才可以成功到达Servlet,而拦截器并不是在Servlet之前,它在Servlet与RequestMapping之间,相当于DispatcherServlet在将请求交给对应Controller中的方法之前进行拦截处理,它只会拦截所有Controller中定义的请求映射对应的请求(不会拦截静态资源),这里一定要区分两者的不同。