赞
踩
SpringMVC是一种基于Java实现MVC模型的轻量级web框架
入门案例
创建一个Maven项目,在pom.xml中导入依赖
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
-
- <groupId>com.spark</groupId>
- <artifactId>springmvc-start</artifactId>
- <version>1.0-SNAPSHOT</version>
-
- <properties>
- <maven.compiler.source>8</maven.compiler.source>
- <maven.compiler.target>8</maven.compiler.target>
- </properties>
- <dependencies>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>5.2.10.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>3.1.0</version>
- <scope>provided</scope>
- </dependency>
- </dependencies>
- </project>

编写表现层Controller
- package com.spark.controller;
-
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.ResponseBody;
-
- /**
- * UserController class
- * description: UserController
- *
- * @author Administrator
- * @date 2023/7/26
- */
- @Controller
- public class UserController {
-
- // 提供方法的请求路径
- @RequestMapping("/save")
- @ResponseBody
- public String saveUser(){
- System.out.println("user save ...");
- return "{module:save}";
- }
- }

编写SpringMVC配置类加载Controller层注册的Bean
- package com.spark.config;
-
- import org.springframework.context.annotation.ComponentScan;
- import org.springframework.context.annotation.Configuration;
-
- /**
- * SpringmvcConfig class
- * description: SpringMvcConfig
- *
- * @author Administrator
- * @date 2023/7/26
- */
- @Configuration
- @ComponentScan("com.spark.controller")
- public class SpringMvcConfig {
-
- }

编写Servlet容器配置类加载SpringMVC配置类
- package com.spark.config;
-
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.context.WebApplicationContext;
- import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
- import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
-
- /**
- * ServletInitConfig class
- * description: ServletInitConfig
- *
- * @author Administrator
- * @date 2023/7/26
- */
- @Configuration
- public class ServletInitConfig extends AbstractDispatcherServletInitializer {
-
- @Override
- protected WebApplicationContext createServletApplicationContext() {
- AnnotationConfigWebApplicationContext atx = new AnnotationConfigWebApplicationContext();
- atx.register(SpringMvcConfig.class);
- return atx;
- }
-
- @Override
- protected String[] getServletMappings() {
- // 所有请求
- return new String[] {"/"};
- }
-
- @Override
- protected WebApplicationContext createRootApplicationContext() {
- return null;
- }
- }

配置Tomcat
打开浏览器访问 URL + Controller定义的方法请求路径查看结果
http://localhost:8082/springmvc_start/save
入门案例的工作流程
① 服务器启动初始化流程
② 发送save请求过程
一个完整的SpringMVC请求涉及到有表现层(Controller)、数据层(Dao)、业务层(Service)
Controller层由SpringMVC加载,业务层和数据层由Spring加载
Web容器启动后,Spring会加载到SpringMVC的bean,如何进行避免?
加载Spring控制的bean时排除掉SpringMVC控制的bean
方式一:Spring加载的bean设定扫描范围,并排除掉Controller包内的bean
- package com.spark.config;
-
- import org.springframework.context.annotation.ComponentScan;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.FilterType;
-
- /**
- * SpringConfig class
- * description: SpringConfig
- *
- * @author Administrator
- * @date 2023/7/26
- */
- @Configuration
- // 方式一:排除掉Controller层,排除规则为注解方式
- @ComponentScan(value = "com.spark",
- excludeFilters = @ComponentScan.Filter(
- type = FilterType.ANNOTATION
- )
- )
- public class SpringConfig {
- }

方式二:Spring加载的bean设定扫描范围为精确范围
- package com.spark.config;
-
- import org.springframework.context.annotation.ComponentScan;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.FilterType;
-
- /**
- * SpringConfig class
- * description: SpringConfig
- *
- * @author Administrator
- * @date 2023/7/26
- */
- @Configuration
- // 方式二:设定精确的扫描范围
- @ComponentScan({"com.spark.dao","com.spark.service"})
- public class SpringConfig {
- }

在Servlet容器配置类中注册Spring配置类
- package com.spark.config;
-
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.context.WebApplicationContext;
- import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
- import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
-
- /**
- * ServletInitConfig class
- * description: ServletInitConfig
- *
- * @author Administrator
- * @date 2023/7/26
- */
- @Configuration
- public class ServletInitConfig extends AbstractDispatcherServletInitializer {
-
- @Override
- protected WebApplicationContext createServletApplicationContext() {
- AnnotationConfigWebApplicationContext atx = new AnnotationConfigWebApplicationContext();
- atx.register(SpringMvcConfig.class);
- return atx;
- }
-
- @Override
- protected String[] getServletMappings() {
- // 所有请求
- return new String[] {"/"};
- }
-
- @Override
- protected WebApplicationContext createRootApplicationContext() {
- // 注册Spring配置类
- AnnotationConfigWebApplicationContext atx = new AnnotationConfigWebApplicationContext();
- atx.register(SpringConfig.class);
- return atx;
- }
- }

拓展:简化开发Servlet容器配置类
- package com.spark.config;
-
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
-
- /**
- * ServletInitConfig class
- * description: ServletInitConfig
- *
- * @author Administrator
- * @date 2023/7/26
- */
- @Configuration
- public class ServletInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer{
-
- @Override
- protected Class<?>[] getRootConfigClasses() {
- // 注册Spring配置类
- return new Class[]{SpringConfig.class};
- }
-
- @Override
- protected Class<?>[] getServletConfigClasses() {
- // 注册SpringMVC配置类
- return new Class[]{SpringMvcConfig.class};
- }
-
- @Override
- protected String[] getServletMappings() {
- // 所有请求
- return new String[]{"/"};
- }
- }

Postman是一款功能强大的网页调试与发送网页Http请求的Chrome插件,常用于进行接口测试
下载地址:https://www.postman.com/downloads/
安装完成后,打开让选择注册用户,可以不进行注册,关闭重新打开就可以进入
启动入门案例IDEA中配置的Tomcat,输入Controller层方法配置的接口地址,查看响应结果
团队多人开发,每个人设置不同的请求路径,有可能会出现冲突,当多人的请求路径相同时,项目启动会出现错误。
通常会在请求路径前设置模块名作为请求路径前缀来解决问题
设置请求路径使用@RequestMapping注解,该注解可以用在类或方法上,前缀一般设置在Controller类上
- package com.spark.controller;
-
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.ResponseBody;
-
- /**
- * UserController class
- * description: UserController
- *
- * @author Administrator
- * @date 2023/7/26
- */
- @Controller
- // 设置前缀,一般使用模块名
- @RequestMapping("/user")
- public class UserController {
-
- // 提供方法的请求路径
- @RequestMapping("/save")
- @ResponseBody
- public String saveUser(){
- System.out.println("user save ...");
- return "{module:save}";
- }
- }

创建一个新的Maven项目,在Controller层添加一个方法用于展示请求传递的参数
- package com.spark.controller;
-
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.ResponseBody;
-
- /**
- * UserController class
- * description: UserController
- *
- * @author Administrator
- * @date 2023/7/26
- */
- @Controller
- // 设置前缀,一般使用模块名
- @RequestMapping("/user")
- public class UserController {
-
- // 接收请求参数
- @RequestMapping("/commonParams")
- @ResponseBody
- public String commonParams(String name,int age){
- System.out.println("普通参数name===>"+name);
- System.out.println("普通参数age===>"+age);
- return "{module:commonParams}";
- }
- }

① GET请求传参
普通参数:URL地址传参,地址参数名与形参变量名相同,定义形参即可接收参数
② POST请求传参
普通参数:使用form表单进行传参,表单参数名与形参变量名相同,定义形参即可接收参数
传递中文会出现乱码问题,需要在Servlet容器配置类中添加过滤器配置,处理中文乱码
- package com.spark.config;
-
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.filter.CharacterEncodingFilter;
- import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
-
- import javax.servlet.Filter;
-
- /**
- * ServletInitConfig class
- * description: ServletInitConfig
- *
- * @author Administrator
- * @date 2023/7/26
- */
- @Configuration
- public class ServletInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer{
-
- @Override
- protected Class<?>[] getRootConfigClasses() {
- // 注册Spring配置类
- return new Class[]{SpringConfig.class};
- }
-
- @Override
- protected Class<?>[] getServletConfigClasses() {
- // 注册SpringMVC配置类
- return new Class[]{SpringMvcConfig.class};
- }
-
- @Override
- protected String[] getServletMappings() {
- // 所有请求
- return new String[]{"/"};
- }
-
- // 添加过滤器配置
- @Override
- protected Filter[] getServletFilters() {
- CharacterEncodingFilter filter = new CharacterEncodingFilter();
- // 设置字符编码
- filter.setEncoding("UTF-8");
- return new Filter[]{filter};
- }
- }

① 普通参数传递
普通参数传递要求形参与传参的参数名一致,如果不一致,需要使用@RequestParam注解指定传参的参数名
举例:形参列表的参数名为userName,传参的参数名为name
- // 接收请求参数
- @RequestMapping("/commonParams")
- @ResponseBody
- // 将传参的name属性值赋值给形参的userName
- public String commonParams(@RequestParam("name") String userName){
- System.out.println("普通参数userName===>"+userName);
- return "{module:commonParams}";
- }
② POJO类型参数传递
POJO参数传递要求请求参数名与形参对象属性名相同,定义POJO类型参数即可接收参数,将请求参数封装为实体类
- package com.spark.entity;
-
- /**
- * UserEntity class
- * description: UserEntity
- *
- * @author Administrator
- * @date 2023/7/30
- */
- public class UserEntity {
-
- private String userName;
-
- private int age;
-
- public String getUserName() {
- return userName;
- }
-
- public void setUserName(String userName) {
- this.userName = userName;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- @Override
- public String toString() {
- return "UserEntity{" +
- "userName='" + userName + '\'' +
- ", age=" + age +
- '}';
- }
- }

Controller层定义方法
- // 接收POJO参数
- @RequestMapping("/pojoParams")
- @ResponseBody
- public String pojoParams(UserEntity user){
- System.out.println("user:::"+user);
- return "{module:pojoParams}";
- }
③ 嵌套POJO类型参数传递
当实体类中包含其他实体类情况下,请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数
添加Address实体类
- package com.spark.entity;
-
- /**
- * AddressEntity class
- * description: AddressEntity
- *
- * @author Administrator
- * @date 2023/7/30
- */
- public class AddressEntity {
-
- private String city;
-
- public String getCity() {
- return city;
- }
-
- public void setCity(String city) {
- this.city = city;
- }
-
- @Override
- public String toString() {
- return "AddressEntity{" +
- "city='" + city + '\'' +
- '}';
- }
- }

UserEntity实体类中添加AddressEntity实体类
- package com.spark.entity;
-
- /**
- * UserEntity class
- * description: UserEntity
- *
- * @author Administrator
- * @date 2023/7/30
- */
- public class UserEntity {
-
- private String userName;
-
- private int age;
-
- private AddressEntity address;
-
- public String getUserName() {
- return userName;
- }
-
- public void setUserName(String userName) {
- this.userName = userName;
- }
-
- public int getAge() {
- return age;
- }
-
- public void setAge(int age) {
- this.age = age;
- }
-
- public AddressEntity getAddress() {
- return address;
- }
-
- public void setAddress(AddressEntity address) {
- this.address = address;
- }
-
- @Override
- public String toString() {
- return "UserEntity{" +
- "userName='" + userName + '\'' +
- ", age=" + age +
- ", address=" + address +
- '}';
- }
- }

Controller层定义方法
- // 接收嵌套POJO参数
- @RequestMapping("/pojoNestParams")
- @ResponseBody
- public String pojoNestParams(UserEntity user){
- System.out.println("user:::"+user);
- return "{module:pojoParams}";
- }
④ 数组类型参数传递
请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型形参即可接收参数
Controller层定义方法
- // 接收数组类型参数
- @RequestMapping("/arrayParams")
- @ResponseBody
- public String arrayParams(String [] likes){
- System.out.println(Arrays.toString(likes));
- return "{module:arrayParams}";
- }
⑤ 集合参数传递
请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系
Controller层定义方法
- // 接收集合类型参数
- @RequestMapping("/listParams")
- @ResponseBody
- public String listParams(@RequestParam List<String>likes){
- System.out.println(likes);
- return "{module:listParams}";
- }
集合类型参数加@RequestParam原因是因为系统会默认将List看做为引用数据类型,会去调用其构造方法去初始化,List类型为接口没有构造方法
在项目中数据传递一般是使用的是json对象和json数组。
① 实现json对象传递
pom.xml中引入依赖
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>2.9.0</version>
- </dependency>
在SpringMVC配置类中开启json转换为实体
- package com.spark.config;
-
- import org.springframework.context.annotation.ComponentScan;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-
- /**
- * SpringmvcConfig class
- * description: SpringMvcConfig
- *
- * @author Administrator
- * @date 2023/7/26
- */
- @Configuration
- @ComponentScan("com.spark.controller")
- @EnableWebMvc
- public class SpringMvcConfig {
-
- }

Controller层定义方法
- // 接收json类型参数
- @RequestMapping("/jsonParams")
- @ResponseBody
- public String jsonParams(@RequestBody UserEntity user){
- System.out.println(user);
- return "{module:jsonParams}";
- }
@RequestBody将请求中请求体包含的数据传递给请求参数,此注解一个处理器方法只能用一次
Postman发送请求
② json数组参数传递
Controller层定义方法
- // 接收json类型参数
- @RequestMapping("/jsonArrayParams")
- @ResponseBody
- public String jsonArrayParams(@RequestBody List<UserEntity> users){
- System.out.println(users);
- return "{module:jsonArrayParams}";
- }
Postman发送请求
@RequestParam和@RequestBody
区别
应用
日期类型基于系统不同格式也不尽相同
接收形参时,根据不同的日期格式设置不同的接收方式
- // 接收日期类型参数
- @RequestMapping("/dateParams")
- @ResponseBody
- public String dateParams(Date date,
- @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date date2){
- System.out.println("Date:"+date);
- System.out.println("Date2:"+date2);
- return "{module:dateParams}";
- }
@DateTimeFormat设置日期类型数据格式
REST表现形式状态转换
传统风格资源描述形式
REST风格描述形式
优点:隐藏资源的访问行为,无法通过地址得知对资源是何种操作,书写简化
按照REST风格访问资源时使用行为动作区分对资源进行了何种操作,常用的有四种
根据REST风格对资源进行访问称为RestFul
使用REST风格约定请求动作,编写表现层Controller
- package com.spark.controller;
-
- import com.spark.entity.UserEntity;
- import org.springframework.stereotype.Controller;
- import org.springframework.web.bind.annotation.RequestBody;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.ResponseBody;
-
- /**
- * RestController class
- * description: RestController
- *
- * @author Administrator
- * @date 2023/7/31
- */
- @Controller
- @RequestMapping("/users")
- public class RestController {
-
- // 约定save方法的请求动作为POST
- @RequestMapping(value = "/save",method = RequestMethod.POST)
- @ResponseBody
- public String save(@RequestBody UserEntity user){
- System.out.println(user);
- return "{module:save}";
- }
- // 约定delete方法的请求动作为DELETE
- @RequestMapping(value = "/delete",method = RequestMethod.DELETE)
- @ResponseBody
- public String delete(Integer id){
- System.out.println("user id===>"+id);
- return "{module:delete}";
- }
- }

当规定了行为动作后,使用其他方式访问接口会报请求方式不支持异常
地址传参,使用DELETE方式访问却报404
使用路径传参时,方法的形参列表需要使用@PathVariable表明值从url获取
改写delete方法
- // 约定delete方法的请求动作为DELETE
- // url指定参数名
- @RequestMapping(value = "/delete/{id}",method = RequestMethod.DELETE)
- @ResponseBody
- // 使用@PathVariable注解表明参数从url获取
- public String delete(@PathVariable Integer id){
- System.out.println("user id===>"+id);
- return "{module:delete}";
- }
@RestController注解是@Controller和@ResponseBody的复合注解,以后在表现层只需要使用@RestController注解就可以管理该类并且方法结果都可以原样返回
@RequestMapping中的method属性指明行为动作,也可以使用具体的注解进行简化开发
- package com.spark.controller;
-
- import org.springframework.web.bind.annotation.*;
-
- /**
- * RestController class
- * description: RestController
- *
- * @author Administrator
- * @date 2023/7/31
- */
- @RestController
- @RequestMapping("/books")
- public class RestfulController {
-
- @GetMapping("/allBooks")
- public String getAllBooks() {
- return "{module:getAllBooks}";
- }
- @PostMapping("/saveBooks")
- public String saveBooks(){
- return "{module:saveBooks}";
- }
- @PutMapping("/updateBook")
- public String updateBook(){
- return "{module:updateBook}";
- }
- @DeleteMapping("/deleteBook")
- public String deleteBook(){
- return "{module:deleteBook}";
- }
- }

使用web模版创建一个Maven项目,在pom.xml中引入依赖
- <dependencies>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-webmvc</artifactId>
- <version>5.2.10.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- <version>5.2.10.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-jdbc</artifactId>
- <version>5.2.10.RELEASE</version>
- </dependency>
- <dependency>
- <groupId>org.mybatis</groupId>
- <artifactId>mybatis-spring</artifactId>
- <version>2.0.6</version>
- </dependency>
- <dependency>
- <groupId>org.mybatis</groupId>
- <artifactId>mybatis</artifactId>
- <version>3.5.6</version>
- </dependency>
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>druid</artifactId>
- <version>1.2.8</version>
- </dependency>
- <dependency>
- <groupId>mysql</groupId>
- <artifactId>mysql-connector-java</artifactId>
- <version>5.1.49</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- <version>2.13.1</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>2.13.1</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- <version>2.13.1</version>
- </dependency>
- <dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>3.1.0</version>
- <scope>provided</scope>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.12</version>
- </dependency>
- </dependencies>

resources目录下新建jdbc.properties文件,写入MySQL连接信息
- jdbc.driver = com.mysql.jdbc.Driver
- jdbc.url = jdbc:mysql://localhost:3306/ssm_db
- jdbc.username = root
- jdbc.password = root
编写JDBC配置类
- package com.spark.config;
-
- import com.alibaba.druid.pool.DruidDataSource;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Bean;
-
- import javax.sql.DataSource;
-
- /**
- * JdbcConfig class
- * description: JdbcConfig
- *
- * @author Administrator
- * @date 2023/8/3
- */
- public class JdbcConfig {
-
- @Value("${jdbc.driver}")
- private String driver;
- @Value("${jdbc.url}")
- private String url;
- @Value("${jdbc.username}")
- private String username;
- @Value("${jdbc.password}")
- private String password;
-
- // 注册数据源
- @Bean
- public DataSource getDataSource(){
- DruidDataSource dataSource = new DruidDataSource();
- dataSource.setDriverClassName(driver);
- dataSource.setUrl(url);
- dataSource.setUsername(username);
- dataSource.setPassword(password);
- return dataSource;
- }
- }

编写Mybatis配置类
- package com.spark.config;
-
- import org.mybatis.spring.SqlSessionFactoryBean;
- import org.mybatis.spring.mapper.MapperScannerConfigurer;
- import org.springframework.context.annotation.Bean;
-
- import javax.sql.DataSource;
-
- /**
- * MybatisConfig class
- * description: MybatisConfig
- *
- * @author Administrator
- * @date 2023/8/3
- */
- public class MybatisConfig {
-
- // 获取SqlSessionFactory
- @Bean
- public SqlSessionFactoryBean getSqlSessionFactoryBean(DataSource dataSource) {
- SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
- sqlSessionFactoryBean.setDataSource(dataSource);
- // 扫描entity包
- sqlSessionFactoryBean.setTypeAliasesPackage("com.spark.entity");
- return sqlSessionFactoryBean;
- }
-
- // 映射dao
- @Bean
- public MapperScannerConfigurer mapperScannerConfigurer(){
- MapperScannerConfigurer configurer = new MapperScannerConfigurer();
- configurer.setBasePackage("com.spark.dao");
- return configurer;
- }
- }

编写Spring和SpringMVC配置类
- package com.spark.config;
-
- import org.springframework.context.annotation.ComponentScan;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.Import;
- import org.springframework.context.annotation.PropertySource;
-
- /**
- * SpringConfig class
- * description: SpringConfig
- *
- * @author Administrator
- * @date 2023/8/3
- */
- @Configuration
- @PropertySource({"classpath:jdbc.properties"})
- @Import({JdbcConfig.class,MybatisConfig.class})
- @ComponentScan({"com.spark.service","com.spark.dao"})
- public class SpringConfig {
- }

- package com.spark.config;
-
- import org.springframework.context.annotation.ComponentScan;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-
- /**
- * SpringMvcConfig class
- * description: SpringMvcConfig
- *
- * @author Administrator
- * @date 2023/8/3
- */
- @Configuration
- @ComponentScan("com.spark.controller")
- @EnableWebMvc
- public class SpringMvcConfig {
- }

编写Servlet容器配置
- package com.spark.config;
-
- import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
-
- /**
- * ServletConfig class
- * description: ServletConfig
- *
- * @author Administrator
- * @date 2023/8/3
- */
- public class ServletConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
- @Override
- protected Class<?>[] getRootConfigClasses() {
- return new Class[]{SpringConfig.class};
- }
-
- @Override
- protected Class<?>[] getServletConfigClasses() {
- return new Class[]{SpringMvcConfig.class};
- }
-
- @Override
- protected String[] getServletMappings() {
- return new String[]{"/"};
- }
- }

数据库创建数据表,并写入数据
- DROP TABLE IF EXISTS `books`;
- CREATE TABLE `books` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `type` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
- `name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
- `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
- PRIMARY KEY (`id`) USING BTREE
- ) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-
- INSERT INTO `books` VALUES (1, '计算机理论', 'Spring实战 第5版', 'Spring入门经典教程,深入理解Spring原理技术内幕');
- INSERT INTO `books` VALUES (2, '计算机理论', 'Spring 5核心原理与30个类手写实战', '十年沉淀之作,手写Spring精华思想');
- INSERT INTO `books` VALUES (3, '计算机理论', 'Spring 5 设计模式', '深入Spring源码剖析Spring源码中蕴含的10大设计模式');
- INSERT INTO `books` VALUES (4, '计算机理论', 'Spring MVC+MyBatis开发从入门到项目实战', '全方位解析面向Web应用的轻量级框架,带你成为Spring MVC开发高手');
- INSERT INTO `books` VALUES (5, '计算机理论', '轻量级Java Web企业应用实战', '源码级剖析Spring框架,适合已掌握Java基础的读者');
- INSERT INTO `books` VALUES (6, '计算机理论', 'Java核心技术 卷I 基础知识(原书第11版)', 'Core Java 第11版,Jolt大奖获奖作品,针对Java SE9、10、11全面更新');
- INSERT INTO `books` VALUES (7, '计算机理论', '深入理解Java虚拟机', '5个维度全面剖析JVM,大厂面试知识点全覆盖');
- INSERT INTO `books` VALUES (8, '计算机理论', 'Java编程思想(第4版)', 'Java学习必读经典,殿堂级著作!赢得了全球程序员的广泛赞誉');
- INSERT INTO `books` VALUES (9, '计算机理论', '零基础学Java(全彩版)', '零基础自学编程的入门图书,由浅入深,详解Java语言的编程思想和核心技术');
- INSERT INTO `books` VALUES (10, '市场营销', '直播就该这么做:主播高效沟通实战指南', '李子柒、李佳琦、薇娅成长为网红的秘密都在书中');
- INSERT INTO `books` VALUES (11, '市场营销', '直播销讲实战一本通', '和秋叶一起学系列网络营销书籍');
- INSERT INTO `books` VALUES (12, '市场营销', '直播带货:淘宝、天猫直播从新手到高手', '一本教你如何玩转直播的书,10堂课轻松实现带货月入3W+');

创建实体类,并编写Dao
- package com.spark.entity;
-
- /**
- * Book class
- * description: Book
- *
- * @author Administrator
- * @date 2023/8/3
- */
- public class Book {
-
- private Integer id;
-
- private String type;
-
- private String name;
-
- private String description;
-
- public Integer getId() {
- return id;
- }
-
- public void setId(Integer id) {
- this.id = id;
- }
-
- public String getType() {
- return type;
- }
-
- public void setType(String type) {
- this.type = type;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- public String getDescription() {
- return description;
- }
-
- public void setDescription(String description) {
- this.description = description;
- }
-
- @Override
- public String toString() {
- return "Book{" +
- "id=" + id +
- ", type='" + type + '\'' +
- ", name='" + name + '\'' +
- ", description='" + description + '\'' +
- '}';
- }
- }

- package com.spark.dao;
-
- import com.spark.entity.Book;
- import org.apache.ibatis.annotations.Delete;
- import org.apache.ibatis.annotations.Insert;
- import org.apache.ibatis.annotations.Select;
- import org.apache.ibatis.annotations.Update;
-
- import java.util.List;
-
- /**
- * BookDao class
- * description: BookDao
- *
- * @author Administrator
- * @date 2023/8/3
- */
- public interface BookDao {
-
- @Insert("insert into books(`type`,`name`,`description`) values(#{type},#{name},#{description})")
- int save(Book book);
- @Update("update books set type=#{type}, name=#{name}, description=#{description} where id = #{id}")
- int update(Book book);
- @Delete("delete from books where id = #{id}")
- int delete(Integer id);
- @Select("select * from books where id = #{id}")
- Book getById(Integer id);
- @Select("select * from books")
- List<Book> getAll();
- }

定义业务层接口方法并编写实现类
- package com.spark.service;
-
- import com.spark.entity.Book;
-
- import java.util.List;
-
- /**
- * BookService class
- * description: BookService
- *
- * @author Administrator
- * @date 2023/8/3
- */
- public interface BookService {
-
- boolean addBook(Book book);
- boolean updateBook(Book book);
- boolean deleteBook(Integer id);
- Book selectById(Integer id);
- List<Book> selectAll();
- }

- package com.spark.service.impl;
-
- import com.spark.dao.BookDao;
- import com.spark.entity.Book;
- import com.spark.service.BookService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
-
- import java.util.List;
-
- /**
- * BookServiceImpl class
- * description: BookServiceImpl
- *
- * @author Administrator
- * @date 2023/8/3
- */
- @Service
- public class BookServiceImpl implements BookService {
-
- @Autowired
- BookDao bookDao;
-
- @Override
- public boolean addBook(Book book) {
- return bookDao.save(book) > 0;
- }
-
- @Override
- public boolean updateBook(Book book) {
- return bookDao.update(book) > 0;
- }
-
- @Override
- public boolean deleteBook(Integer id) {
- return bookDao.delete(id) > 0;
- }
-
- @Override
- public Book selectById(Integer id) {
- return bookDao.getById(id);
- }
-
- @Override
- public List<Book> selectAll() {
- return bookDao.getAll();
- }
- }

编写表现层Controller
- package com.spark.controller;
-
- import com.spark.entity.Book;
- import com.spark.service.BookService;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.*;
-
- import java.util.List;
-
- /**
- * BookController class
- * description: BookController
- *
- * @author Administrator
- * @date 2023/8/3
- */
- @RestController
- @RequestMapping("/books")
- public class BookController {
-
- @Autowired
- private BookService bookService;
-
- @PostMapping("/addBook")
- public String addBook(@RequestBody Book book){
- if(bookService.addBook(book)){
- return "添加成功";
- }else{
- return "添加失败";
- }
- }
- @PutMapping("/updateBook")
- public String updateBook(@RequestBody Book book){
- if(bookService.updateBook(book)){
- return "更新成功";
- }else{
- return "更新失败";
- }
- }
- @DeleteMapping("/deleteBook")
- public String deleteBook(Integer id){
- if(bookService.deleteBook(id)){
- return "删除成功";
- }else{
- return "删除失败";
- }
- }
- @GetMapping("/getById")
- public Book selectById(Integer id){
- return bookService.selectById(id);
- }
- @GetMapping("/getAll")
- public List<Book> selectAll(){
- return bookService.selectAll();
- }
-
- }

编写测试类
- package com.spark;
-
- import com.spark.config.SpringConfig;
- import com.spark.entity.Book;
- import com.spark.service.BookService;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.test.context.ContextConfiguration;
- import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
-
- /**
- * BookServiceTest class
- * description: BookServiceTest
- *
- * @author Administrator
- * @date 2023/8/5
- */
- @RunWith(SpringJUnit4ClassRunner.class)
- @ContextConfiguration(classes = SpringConfig.class)
- public class BookServiceTest {
-
- @Autowired
- BookService bookService;
-
- @Test
- public void testBookInsert(){
- Book book = new Book();
- book.setName("Java从入门到放弃");
- book.setType("计算机");
- book.setDescription("Java从入门到放弃");
- bookService.addBook(book);
- }
-
- @Test
- public void testBookUpdate(){
- Book book = new Book();
- book.setName("Java从入门到放弃 第二版");
- book.setType("计算机");
- book.setDescription("Java从入门到放弃第二版");
- book.setId(13);
- bookService.updateBook(book);
- }
-
- @Test
- public void testBookDelete(){
- bookService.deleteBook(13);
- }
-
- @Test
- public void testBookSelectById(){
- System.out.println(bookService.selectById(1));
- }
-
- @Test
- public void testBookSelectAll(){
- System.out.println(bookService.selectAll());
- }
- }

拓展:开启事务
Spring配置类中使用注解开启事务管理
- package com.spark.config;
-
- import org.springframework.context.annotation.ComponentScan;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.context.annotation.Import;
- import org.springframework.context.annotation.PropertySource;
- import org.springframework.transaction.annotation.EnableTransactionManagement;
-
- /**
- * SpringConfig class
- * description: SpringConfig
- *
- * @author Administrator
- * @date 2023/8/3
- */
- @Configuration
- @PropertySource({"classpath:jdbc.properties"})
- @Import({JdbcConfig.class,MybatisConfig.class})
- @ComponentScan({"com.spark.service","com.spark.dao"})
- // 开启事务
- @EnableTransactionManagement
- public class SpringConfig {
- }

在Jdbc配置类中获取事务管理对象
- package com.spark.config;
-
- import com.alibaba.druid.pool.DruidDataSource;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Bean;
- import org.springframework.jdbc.datasource.DataSourceTransactionManager;
-
- import javax.sql.DataSource;
-
- /**
- * JdbcConfig class
- * description: JdbcConfig
- *
- * @author Administrator
- * @date 2023/8/3
- */
- public class JdbcConfig {
-
- @Value("${jdbc.driver}")
- private String driver;
- @Value("${jdbc.url}")
- private String url;
- @Value("${jdbc.username}")
- private String username;
- @Value("${jdbc.password}")
- private String password;
-
- // 注册数据源
- @Bean
- public DataSource getDataSource(){
- DruidDataSource dataSource = new DruidDataSource();
- dataSource.setDriverClassName(driver);
- dataSource.setUrl(url);
- dataSource.setUsername(username);
- dataSource.setPassword(password);
- return dataSource;
- }
-
- // 数据源事务管理对象
- @Bean
- public DataSourceTransactionManager transactionManager(DataSource dataSource){
- DataSourceTransactionManager ds = new DataSourceTransactionManager();
- ds.setDataSource(dataSource);
- return ds;
- }
- }

在业务层使用事务管理注解
- package com.spark.service;
-
- import com.spark.entity.Book;
- import org.springframework.transaction.annotation.Transactional;
-
- import java.util.List;
-
- /**
- * BookService class
- * description: BookService
- *
- * @author Administrator
- * @date 2023/8/3
- */
- @Transactional
- public interface BookService {
-
- boolean addBook(Book book);
- boolean updateBook(Book book);
- boolean deleteBook(Integer id);
- Book selectById(Integer id);
- List<Book> selectAll();
- }

由于数据传输可能会有多种格式,前端需要分别去解析数据,因此与前端交互时一般需要统一格式。创建结果模型类,封装数据到data属性中,封装操作结果到code属性中,封装特殊消息到message(msg)属性中
- public class Result{
- private String code;
- private String msg;
- private Object data;
- }
Result类字段并不固定,可以根据需要自行增减,提供若干个构造方法,方便操作
定义统一结果类
- package com.spark.util;
-
- /**
- * Result class
- * description: Result
- *
- * @author Administrator
- * @date 2023/8/5
- */
- public class Result {
-
- private String code;
-
- private String msg;
-
- private Object data;
-
- public Result(String code, String msg, Object data) {
- this.code = code;
- this.msg = msg;
- this.data = data;
- }
-
- public String getCode() {
- return code;
- }
-
- public void setCode(String code) {
- this.code = code;
- }
-
- public String getMsg() {
- return msg;
- }
-
- public void setMsg(String msg) {
- this.msg = msg;
- }
-
- public Object getData() {
- return data;
- }
-
- public void setData(Object data) {
- this.data = data;
- }
- }

定义结果类所需的常量
- package com.spark.common;
-
- /**
- * RestCommonContent class
- * description: RestCommonContent
- *
- * @author Administrator
- * @date 2023/8/5
- */
- public class RestCommonContent {
-
- // 定义响应编码和响应信息
- public static final String RESPONSE_SUCCESS = "操作成功!";
- public static final String RESPONSE_ERROR = "操作失败!";
- public static final String RESPONSE_SUCCESS_CODE = "200";
- public static final String RESPONSE_ERROR_CODE = "9999";
- public static final String SELECT_SUCCESS = "查询成功!";
- public static final String SELECT_ERROR = "数据不存在,查询失败!";
-
- // 定义数据常量
- public static final String CONTENT_EMPTY = "";
- public static final String CONTENT_NULL = null;
-
- }

改写表现层Controller
- package com.spark.controller;
-
- import com.spark.common.RestCommonContent;
- import com.spark.entity.Book;
- import com.spark.service.BookService;
- import com.spark.util.Result;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.util.ObjectUtils;
- import org.springframework.web.bind.annotation.*;
-
- import java.util.List;
-
- /**
- * BookController class
- * description: BookController
- *
- * @author Administrator
- * @date 2023/8/3
- */
- @RestController
- @RequestMapping("/books")
- public class BookController {
-
- @Autowired
- private BookService bookService;
-
- @PostMapping("/addBook")
- public Result addBook(@RequestBody Book book){
- if(bookService.addBook(book)){
- return new Result(RestCommonContent.RESPONSE_SUCCESS_CODE,
- RestCommonContent.RESPONSE_SUCCESS,
- true);
- }else{
- return new Result(RestCommonContent.RESPONSE_ERROR_CODE,
- RestCommonContent.RESPONSE_ERROR,
- false);
- }
- }
- @PutMapping("/updateBook")
- public Result updateBook(@RequestBody Book book){
- if(bookService.updateBook(book)){
- return new Result(RestCommonContent.RESPONSE_SUCCESS_CODE,
- RestCommonContent.RESPONSE_SUCCESS,
- true);
- }else{
- return new Result(RestCommonContent.RESPONSE_ERROR_CODE,
- RestCommonContent.RESPONSE_ERROR,
- false);
- }
- }
- @DeleteMapping("/deleteBook")
- public Result deleteBook(Integer id){
- if(bookService.deleteBook(id)){
- return new Result(RestCommonContent.RESPONSE_SUCCESS_CODE,
- RestCommonContent.RESPONSE_SUCCESS,
- true);
- }else{
- return new Result(RestCommonContent.RESPONSE_ERROR_CODE,
- RestCommonContent.RESPONSE_ERROR,
- false);
- }
- }
- @GetMapping("/getById")
- public Result selectById(Integer id){
- Book book = bookService.selectById(id);
- if(ObjectUtils.isEmpty(book)){
- return new Result(RestCommonContent.RESPONSE_ERROR_CODE,
- RestCommonContent.SELECT_ERROR,
- RestCommonContent.CONTENT_EMPTY);
- }
- return new Result(RestCommonContent.RESPONSE_SUCCESS_CODE,
- RestCommonContent.SELECT_SUCCESS,
- book);
- }
- @GetMapping("/getAll")
- public Result selectAll(){
- List<Book> books = bookService.selectAll();
- if(ObjectUtils.isEmpty(books)){
- return new Result(RestCommonContent.RESPONSE_SUCCESS_CODE,
- RestCommonContent.SELECT_SUCCESS,
- RestCommonContent.CONTENT_EMPTY);
- }
- return new Result(RestCommonContent.RESPONSE_SUCCESS_CODE,
- RestCommonContent.SELECT_SUCCESS,
- books);
- }
-
- }

开发中避免不了会遇到异常现象,如果不做处理,前端页面获取错误信息时拿到的是错误页面,无法进行解析,此时需要对异常进行统一处理
出现异常现象的常见位置与常见诱因如下
Spring提供了异常处理器,集中的、统一的处理项目中出现的异常
- @RestControllerAdvice
- public class ProjectExceptionAdvice{
- @ExceptionHandler(Exception.class)
- public Result doException(Exception ex){
- // 处理异常返回结果
- }
- }
@ExceptionHandler专用于异常处理的控制器方法上方,设置指定异常的处理方案,功能等同于控制器方法,出现异常后终止原始控制器执行,并转入当前方法执行
项目异常分类
业务异常(BusinessException)
系统异常(SystemException)
其他异常(Exception)
项目异常处理
编写业务异常类和系统异常类
- package com.spark.exception;
-
- /**
- * BusinessException class
- * description: BusinessException
- *
- * @author Administrator
- * @date 2023/8/5
- */
- public class BusinessException extends RuntimeException{
-
- private String code; // 错误编码
-
- private String tranCode; // 交易码(接口号)
-
-
- public BusinessException(String code, String message, String tranCode) {
- super(message);
- this.code = code;
- this.tranCode = tranCode;
- }
-
- public BusinessException(String code,String message, String tranCode, Throwable cause) {
- super(message, cause);
- this.code = code;
- this.tranCode = tranCode;
- }
-
- public String getCode() {
- return code;
- }
-
- public void setCode(String code) {
- this.code = code;
- }
-
- public String getTranCode() {
- return tranCode;
- }
-
- public void setTranCode(String tranCode) {
- this.tranCode = tranCode;
- }
- }

- package com.spark.exception;
-
- /**
- * SystemException class
- * description: SystemException
- *
- * @author Administrator
- * @date 2023/8/5
- */
- public class SystemException extends RuntimeException {
-
- private String code; // 错误编码
-
- private String tranCode; // 交易码(接口号)
-
-
- public SystemException(String code, String message, String tranCode) {
- super(message);
- this.code = code;
- this.tranCode = tranCode;
- }
-
- public SystemException(String code,String message, String tranCode, Throwable cause) {
- super(message, cause);
- this.code = code;
- this.tranCode = tranCode;
- }
-
- public String getCode() {
- return code;
- }
-
- public void setCode(String code) {
- this.code = code;
- }
-
- public String getTranCode() {
- return tranCode;
- }
-
- public void setTranCode(String tranCode) {
- this.tranCode = tranCode;
- }
- }

自定义异常错误编码和错误信息
- package com.spark.common;
-
- /**
- * ExceptionContent class
- * description: ExceptionContent
- *
- * @author Administrator
- * @date 2023/8/5
- */
- public class ExceptionContent {
-
- public static final String BUSINESS_ERROR_CODE = "50001";
- public static final String BUSINESS_DATA_ERROR = "数据有误,请检查您的数据格式是否正确!";
- public static final String BUSINESS_ERROR_MSG = "操作有误,请联系管理员!";
-
- public static final String SYSTEM_ERROR_CODE = "50002";
- public static final String SYSTEM_ERROR_MSG = "服务器异常,请您稍后重试!";
-
- public static final String SYSTEM_UNKNOWN_ERROR_CODE = "50003";
- public static final String SYSTEM_UNKNOWN_MSG = "系统繁忙,请联系管理员!";
- }

改写业务层根据id查询Book方法,处理异常
- @Override
- public Book selectById(Integer id) {
- if(id<=0){
- throw new BusinessException(ExceptionContent.BUSINESS_ERROR_CODE,
- ExceptionContent.BUSINESS_DATA_ERROR,
- "BK1004",
- new Throwable(ExceptionContent.BUSINESS_DATA_ERROR));
- }
- return bookDao.getById(id);
- }
编写异常处理器统一处理异常
- package com.spark.exception;
-
- import com.spark.common.ExceptionContent;
- import com.spark.util.Result;
- import org.springframework.web.bind.annotation.ExceptionHandler;
- import org.springframework.web.bind.annotation.RestControllerAdvice;
-
- /**
- * ProjectExceptionAdvice class
- * description: ProjectExceptionAdvice
- *
- * @author Administrator
- * @date 2023/8/5
- */
- @RestControllerAdvice
- public class ProjectExceptionAdvice {
-
- // 处理业务异常
- @ExceptionHandler
- public Result doBusinessException(BusinessException ex){
- // 记录日志
- System.out.println(ex.getTranCode() + "出现异常");
- return new Result(ex.getCode(),ex.getMessage(),null);
- }
-
- // 处理系统异常
- @ExceptionHandler
- public Result doSystemException(SystemException sy){
- // 记录日志
- System.out.println(sy.getTranCode() + "出现异常");
- return new Result(sy.getCode(),sy.getMessage(),null);
- }
-
- // 处理其他未知异常
- @ExceptionHandler
- public Result doException(Exception ex){
- // 记录日志
- System.out.println("出现未知异常");
- System.out.println("异常信息如下:");
- System.out.println(ex.getMessage());
- return new Result(ExceptionContent.SYSTEM_UNKNOWN_ERROR_CODE,
- ExceptionContent.SYSTEM_UNKNOWN_MSG,
- null);
- }
- }

由于后台Servlet容器配置里面是拦截一切请求,前端代码在项目的webapp目录下,Tomcat启动后,去访问前端页面会被拦截,因此需要对前端资源进行放行
编写SpringMVC资源放行配置类
- package com.spark.config;
-
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
-
- /**
- * SpringMvcSupportConfig class
- * description: SpringMvcSupportConfig
- *
- * @author Administrator
- * @date 2023/8/5
- */
- @Configuration
- public class SpringMvcSupportConfig extends WebMvcConfigurationSupport {
-
- @Override
- protected void addResourceHandlers(ResourceHandlerRegistry registry) {
- registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
- registry.addResourceHandler("/css/**").addResourceLocations("/css/");
- registry.addResourceHandler("/js/**").addResourceLocations("/js/");
- registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
- }
- }

在SpringMVC配置类中扫描config包
- package com.spark.config;
-
- import org.springframework.context.annotation.ComponentScan;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-
- /**
- * SpringMvcConfig class
- * description: SpringMvcConfig
- *
- * @author Administrator
- * @date 2023/8/3
- */
- @Configuration
- @ComponentScan({"com.spark.controller","com.spark.config"})
- @EnableWebMvc
- public class SpringMvcConfig {
- }

拦截器是一种动态拦截方法调用的机制,在SpringMVC中动态拦截控制器方法的执行
作用:在指定的方法调用前后执行预先设定的代码;阻止原始方法的执行
拦截器和过滤器的区别
编写拦截器
- package com.spark.interceptor;
-
- import org.springframework.stereotype.Component;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- /**
- * ProjectInteceptor class
- * description: ProjectInteceptor
- *
- * @author Administrator
- * @date 2023/8/7
- */
- @Component
- public class ProjectInteceptor implements HandlerInterceptor {
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- System.out.println("原始方法执行前执行...");
- return true;
- }
-
- @Override
- public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
- System.out.println("原始方法执行后执行...");
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
- System.out.println("postHandle执行后执行...");
- }
- }

SpringMVC配置类中添加拦截器并扫描
- package com.spark.config;
-
- import com.spark.interceptor.ProjectInteceptor;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
- import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
- import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
-
- /**
- * SpringMvcSupportConfig class
- * description: SpringMvcSupportConfig
- *
- * @author Administrator
- * @date 2023/8/5
- */
- @Configuration
- public class SpringMvcSupportConfig extends WebMvcConfigurationSupport {
-
- @Autowired
- ProjectInteceptor projectInteceptor;
-
- @Override
- protected void addResourceHandlers(ResourceHandlerRegistry registry) {
- registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
- registry.addResourceHandler("/css/**").addResourceLocations("/css/");
- registry.addResourceHandler("/js/**").addResourceLocations("/js/");
- registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
- }
-
- // 添加拦截器
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(projectInteceptor).addPathPatterns("/books/*","/books");
- }
- }

- package com.spark.config;
-
- import org.springframework.context.annotation.ComponentScan;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-
- /**
- * SpringMvcConfig class
- * description: SpringMvcConfig
- *
- * @author Administrator
- * @date 2023/8/3
- */
- @Configuration
- @ComponentScan({"com.spark.controller","com.spark.config","com.spark.interceptor"})
- @EnableWebMvc
- public class SpringMvcConfig{
-
- }

当配置多个拦截器时,形成拦截器链
多拦截器执行顺序
preHandle方法按照拦截器配置顺序执行,postHandle和afterCompletion方法按照配置顺序倒序执行
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。