SSM - SpringMVC

本文最后更新于:5 个月前

SSM框架 - SpringMVC

SpringMVC

简介-入门

SpringMVC是一种基于Java实现MVC模型的轻量级web框架

SpringMVC技术与Servlet技术功能等同,均属于web层开发技术

优点

使用简单,开发便捷(相比于servlet)

灵活性强

IDEA 创建SpringMVC项目

https://www.bilibili.com/video/BV1Fi4y1S7ix?p=44

SpringMVC入门案例

1、使用SpringMVC技术需要先导入SpringMVC坐标与Servlet坐标

2、创建SpringMVC控制器类(等同于servlet功能)

3、初始化SpringMVC环境(同Spring环境),设定SpringMVC配置类加载对应的bean

4、初始化servlet容器,使Tomcat服务器加载SpringMVC环境,并设置SpringMVC技术处理的请求


1、使用SpringMVC技术需要先导入SpringMVC坐标与Servlet坐标

<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>3.1.0</version>
  <scope>provided</scope>
</dependency>

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>5.2.10.RELEASE</version>
</dependency>

2、创建SpringMVC控制器类(等同于servlet功能)

必须要用@Controller 来声明SpringMVC的bean

//2. 定义Controller
//2.1 使用@Controller定义bean
@Controller
public class UserController {
    //2.2 设置当前操作的访问路径
    @RequestMapping("/save")
    //2.3 设置当前操作的返回值类型
    @ResponseBody
    public String save(){
        System.out.println("user save ...");
        return "{'username':'springmvc'}";
    }
}

3、初始化SpringMVC环境(同Spring环境),设定SpringMVC配置类加载对应的bean

//3. 创建SpringMVC配置文件,加载controller对应的bean
@Configuration
@ComponentScan("com.opn.controller")
public class SpringMVCConfig {
}

4、初始化servlet容器,使Tomcat服务器加载SpringMVC环境,并设置SpringMVC技术处理的请求

//4. 定义一个servLet容器启动的配置类,在里面加裁spring 的配置
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {
    
    //加载springMVC容器配置
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        //注册springMVC配4配置类
        ctx.register(SpringMVCConfig.class);
        return ctx;
    }

    //加载spring容器配置
    protected WebApplicationContext createRootApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringConfig.class);
        return ctx;
    }

    //设置哪些请求归属springMVC处理
        protected String[] getServletMappings() {
        //所有请求归MVC处理
        return new String[]{"/"};
    }
}

SpringMVC 入门注解

  • @Controller

专门用来设定SpringMVC控制器

  • @RequestMapping

设置当前控制器方法请求访问路径

  • @ResponseBody

设置当前控制器方法响应内容为当前返回值

SpringMVC Servlet容器配置类

AbstractDispatcherServletInitializer类是SpringMVc提供的快速初始化web3.0容器的抽象类

AbstractDispatcherServletInitializer提供三个接口方法供用户实现

  • createservletApplicationContext()

专门用来加载SpringMVC的核心配置

  • getServletMappings()

设置请求路径

  • createRootApplicationcontext()

专门用来加载Spring的核心配置

SpringMVC 开发思路

1+N

SpringMVC 入门案例工作流程分析

Bean加载控制

解决 –

Spring 加载 controller,dao,service 中的bean

springMVC 加载 controller 的bean

重复加载问题

因为功能不同,如何避免Spring错误的加载到SpringMIVC的bean

——

加载spring控制的bean的时候排除掉SpringMVC控制的bean


方式一

Spring加载bean的设定扫面范围为con.opn,排除掉controller包内的bean

方式二

Spring加载的bean设定扫描范围为精准范围,例如service包、dao包等

方式三

不区分Spring与SpringMVC的环境,加载到同一个环境中

方式一    

先去除SpringMVC的@Configuration,
或将Spring,SpringMVC的config配置类放到com目录下

type,按照什么方式排除,此处为类型排除
class,排除@Controller注解类型的类

@Configuration
@ComponentScan(value = "com.opn",
    excludeFilters = @ComponentScan.Filter(
            type = FilterType.ANNOTATION,
            classes = Controller.class
    ))

方式二

@Configuration
@ComponentScan({"com.opn.service","com.opn.dao"})
public class SpringConfig {
}

Servlet配置类简化书写

//4. 定义一个servLet容器启动的配置类,在里面加裁spring 的配置
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer {

    //加载springMVC容器配置
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        //注册springMVC配置类
        ctx.register(SpringMVCConfig.class);
        return ctx;
    }
    
    //加载spring容器配置
    protected WebApplicationContext createRootApplicationContext() {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(SpringConfig.class);
        return ctx;
    }

    //设置哪些请求归属springMVC处理
    protected String[] getServletMappings() {
        //所有请求归MVC处理
        return new String[]{"/"};
    }
}

public class ServletContainersInitConfig extends     AbstractAnnotationConfigDispatcherServletInitializer {

    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{SpringConfig.class};
    }

    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{SpringMVCConfig.class};
    }

    protected String[] getServletMappings() {
        return new String[]{"/"};
    }
}

PostMan工具

Postman是一款功能强大的网页调试与发送网页HTTP请求的Chrome插件

模拟请求

get/post/ajax

简单/高效

https://www.postman.com/

请求与响应

设置请求映射路径

命名重复问题

团队多人开发,每人设置不同的请求路径,冲突问题如何解决

–设置规范

设置模块名作为请求路径前缀

将@RequestMapping(“/user”) 放在类上

Get/Post请求

不区分Get/Post


普通参数

+形参

@RequestMapping("/save")
@ResponseBody
public String save(String name){
    return "this is name ==> "+name;
}

中文 – POST请求乱码处理

设置过滤器

在Servlet的配置类中添加过滤器

//乱码处理 -- 设置过滤器
protected Filter[] getServletFilters(){
    CharacterEncodingFilter filter = new CharacterEncodingFilter();
    filter.setEncoding("UTF-8");
    return new Filter[]{filter};
}

五种类型参数传递

  1. 普通参数
  2. POJO类型参数
  3. 嵌套POJO类型参数
  4. 数组类型参数
  5. 集合类型参数
实体类需要定义get/set方法,不然无法传值

与参数访问类型无关

需要get/set方法

自动生成

fn + alt + insert


  • 普通参数

普通参数: url地址传参,地址参数名与形参变量名相同,定义形参即可接收参数

  • 请求参数名与形参名不同

@RequestParam

绑定请求参数与形参之间的关系

@RequestMapping("/save")
@ResponseBody
public String save(@RequestParam("name") String username, Integer age){
    return "this is name ==> "+ username + "age ==> "+age;
}

请求url/save?name=123&age=123

this is name ==> 123age ==> 123
  • POJO类型参数

传实体类

@RequestMapping("/usersend")
@ResponseBody
public String save2(User user){
    return "this is user ==> "+ user;
}

传递的参数

url/usersend?name=123&age=123
  • 嵌套POJO类型参数

带引用类型的实体类

public class Address {
    public Integer id;
    public String addresses;

    get/set/tostring...
}

public class User {
    private String name;
    private Integer age;

    private Address address;

    get/set/tostring...
}

 @RequestMapping("/save3")
@ResponseBody
public String save3(User user){
    System.out.println(user);
    return "this is user ==> "+ user ;
}

传递的参数

url/save3?name=123&age=333&address.id=123&address.addresses=999
传几个参数,有几个参数的值,其他参数值为null
  • 数组类型参数

数组

@RequestMapping("/array")
@ResponseBody
public String array(String[] likes){
    System.out.println();
    return "this is ==> " + Arrays.toString(likes);
}

传递的参数

url/array?likes=p&likes=o&likes=i
  • 集合类型参数

集合数据

@RequestParam 必须要加

不然会按照POJO类型处理,报错

将传入的内容作为集合的属性(如长度),而不是集合的内容

@RequestMapping("/list")
@ResponseBody
public String list(@RequestParam List<String> likes){
    System.out.println();
    return "this is ==> " + likes;
}

传递的参数

url/list?likes=q&likes=w&likes=e

  1. 普通参数

url地址传参,地址参数名与形参变量名相同,定义形参即可接收参数

请求参数名与形参变量名不同,使用@RequestParam绑定参数关系

@RequestParam

  1. POJO类型参数

请求参数名与形参对象属性名相同,定义POJO类型形参即可接收参数

  1. 嵌套POJO类型参数

请求参数名与形参对象属性名相同,按照对象层次结构关系即可接收嵌套POJO属性参数

  1. 数组类型参数

请求参数名与形参对象属性名相同且请求参数为多个,定义数组类型形参即可接收参数

  1. 集合类型参数

请求参数名与形参集合对象名相同且请求参数为多个,@RequestParam绑定参数关系

Python - JSON

from urllib import request
import json

# 请求体数据
request_data =["account","sign"]

headers = {"content-type": "application/json"}

req = request.Request(url="...",
                  headers=headers,
                  data=json.dumps(request_data).encode("utf-8"))

print(req.headers)
print(req.data)

reps = request.urlopen(req).read().decode("utf-8")

print(reps)

JSON数据传递

  1. json数组
  2. json对象(POJO)
  3. json数组(POJO)(多个实体类)

JSON 坐标

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.13.1</version>
</dependency>

@EnableWebMvc

接受外部JSON数据转对象

@EnableWebMvc
public class SpringMVCConfig {
}
  • JSON数组

@RequestBody

数组

@RequestMapping("/JSON")
@ResponseBody
public String JSON(@RequestBody List<String> likes){
    System.out.println();
    return "this is ==> " + likes;
}

传递的参数

postman - Body - raw - JSON

["11","22","33"]
  • JSON对象(POJO)

对象

@RequestMapping("/JSON2")
@ResponseBody
public String JSON2(@RequestBody User user){
    System.out.println(user);
    return "this is user ==> "+ user ;
}

传递的参数

postman - Body - raw - JSON

{"name":"123","age":23}
  • JSON集合(POJO)(多个实体类)

多个实体类

@RequestMapping("/JSON3")
@ResponseBody
public String JSON3(@RequestBody List<User> likes){
    System.out.println(likes);
    return "this is ==> " + likes;
}

传递的参数

[{"name":"123","age":23},{"name":"123","age":23}]

@EnableWebMvc

@RequestBody

接收方法体中的json数据


@RequestParam 与 @RequestBody 区别

日期类型参数传递

日期类型参数

@RequestMapping("/date")
@ResponseBody
public String date(Date date,
                   @DateTimeFormat(pattern = "yyyy-MM-dd")Date date1,
                   @DateTimeFormat(pattern = "yyyy/MM/dd HH:mm:ss")Date date2){
    System.out.println(date);
    System.out.println(date1);
    System.out.println(date2);
    return "this is ==> " + date;
}

传递的参数

/data?date=2000/01/01&date1=2000-01-01&date2=2000/01/01+01:01:01

@DateTimeFormat(pattern=””)

指定date参数类型

响应

响应界面

响应数据

@ResponseBody

  • 响应页面

页面

没有@ResponseBody(作用-设置当前控制器方法响应内容为当前返回值)

@RequestMapping("/response")
public String response(){
    System.out.println("跳转页面");
    return "/index.jsp";
}
  • 响应文本数据

文本数据

+@ResponseBody 直接返回字符串
不+@ResponseBody 程序会查询response text的文件

@RequestMapping("/response2")
@ResponseBody
public String response2(){
    System.out.println("返回纯文本数据");
    return "response text";
}
  • 响应json对象

+@ResponseBody

@RequestMapping("/response3")
@ResponseBody
public User response3(){
    System.out.println("返回json数据");
    User user = new User();
    user.setName("111");
    user.setAge(33);
    return user;
}
  • 响应json对象集合

+@ResponseBody

@RequestMapping("/response4")
@ResponseBody
public List<User> response4(){
    System.out.println("返回json数据集合");
    User user1 = new User();
    user1.setName("111");
    user1.setAge(33);

    User user2 = new User();
    user2.setName("333");
    user2.setAge(11);

    List<User> userList = new ArrayList<User>();
    userList.add(user1);
    userList.add(user2);
    return userList;
}

REST风格

REST简介

REST (Representational State Transfer),表现形式状态转换

隐藏资源的访问行为,无法通过地址得知对资源是何种操作

书写简化

  • 访问网络资源的格式—url的格式设定

  • 按照REST风格访问资源时使用行为动作区分对资源进行了何种操作
  • 按照不同的请求方式,进行不同的操作

GET/POST/PUT/DELETE

上述行为是约定方式,约定不是规范,可以打破,所以称REST风格,而不是REST规范

描述模块的名称通常使用复数,也就是加s的格式描述,表示此类资源,而非单个资源,例如:users、books、account ….

  • 根据REST风格对资源进行访问称为RESTful

REST入门案例

  • 使用实例

传参 – 在添加@RequestBody后,只能接收请求体中的json数据

postman - 选择请求方式 - Body - raw - JSON - 添加数据

{“name”:”56”}…

//查询全部

@RequestMapping(value = "/users",method = RequestMethod.GET)
@ResponseBody
public String selectall(){
    return "user select ";
}

//查询单个

@RequestMapping(value = "/users/{id}",method = RequestMethod.GET)
@ResponseBody
public String selectbyid(@PathVariable Integer id){
    return "user select " + id;
}

//添加

@RequestMapping(value = "/users",method = RequestMethod.POST)
@ResponseBody
public String add(@RequestBody User user){
    System.out.println(user);
    return "this is user ==> "+ user;
}

//修改

@RequestMapping(value = "/users",method = RequestMethod.PUT)
@ResponseBody
public String update(@RequestBody User user){
    return "user update " + user;
}

//删除

@RequestMapping(value = "/users/{id}",method = RequestMethod.DELETE)
@ResponseBody
public String delete(@PathVariable Integer id){
    return "user delete " + id;
}
  • 步骤

1、设定http请求动作(动词)

设置相应的method

2、设定请求参数(路径变量)

/user/{id} – 路径参数定位

@PathVariable – 从路径中取参数

  • 注解

@RequestMapping


注解分析

@RequestBody

接收方法体中的json数据

@RequestParam

@PathVariable

注解分析


REST快速开发

  • 路径

将方法的重复路径注解放到类的注解中

能删的删,其他保存路径参数

  • @RequestBody

提到类上

  • @RestController

简化,

@RestController = @Controller + @ResponseBody

  • @xxxMapping

@GetMapping、@PostMapping、@PutMapping、@DeleteMapping

再加路径变量

@GetMapping(“/{id}”)

@RestController
@RequestMapping("/users")

public class RESTController {
    @GetMapping
    public String selectall(){
        return "user select ";
    }

    @GetMapping("/{id}")
    public String selectbyid(@PathVariable Integer id)    {
        return "user select " + id;
    }
}

REST案例 - 基于REST风格的数据交互

  • 对于静态资源的访问

问题:

在加载前端界面时,服务器查找mapper(走了SpringMvcConfig)

解决:

@Configuration
public class SpringMvcSupport extends WebMvcConfigurationSupport {

    @Override
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        //当访问/page下的文件时,不走MVC,走page目录下的内容
        registry.addResourceHandler("/pages/**").addResourceLocations("/pages/");
        registry.addResourceHandler("/js/**").addResourceLocations("/js/");
        registry.addResourceHandler("/css/**").addResourceLocations("/css/");
        registry.addResourceHandler("/plugins/**").addResourceLocations("/plugins/");
    }
}

在SpringMvcConfig添加搜索

@ComponentScan({"com.opn.controller","com.opn.config"})
  • 步骤

先做后台功能,开发接口并调通接口

再做页面异步调用,确认功能可以正常访问

最后完成页面数据展示

补充:放行静态资源访问

  • 案例代码

前端
vue

看不懂…

        //添加
            saveBook () {
                axios.post("../books",this.formData).then((res)=>{

                });
            },

            //主页列表查询
            getAll() {
                axios.get("../books").then((res)=>{
                    this.dataList = res.data;
                });
            },

后端

@RestController
@RequestMapping("/books")
public class BookController {

    @PostMapping
    public String save(@RequestBody Book book){
        System.out.println("book save ..." + book);
        return "{'model':'booksave '}" + book;
    }

    @GetMapping
    public List<Book> getALL(){
        System.out.println("success");
        Book book1 = new Book();
        book1.setId(1);
        book1.setName("大学");
        book1.setType("internet");
        book1.setDescription("lll");
    
        List<Book> list = new ArrayList<Book>();
        list.add(book1);

        System.out.println("book getAll ..."+list);
        return list;
    }
}

SSM整合 - 前后台数据交互

https://opn90.top/2023/02/13/SSM-WorkTogether/

表现层数据封装

前端接收数据格式————创建结果模型类,封装数据到data属性中

前端接收数据格式————封装操作结果到code属性中

前端接收数据格式————封装特殊消息到message(msg)属性中

{    
    "code":200xx,
    "data":true,
    "message":"数据查询失败,请重试!"
}

设置统一数据返回结果类(前后端交互)

public class Result{
    private Object data;
    private Integer code;
    private String msg;
}

Result类中的字段并不是固定的,可以根据需要自行增减
提供若干个构造方法,方便操作

表现层与前端数据传输协议-实现

  • Result类

设置统一数据返回结果类

在controller包里写…?

public class Result {
    private Object data;
    private Integer code;
    private String msg;
    
    get/set/tostring方法

    多种构造方法,
    public Result( Integer code,Object data){}
    public Result(Integer code,Object data,  String msg){}
}
  • Code类

设置统─数据返回结果编码

在controller包里写…?

public class Code {
    public static final Integer SAVE_OK = 20011;
    public static final Integer DELETE_OK = 20021;
    public static final Integer UPDATE_OK = 20031;
    public static final Integer GET_OK = 20041;

    public static final Integer SAVE_ERR = 20010;
    public static final Integer DELETE_ERR = 20020;
    public static final Integer UPDATE_ERR = 20030;
    public static final Integer GET_ERR = 20040;
}
  • UserController类

修改方法实现–返回值

包含多个三元运算符

@RestController
@RequestMapping("/users")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping
    public Result save(@RequestBody User user) {
        Boolean flag = userService.save(user);
        return new Result(flag ? Code.SAVE_OK : Code.SAVE_ERR , flag);
    }

    @PutMapping
    public Result update(@RequestBody User user) {
        Boolean flag = userService.update(user);
        return new Result(flag ? Code.UPDATE_OK : Code.UPDATE_ERR , flag);
    }

    @DeleteMapping("/{username}")
    public Result delete(@PathVariable String username) {
        Boolean flag = userService.delete(username);
        return new Result(flag ? Code.DELETE_OK : Code.DELETE_ERR , flag);
    }

    @GetMapping("/{username}")
    public Result getById(@PathVariable String username) {
        User user = userService.getById(username);
        Integer code = user != null ? Code.GET_OK:Code.GET_ERR;
        String msg = user != null ? "查询成功":"查询失败";
        return new Result(code,user,msg);
    }

    @GetMapping
    public Result getAll() {
        List<User> userlist = userService.getAll();
        Integer code = userlist != null ? Code.GET_OK:Code.GET_ERR;
        String msg = userlist != null ? "查询成功":"查询失败";
        return new Result(code,userlist,msg);
    }
}

异常处理器

  • 位置

异常向上抛出

所有的异常均抛出到表现层进行处理

  • 处理

分类处理,AOP思想


  • 异常处理器

集中的、统一的处理项目中出现的异常

@RestControllerAdvice
public class ProjectExceptionAdvice {
    @ExceptionHandler(Exception.class)
    public Result doException(Exception ex){
        System.out.println(ex);
        return new Result(000,null,ex.toString());
    }
}
  • @RestControllerAdvice注解

  • @ExceptionHandler注解

项目异常处理方案

发现异常,将异常分类,业务/系统异常

其他异常,将其归如业务/系统异常中


  • 补充异常编码

com.opn.controller

Code

public class Code {
    public static final Integer SYSTEM_ERR = 50001;
    public static final Integer SYSTEM_TIMEOUT_ERR = 50002;
    public static final Integer SYSTEM_UNKNOW_ERR = 59999;
    public static final Integer BUSINESS_ERR = 60002;
    //......
}
  • 自定义项目系统级异常

com.opn.exception

SystemException

public class SystemException extends RuntimeException{
    private Integer code;

    get/set

    public SystemException( Integer code,String message) {
        super(message);
        this.code = code;
    }

    public SystemException(Integer code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }
}
  • 自定义项目业务级异常

BusinessException

public class BusinessException extends RuntimeException{
    private Integer code;
    
    get/set

    public BusinessException(Integer code, String message) {
        super(message);
        this.code = code;
    }

    public BusinessException(Integer code, String message, Throwable cause) {
        super(message, cause);
        this.code = code;
    }
}
  • 触发/模拟自定义异常

com.opn.service.Impl.UserService

public User getById(String username) {
    if(username=="admin")
        throw new BusinessException(Code.BUSINESS_ERR,"禁止查询管理员");
    return userDao.getById(username);
}
  • 在异常处理器中添加拦截,并处理异常

com.opn.controller.ProjectExceptionAdvice

@RestControllerAdvice
public class ProjectExceptionAdvice {
    @ExceptionHandler(SystemException.class)
    public Result doSystemException(SystemException ex){
        //记录日志
        //发送消息给运维
        //发送邮件给开发
        return new Result(ex.getCode(),null,ex.getMessage());
    }

    @ExceptionHandler(BusinessException.class)
    public Result doBusinessException(BusinessException ex){
        System.out.println(ex);
        return new Result(ex.getCode(),null,ex.getMessage());
    }

    @ExceptionHandler(Exception.class)
    public Result doException(Exception ex){
        //记录日志
        //发送消息给运维
        //发送邮件给开发
        return new Result(Code.SYSTEM_UNKNOW_ERR,null,"系统繁忙");
    }
}
  • 返回的是Result的数据

SSM整合 - 前后台通信

前后台协议联调

静态资源放行

com.opn.config.SpringMvcSupport

@Configuration
public class SpringMvcSupport 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/");
    }
}

在SpringMvcConfig中添加路径

前端界面功能

仿写…看不懂

前后端数据绑定,界面数据绑定,界面操作

参考代码,进行修改

前端界面 - 添加、添加状态、修改、删除功能实现

https://www.bilibili.com/video/BV1Fi4y1S7ix/?p=67

https://www.bilibili.com/video/BV1Fi4y1S7ix/?p=68

https://www.bilibili.com/video/BV1Fi4y1S7ix/?p=69

https://www.bilibili.com/video/BV1Fi4y1S7ix/?p=70

拦截器

拦截器(Interceptor)

是一种动态拦截方法调用的机制,在springMC中动态拦截控制器方法的执行

作用
在指定的方法调用前后执行预先设定的代码
阻止原始方法的执行

拦截器/过滤器区别

归属不同:Filter属于Servlet技术,Interceptor属于SpringMVC技术

拦截内容不同:Filter对所有访问进行增强,Interceptor仅针对springMVc的访问进行增强

SpringMvc的访问范围

config.ServletConfig

在此处进行设置

protected String[] getServletMappings() {
    return new String[]{"/"};
}

拦截器入门案例

com.opn.interceptor

ProjectInterceptor配置类

@Configuration
public class ProjectInterceptor implements HandlerInterceptor {
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("preHandle");
        return true;
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("postHandle");
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("afterCompletion");
    }
}

配置类

com.opn.config

SpringMvcSupport/就是静态资源访问通过的类 中添加 addInterceptors 方法

配置具体的拦截路径

@Autowired
private ProjectInterceptor projectInterceptor;

@Override
protected void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(projectInterceptor).addPathPatterns("/users");
}

拦截前

拦截后

在post后的操作

preHandle,true/false终止原始条件


拦截器简化开发

使用标准接口webMvcConfigurer简化开发—侵入性较强

com.opn.config

SpringMvcConfig

@Configuration
@ComponentScan({"com.opn.controller","com.opn.config","com.opn.interceptor"})
@EnableWebMvc
public class SpringMvcConfig implements WebMvcConfigurer {
    @Autowired
    private ProjectInterceptor projectInterceptor;
    
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(projectInterceptor).addPathPatterns("/users");
    }
}

拦截器执行流程

拦截器参数

前置处理

后置处理

完成后处理

拦截器链配置

当配置多个拦截器时,形成拦截器链

执行顺序

拦截器链的运行顺序参照拦截器添加顺序为准

false

当拦截器中出现对原始处理器的拦截,后面的拦截器均终止运行

当拦截器运行中断,仅运行配置在前面的拦截器的aftercompletion操作


Maven


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!