1. SpringMVC简介
SpringMVC主要解决了V-C交互的问题,即如何使用控制器接收请求并给予响应的问题。
MVC:Model(数据模型) + View(视图) + Controller(控制器)
2. 关于SpringBoot框架
SpringBoot框架可以简单的当作为一个“加强版的SpringMVC框架”,相比直接创建SpringMVC框架的项目,如果创建的是SpringBoot框架的项目,可以不必添加非常用依赖,也可以省去大量的常规配置!
3. 创建SpringBoot项目
创建项目时,选择Spring Initializr
的创建向导:
当创建项目时,在以上界面点击下一步后长时间无响应时,应该在以上界面的右侧选中Custom
,并使用 https://start.springboot.io 网址并再次点击下一步。
在接下来的界面中确定当前项目的一些参数,例如Group、Artifact、Java Version等:
在选择依赖的界面,在左侧选择Web
,在右侧勾选Spring Web
:
完成后,项目即创建完成,第1次使用时,开发工具会自动下载大量依赖。
4. 启动SpringBoot项目
创建好的SpringBoot中默认在src/main/java
下就已经有一个package了,其名称是创建项目时指定的Group和Artifact决定的:
注意:这个包是SpringBoot默认指定的组件扫描的包,所以,项目中的各组件都必须放在这个包或其子孙包中!
在这个包中,默认已经存在SpringmvcApplication
类,类的名称是创建项目时指定的Artifact决定的:
这个类中有main()
方法,执行这个main()
方法就可以启动整个项目,所以,这个类也称之为“启动类”。
启动成功后,控制台输出内容例如:
通过启动日志可以看到,启动当前项目时是启动了Tomcat的,并将项目部署在8080
端口,这个Tomcat是当前项目内置的!
另外,通过以上启动日志可以看到Tomcat在部署当前项目时配置的Context Path是空值:
所以,后续在访问当前项目时,在URL中端口号的右侧不必再添加项目名称或对应的路径值!
在项目的src/main/resources
下默认就存在application.properties
文件,这个文件是项目的配置文件:
SpringBoot框架会自动读取项目中的配置,并且,SpringBoot还约定框架相关配置的属性名称,所以,除非是编写自定义的配置,否则,各配置的属性名称是相对固定的!
如果需要指定当前项目启动时,将Tomcat启动在哪个端口,可以添加配置:
如果使用的是MacOS或Linux操作系统,可能无法直接将端口号修改为80
,因为操作系统将80
端口视为敏感端口,需要事先修改操作系统的设置才可以使用。
5. 添加静态页面
在SpringBoot项目中,如果创建项目时就已经勾选了Spring Web
依赖,默认情况下在src\main\resources
下就已经创建好了static
文件夹:
该文件夹是SpringBoot框架默认的静态资源文件夹,项目中的静态资源应该放在这个文件夹之下,例如.html
、.css
、.js
、图片文件等,例如,在static
文件夹下创建index.html
:
完成后,重启项目,打开浏览器,输入 http://localhost 即可访问这个页面!
SpringBoot框架将
index.html
设置为默认访问的资源,所以,如果需要访问的是 http://localhost/index.html,在URL中可以不必显式的指定资源名,即使用 http://localhost 即可!
【练习】
设计register.html
页面作为“用户注册”页面,在该页面需要1个表单,表单中至少包含用户名、密码、年龄、手机、邮箱对应的5个输入框和1个提交按钮。最终,通过 http://localhost/register.html 可以打开这个页面。
6. SpringMVC中的控制器
在传统Java EE项目中是使用Servlet组件(自定义类继承自HttpServlet
)作为控制器的,在SpringMVC框架中可以自定义任何类作为控制器类,推荐使用Controller
作为类名的最后一个单词,并且在类的声明之前添加@Controller
注解即可将该类配置为控制器类!例如,在cn.tedu.springmvc
包中创建UserController
类并添加@Controller
注解:
在传统的Java EE中,如果需要处理客户端提交的请求,需要在Servlet类之前添加注解来配置请求路径,并重写Servlet中的doGet()
或doPost()
方法来处理GET或POST类型的请求,在SpringMVC中:
-
在方法的声明之前使用
@RequestMapping
注解来配置请求路径; -
应该使用
public
权限; -
暂时使用
String
作为返回值类型; -
方法名称可以自定义;
-
参数列表暂时为空;
-
在方法的声明之前暂时添加
@ResponseBody
注解。
例如:
完成后,重启项目,在浏览器中通过 http://localhost/hello 即可测试访问,在浏览器中将可以看到OK
字样,并且在IntelliJ IDEA的控制台可以看到以上输出的内容!
同一个控制器中可以有若干个处理请求的方法,例如此前练习的“用户注册”页面可以将请求路径设计为/register
:
然后,在UserController
中补充处理/register
的方法:
完成后,重启项目,在浏览器重新打开 http://localhost/register.html(如果已经打开,则需要刷新),可以不必输入任何内容,直接点击提交按钮,在浏览器将可以看到Register OK
字样,并且在IntelliJ IDEA的控制台可以看到以上输出的内容!
7. SpringMVC框架接收请求参数
在register.html
中,为表单中的各控件配置name
属性就可以设置请求参数的名称,例如:
在SpringMVC中,如果需要接收这些请求参数,直接将各请求参数声明为处理请求的方法的参数即可,例如:
完成后,即可重启项目,观察运行结果。
【练习】
自行设计login.html
页面,页面中需要用户名、密码的输入框和提交按钮,提交请求后,服务器端可以接收到用户名和密码的值。
使用以上做法接收请求参数时,如果客户端提交的请求参数的数量较多,就会导致处理请求的方法的参数列表中需要声明对应的多个参数,为了避免参数的数量过多,可以将客户端提交的多个请求参数进行封装!例如,创建User
类:
public class User {
public String username;
public String password;
public Integer age;
public String phone;
public String email;
// SETTERS & GETTERS
// toString()
}
提示:以上各属性的访问权限并不重要!
然后,将处理请求的方法的参数列表中使用该类型即可:
完成后,再次重启项目,重新提交表单,可以看到仍正常接收请求参数!
所以,在SpringMVC框架中,当需要接收客户端提交的请求参数时,可以将各参数直接声明为处理请求的方法的参数,也可以将这些请求参考封装起来,理论上来说,如果请求参数的数量较少且可控,则直接声明即可,如果请求参数的数量较多或可能发生调整,应该封装,实际情况是应该封装,除非请求参数只有1个。
8. 关于转发
当需要向客户端响应HTML网页时,可以先在pom.xml
中添加SpringBoot整合Thymeleaf的依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
在SpringBoot中,当创建项目时勾选了Spring Web
的依赖后,默认在src/main/resources
下就已经创建好了templates
文件夹:
这个templates
文件夹就是SpringBoot项目中用于存放模版页面的文件夹!
在templates
下创建hello.html
文件:
然后,在UserController
中,将原本的hello()
方法上的@ResponseBody
删除,并将返回值改为hello
:
完成后,重启项目,再次访问 http://localhost/hello 即可看到所设计的hello.html
网页!
在以上操作中,首先删除了@ResponseBody
注解,该注解的作用是“将方法返回的数据直接响应到客户端”,简称“响应正文”!
然后,在处理请求的方法中,返回了"hello"
字符串,是因为SpringMVC框架中,当控制器中处理请求的方法的返回值类型是String
时,表示“返回视图名称”,即“由哪个视图来负责响应”,当前项目是添加了SpringBoot整合Thymeleaf的依赖,其对“视图名称”的处理方法是根据/templates/
与视图名称与.html
来确定由哪个文件负责响应,即:
"/template/" + 返回值 + ".html" = "/templates/hello.html"
所以,拼接出来的结果就是视图文件(HTML文件)的位置!所以,当HTML文件直接放在templates
下,而并不在其子级文件夹中时,也可以简单的理解为“返回的字符串就是文件名”!
【练习】
在templates
下创建success.html
页面用于表示“成功”时显示的页面,再创建error.html
用于表示“失败”时显示的页面,当用户提交登录时,如果用户名和密码分别是root
和1234
,则视为登录成功,否则视为登录失败,无论成功或失败都应该显示对应的页面!
9. 转发时封装数据并显示
当控制器向模版页面转发时需要将数据交给模版页面去显示时,需要在处理请求的方法的参数列表中添加ModelMap
类型的参数,并在处理过程中,调用该参数对象的addAttribute()
方法封装数据:
后续,在页面中需要显示数据时,通过Thymeleaf表达式来显示数据即可:
完成后,重启项目,在登录时分别使用错误的用户名和错误的密码即可看到执行效果!
10. 重定向
在SpringMVC中,当控制器处理请求的方法的返回值类型是String
且没有添加@ResponseBody
时,返回值使用redirect:目录路径
即可实现重定向,例如:
1. 关于Session
通常,会使用Session来保存:
-
用户身份的唯一标识,例如用户的ID、用户名、手机号码等具有“唯一”特点的数据;
-
高使用频率的数据,例如用户名、用户的头像、用户的等级等经常需要使用的数据;
-
其它不便于使用其它技术处理存取的应用场景。
另外,Session在以下情况会消失/不可用:
-
超时;
-
浏览器关闭;
-
服务器关闭。
在SpringMVC框架中,当需要使用Session时,只需要在处理请求的方法的参数列表中添加HttpSession
类型的参数即可,例如:
当向Session中存入数据后,后续的访问中就可以从Session中取出此前存入的数据,例如:
包括在Thymeleaf的模版页面中也可以显示Session中的数据,例如:
2. SpringMVC拦截器(Interceptor)的基本使用
在一个项目中,需要登录以后才可以进行的访问的种类可能非常多,如果在各个处理请求的方法中都添加判断语句进行判断,则这段代码将大量的出现在项目中,操作麻烦且不利于管理和维护!使用拦截器就可以很方便的解决这个问题。
要使用拦截器,必须先自定义类,实现HandlerInterceptor
接口,并添加接口中定义的3个方法:
package cn.tedu.springmvc;
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("LoginInterceptor.preHandle");
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("LoginInterceptor.postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("LoginInterceptor.afterCompletion");
}
}
仅仅创建了拦截器是不够,在SpringMVC中拦截器还需要进行配置后才可以使用,则需要创建配置类,例如创建SpringMvcConfigurer
实现WebMvcConfigurer
接口,重写接口中的addInterceptors()
方法进行配置:
@Configuration
public class SpringMvcConfigurer implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 创建自定义的拦截器对象
LoginInterceptor loginInterceptor = new LoginInterceptor();
// 添加注册拦截器
registry.addInterceptor(loginInterceptor)
// 添加要拦截的路径
.addPathPatterns("/", "/index.html");
}
}
完成后,重启项目,在浏览器中访问主页,结果在浏览器中显示一片空白,并且,在IntelliJ IDEA的控制台可以看到:
在拦截器中的preHandle()
方法的返回值决定了“阻止”或是“放行”,例如,将返回值改为true
:
再次执行,页面是可以正常打开的,并且,在IntelliJ IDEA的控制台可以看到:
通过以上运行效果和输出结果可以看到,拦截器中的preHandle()
方法是在控制器之前执行的,是真正起到“拦截”作用的方法,而postHandle()
和afterCompletion()
是在控制器之后执行的,并不能真正的“拦截”控制器执行!所以,可以在preHandle()
方法中添加一些判断标准,以决定当前请求是否允许执行,例如:
3. SpringMVC拦截器的配置
在配置拦截器时,当添加了拦截器对象后,可以调用返回结果的addPathPatterns()
方法来配置需要“拦截”的请求路径,例如:
注意:在拦截器中配置的所有路径都必须使用/
作为第1个字符!
以上addPathPatterns()
方法的源代码为:
可以看到,addPathPatterns()
方法被重载了2次,可以使用List<String>
或String...
作为参数,无论使用哪种参数格式,都可以配置多个路径被“拦截”,并且,在配置路径时,可以使用*
作为通配符!
例如,将/user/*
配置为拦截路径时,如果客户端提交的请求路径是/user/info
或/user/password
都会被拦截!需要注意,在SpringMVC拦截器的路径中,1个星号只能通配当前层级的资源名,不可以通配多个层级,例如配置为/user/*
时就不可以匹配到/user/info/change
这样的路径!如果需要通配多个层级,必须使用2个连续的星号,例如配置为/user/**
就可以匹配到/user/info
或/user/info/change
或/user/list/2020/10
等……
如果大量使用通配符,就可能导致匹配的范围多大!例如配置为/user/*
或/user/**
时,可以匹配/user/info
、/user/password
,也可以匹配到/user/register
、/user/login
……其实,在项目中,必然存在某些请求路径的前半部分相同,后半部分不同的多个路径中,有些是需要拦截的,而有些并不需要拦截!对于这种情况,可以调用excludePathPatterns()
方法来添加“例如”,也就是不拦截的请求路径!例如配置为:
以上excludePathPatterns()
方法也被重载了2次,同样支持List<String>
和String...
类型的参数!
注意:当同时配置拦截路径和例如时,必须先配置拦截路径,后配置例外!
另外,同一个项目中是可以同时创建并使用多个拦截器的,当某个请求路径会被多个拦截器拦截时,必须每个拦截器都放行,才可以执行到控制器中,且各拦截器的执行先后顺序取决于“注册”时的顺序!
注意:使用拦截器的目的并不一定是全部要检查是否能够继续向后执行,只要项目中有若干个请求路径都执行相同的任务,就可以使用拦截器!
4. 关于@RequestMapping
注解
在SpringMVC框架中,在处理请求的方法之前添加@RequestMapping
,可以用于配置请求路径与处理请求的方法之间的绑定关系!
除了在方法的声明之前添加该注解以外,还可以将该注解添加到类的声明之前,
当在类的声明之前添加了该注解后,这个类中配置的各路径都需要添加以上配置的前缀,例如原本是通过 http://localhost/index.html 来访问主页,现在就需要改为 http://localhost/user/index.html !
在实际项目开发中,推荐为每一个控制器类的声明之前配置@RequestMapping
注解,用于配置当前类中处理请求的方法的URL的前缀!
在配置@RequestMapping
中的URL时,URL值的两端多余的/
是可以忽略的,例如:
序号 | 类的声明之前的配置 | 方法的声明之前的配置 |
---|---|---|
1 | /user | /list |
2 | /user | list |
3 | /user/ | /list |
4 | /user/ | list |
5 | user | /list |
6 | user | list |
7 | user/ | /list |
8 | user/ | list |
以上8种配置的组合是完全等效的!推荐使用以上第1种!
关于@RequestMapping
注解的源代码片段:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Mapping
public @interface RequestMapping {
// 其它代码
}
可以看到在@RequestMapping
的声明之前还添加了@Target
、@Retention
等注解,表示当前@RequestMapping
同时具有以上4个注解配置的特性!
在源代码中还有:
/**
* Assign a name to this mapping.
* <p><b>Supported at the type level as well as at the method level!</b>
* When used on both levels, a combined name is derived by concatenation
* with "#" as separator.
* @see org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder
* @see org.springframework.web.servlet.handler.HandlerMethodMappingNamingStrategy
*/
String name() default "";
以上name()
是注解中的属性,所以,在使用@RequestMapping
时,可以配置名为name
的属性,且该属性的值是String
类型的,例如,可以配置为:
@RequestMapping(name = "Test Name")
以上源代码中的default ""
表示该属性的默认值是""
(空字符串)。
另外,还可以通过该属性的声明之前的注释来尝试理解该属性的作用,例如name
属性的作用就是:Assign a name to this mapping.
所以,这条属性没有任何实质的作用。
在源代码中还有:
/**
* The primary mapping expressed by this annotation.
* <p>This is an alias for {@link #path}. For example,
* {@code @RequestMapping("/foo")} is equivalent to
* {@code @RequestMapping(path="/foo")}.
* <p><b>Supported at the type level as well as at the method level!</b>
* When used at the type level, all method-level mappings inherit
* this primary mapping, narrowing it for a specific handler method.
* <p><strong>NOTE</strong>: A handler method that is not mapped to any path
* explicitly is effectively mapped to an empty path.
*/
@AliasFor("path")
String[] value() default {};
以上代码表示了:在注解中可以使用value
这个属性,属性值是String[]
类型的,默认值是{}
。
注意:在注解中,value
属性是默认的属性名,在配置时,如果该注解中只配置这1个属性,可以不必显式的指定该属性名,例如:
@RequestMapping(value={"a", "b", "c"})
@RequestMapping({"a", "b", "c"})
以上2种配置是完全等效的!
注意:在注解中,配置属性的值时,如果值类型是数组类型的,当需要配置的值只有1个值时,直接使用数组元素类型的值即可!例如:
@RequestMapping({"a"})
@RequestMapping("a")
以上2种配置是完全等效的!
以上源代码中还有@AliasFor("path")
表示当前value
属性与path
属性是完全等效的!所以,还有如下源代码:
/**
* The path mapping URIs (e.g. {@code "/profile"}).
* <p>Ant-style path patterns are also supported (e.g. {@code "/profile/**"}).
* At the method level, relative paths (e.g. {@code "edit"}) are supported
* within the primary mapping expressed at the type level.
* Path mapping URIs may contain placeholders (e.g. <code>"/${profile_path}"</code>).
* <p><b>Supported at the type level as well as at the method level!</b>
* When used at the type level, all method-level mappings inherit
* this primary mapping, narrowing it for a specific handler method.
* <p><strong>NOTE</strong>: A handler method that is not mapped to any path
* explicitly is effectively mapped to an empty path.
* @since 4.2
*/
@AliasFor("value")
String[] path() default {};
在源代码中,还有:
/**
* The HTTP request methods to map to, narrowing the primary mapping:
* GET, POST, HEAD, OPTIONS, PUT, PATCH, DELETE, TRACE.
* <p><b>Supported at the type level as well as at the method level!</b>
* When used at the type level, all method-level mappings inherit this
* HTTP method restriction.
*/
RequestMethod[] method() default {};
以上源代码表示:在@RequestMapping
注解中可以配置名为method
的属性,值的类型是RequestMethod
数组类型,默认值为空!
以上method
属性用于限制请求方式,当没有配置该属性的值时,无论哪种请求方式都是允许的,如果配置为某1种请求方式,则只有这种请求方式是允许的,其它请求方式将导致405
错误,例如配置为:
@RequestMapping(path="/login", method=RequestMethod.POST)
则只允许通过POST类型的请求对/login
对应的URL进行访问!
5. 关于@RequestMapping
的进阶版注解
在SpringMVC框架中还定义了@GetMapping
注解,其源代码是:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@RequestMapping(method = RequestMethod.GET)
public @interface GetMapping {
/**
* Alias for {@link RequestMapping#name}.
*/
@AliasFor(annotation = RequestMapping.class)
String name() default "";
// ...
}
所以,@GetMapping
就是一个已经将请求类型限制为GET
类型的@RequestMapping
注解!
与之类似的还有@PostMapping
、@PutMapping
、@DeleteMapping
等。
6. 关于@Controller
注解
@Controller
是Spring框架定义的注解,在Spring框架的作用范围内,它与@Component
、@Service
、@Repository
这几个注解是完全等效的!
但是,在SpringMVC中,控制器类必须添加@Controller
注解,不可以使用@Component
等3个中的某1个。
在实际开发中,还经常会使用到@RestController
注解,也是可以添加在控制器类的声明之前的,其源代码为:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Controller
@ResponseBody
public @interface RestController {
// ...
}
可以看到,@RestController
注解同时具有@Controller
和@ResponseBody
的效果!
7. 关于@ResponseBody
注解
如果在控制器类的处理请求的方法的声明之前添加@ResponseBody
注解,表示该方法将“响应正文”,则方法的返回值会响应到客户端去!
如果在控制器类的声明之前添加@ResponseBody
注解,表示该类中所有处理请求的方法都将“响应正文”!
目前,服务器端向客户端响应正文是主流的开发模式!
通常,响应到客户端的数据是需要一定的格式的,例如,当需要向客户端响应某个用户的详情时,用户详情中包含用户名、密码、年龄、手机、邮箱等数据,但是,方法的返回值却只有1个,不可能响应为这样的数据:
root12342513800138001root@tedu.cn
所以,响应到客户端的数据必须是有一定格式的,例如,可以把数据组织为JSON格式的字符串:
{
"username":"root",
"password":"1234",
"age":25,
"phone":"13800138001",
"email":"root@tedu.cn"
}
在SpringMVC中,如果要向客户端响应JSON格式的数据,需要将数据的属性封装在某个类中,例如以上JSON数据中就包含username
等5个属性,那就需要将这5个属性放在某个类中,然后,将这个类作为处理请求的方法的返回值类型即可:
为了正常演示接下来的效果,先禁用拦截器,将拦截器的配置类
SpringMvcConfigurer
的声明之前的@Configuration
删除即可,并且,务必保证当前处理请求的方法是响应正文的。
在SpringMVC框架中,当需要响应正文时,SpringMVC框架会通过“转换器”(Converter)将处理请求的方法返回的结果转换为响应到客户端的数据,并且,SpringMVC框架内置了多个不同的转换器,针对不同类型的返回值会自动使用不同的转换器,例如,当返回值类型是String
时,就会自动使用StringHttpMessageConverter
转换器……当然,肯定存在一些类型是SpringMVC框架的设计者没有预料到的,例如框架的使用者自定义的数据类型,当处理请求的方法的返回值类型是这些种类,且当前项目中添加jackson-databind
的依赖时(SpringBoot项目默认已添加),SpringMVC框架就会自动使用jackson-databind
中的转换器,而jackson-databind
的转换器的工作方式就是将对象转换为JSON格式的字符串,并且,还将响应头(Response Headers)中的Content-Type
设置为application/json
,使得客户端程序接收到该数据时能够明确数据的类型。
【小结】SpringMVC框架小结
-
【理解】SpringMVC框架的主要作用:
-
接收请求,处理响应结果;
-
-
【掌握】创建控制器类:
-
在SpringBoot项目的根包或其子孙包中创建类,在类的声明之前添加
@Controller
或@RestController
注解;
-
-
【掌握】接收客户端的请求:
-
在处理请求的方法之前添加
@RequestMapping
或@GetMapping
等注解,在注解中配置value
/path
参数;
-
-
【掌握】自定义方法处理客户端提交的请求,关于方法的声明:
-
【访问权限】应该使用
public
权限; -
【返回值类型】当需要转发或重定向时,应该使用
String
作为返回值类型,当需要响应JSON结果时,应该使用自定义类作为返回值类型; -
【方法名称】自定义;
-
【参数列表】可以按需添加
HttpServletRequest
、HttpServletResponse
、HttpSession
、ModelMap
,及客户端提交的请求参数,或封装了客户端提交的请求参数的类型的对象。
-
-
【掌握】接收客户端提交的请求参数
-
将客户端提交的请求参数设计为处理请求的方法的参数;
-
【推荐】将客户端提交的请求参数封装在自定义类中(各属性需要有匹配的SETTERS、GETTERS方法),使用自定义类作为方法的参数。
-
-
【掌握】转发
-
需要添加Thymeleaf依赖(如果使用其它视图,可能需要添加其它依赖);
-
使用
String
作为处理请求的方法的返回值类型,并保证返回的字符串与/templates/
、.html
能拼接出HTML页面的位置; -
如果转发时需要封装数据,需要在方法的参数列表中添加
ModelMap
参数,并在转发之前将数据封装在ModelMap对象
中。
-
-
【掌握】重定向
-
使用
String
作为处理请求的方法的返回值类型,返回redirect:目标路径
字符串。
-
-
【掌握】响应正文
-
使用
@RestController
注解,或使用@ResponseBody
注解; -
使用自定义类作为返回值类型即可响应JSON格式的字符串。
-
-
【掌握】拦截器
-
自定义类实现
HandlerInterceptor
接口,主要重写其中的preHandle()
方法; -
自定义类实现
WebMvcConfigurer
接口,在类的声明之前添加@Configruation
注解,重写addInterceptors()
方法以注册并配置拦截器; -
通过
addPathPatterns()
配置拦截路径,通过excludePathPatterns()
方法配置例外路径。
-
-
【掌握】学会阅读注解的源代码,了解注解参数的配置方式。