简单学习 --> Spring统一处理

统一功能处理

假设系统要判断用户是否登录,需要判断用户的key在系统的session里是否存在,这样的判断用户是否登录,要复制这些代码,到每个接口去, 每个接口都要这样做重复的代码

统一功能

公共的 , 公用的功能

例如: 上面的判断登录功能: 每个接口的处理流程都类似,返回的结果也类似,

1.正常情况调用Result.success() : 已经登录 , 2.失败调用Result.fail() : 还未登录 ;

拦截器(Interceptor)

拦截处理发送过来的请求, 和发送出去的响应(请求发过来,先经过拦截器,才到Controller , 返回的响应,也是经过拦截器)

用户=>拦截器=> Controller=>service=>mapper=>数据库

用户<=拦截器<=Controller<=service<=mapper<=数据库

拦截器使用

  1. 先定义一个拦截器 (例如: 定义工作内容,做什么,什么时候拦截,什么时候不拦截)

  2. 注册拦截器 (在哪里做这个工作, )

定义拦截器

preHandle: 返回true,放行请求, 返回false,不放行

目标方法: 这个请求/响应发送给哪个方法的例如下面这个获取页面数据的请求,就是发给这个方法的

注册拦截器

配置包创建配置类,配置拦截器 , 创建一个类来配置拦截器

路径配置 : 添加所有路径

路径

  1. /* 属于一级路径 = /user , /book 这些 ;

  2. /** 就是多级路径 = /user/login/xx , /a/b/c ...

添加路径

使用 addPathPatterns("路径"), 让拦截器在这个路径上生效 ;

不生效路径

使用 excludePathPatterns() 方法 , 配置不生效路径

或使用这种方法: (任意多个,像new了一个String数组一样 , 需要一个一个加)

可以传一个list :

拦截器使用结果
  1. 在请求过来,执行getListByPage方法前执行拦截器方法:preHandle()

  2. 方法执行完后执行: postHandle()

  3. 因为这里没有视图,所以直接指向afterCompletion()

这样就可以将用户登录验证这些操作,给加到preHandle()方法里 ;

preHandle()里进行验证用户登录, 当未登录时, 直接返回false(不放行) , 达到拦截效果 ;

同时返回的 response里将状态码设置为 401 (要求用户身份验证) , 这样前端收到这个返回结果,拿到状态码就可以判断是否是未登录 ;

前端使用 error处理 (此时前端就不会走success)

拦截器源码分析(了解)

Servlet运行流程: init(初始化) => service =>destroy(销毁)

处理请求前这里做了初始化

源码: 此处做了初始化

适配器模式(Adapter适配器)

设计模式: A接口 无法兼容 B接口 , 通过适配器,将A 和 B连接在一起 , A接口就可以使用B接口 ;(例如插头,2孔的插头通过适配器,可以插3孔的适配器 , 耳机适配器)

适配器模式的应用场景

适配器模式可看作是一种 补救措施, 补充设计上的缺陷, 解决接口不兼容的问题 ; (如果在设计初就设计好,就完全不需要适配器)

适配器模式的实现

用户直接使用=>target接口, B接口与A接口不兼容, 通过适配器来完成兼容 ;

复制代码
​
// B接口
public class B {
 public void info(String message){
     System.out.println("B接口的打印,message:"+message);
 }
}
// 用户接口
public interface UserTarget {
void log(String message);    // 用户就用这个接口
}
​
// UserTarget 和 B 的适配器
public class UserTargetBAdapter implements  UserTarget {
​
    // 使用B接口的实现
    private B b ;
    // 构造方法
    public UserTargetBAdapter(B b){
        this.b = b ;
    }
​
    @Override
    public void log(String message) {
        // 虽然重写用户接口, 但底层是使用B接口
        System.out.println("适配器");
        b.info(message);
    }
​
}
​
public class Main {
    public static void main(String[] args) {
        UserTarget userTarget = new UserTargetBAdapter(new B());
        userTarget.log("用户使用");
    }
}

统一结果处理(Advice)

怎么多接口, 要求所有接口返回的结果格式统一

统一结果格式

这里我们创建了Result类, 让所有的返回结果的格式都是Result

统一结果格式使用

在config进行创建 统一结果处理的Advice类

  1. 选择对哪些请求进行处理

  2. 对要返回的结果进行统一处理

  1. 使用@ControllerAdvice注解

  2. supports()方法,对哪些请求进行处理

  3. beforeBodyWrite(), 方法对结果返回前对结果进行处理

我们本就有Result返回结果类型, 所以,所有的返回结果都应该是Result的格式 ;

@ControllerAdvice

这个注解 内部 @Component ,所以使用ControllerAdvice 可以交给spring管理

统一结果处理问题

Result类型不能转换成string类型

使用spring提供的objectMapper来将Result转换

转换后,这里返回的结果就不像其他那样的json格式

源码问题

其他int,boolean等类型,因为父类使用的是泛型,所以用Result类型没事 ; 但如果是String类型 ,走的String的转换器,这个子类重写了父类的方法,同时接收的形参是String类型,所以导致报错 ;

为什么使用ObjectMapper转换后就可以?

objectMapper是json转换器, 所以这里用的就是json的转换器,所以正常

设置返回结果的ContentType

因为返回的结果虽然符合Result集合格式,但其实是以字符串拼接出来了的;

返回的字符串, 改成json , 这样前端就可以依然按json处理返回结果 ;

减少使用返回String这样的

统一异常捕获

  1. 创建出捕获异常类

  2. 捕获异常

  3. 返回统一结果

  4. @ExceptionHandler 注解 和 @ControllerAdvice注解

  5. @ResponseBody注解

异常捕获返回结果问题

当没有@Response注解时, Controller默认返回的是一个视图, 不是数据 , 所以下面返回的data里是404;

加上Response后 , 返回的结果就是捕获到异常的情况

多种异常捕获

可以针对不同的异常,进行不同的 异常捕获后的结果返回 , 针对不同异常,做出不同处理

异常捕获等级

上面的两个异常继承 RuntimeException , 然后RuntimeException 又继承 Exception , 为什么 这两个没有捕获到

而是 NullpointerException 和 ArithmeticException 捕获到 ,

因为异常捕获是从 下往上的 , 当没有找到子的就往上找父的 , 如果没有 NullPointerException 异常捕获 , 就触发RuntimeException捕获

统一异常捕获源码

还是在DispatcherServlet类里 , init初始化适配器里 .... 去匹配异常

最后匹配到的异常全部放进一个list里 按深度排序 , 例如NullPointerException 深度为0 , RuntimeException 为 1 , Exception为2 , 最后

get(0) 拿第0个 , 所以上面没有捕获到 RuntimeException ,Exception , 是因为拿的是深度0的 ;

相关推荐
程序猿乐锅1 小时前
【Tilas|第七篇】学员管理实现
java·笔记·idea·tlias
huohuopro1 小时前
Spring MVC 的核心知识点梳理
spring·mvc·状态模式
程序猿乐锅1 小时前
【Tilas|第六篇】班级管理实现
java·笔记·tlias
吴声子夜歌1 小时前
Java——继承实现的基本原理
java·继承
Kiling_07041 小时前
Java集合进阶:Collection与List详解
java·windows·list
小新同学^O^1 小时前
简单学习 --> 数据加密
java·数据库·学习·数据加密
AOwhisky1 小时前
Docker 学习笔记:从生态系统到镜像构建
linux·运维·笔记·学习·docker·容器
XiYang-DING1 小时前
【Java】URL(Uniform Resource Locator)
java·开发语言
知识分享小能手1 小时前
R语言入门学习教程,从入门到精通,R语言数据结构(4)
数据结构·学习·r语言