SpringBoot统一功能处理,拦截器,统一数据格式,捕捉异常

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: SpringBoot统一功能处理,拦截器,统一数据格式,捕捉异常

数据结构面试:HashMap,ConcurrentHashMap,ThreadLocal要看(建议看源码)

网络:TCP,UDP,HTTP

并发编程:线程创建方式,线程的状态,锁,synchronized,volatile

数据库 基本操作,关键字,

JVM-内存结构,GC

Linux

引入拦截器的原因。

拦截器:是Spring框架提供的核心功能之一,主要用来拦截用户的请求,在指定方法前后,根据业务需要执行预先设定的代码:

(指定在哪些方法前后执行)

JDK17把之前Java的包都换为Jakarta。

指定方法:——指我们登录验证的某些方法(比如图书的增删改查),怎样可以不用动太多代码,实现这个功能

预先设定的代码:对用户是否登录进行验证

拦截器的实现分为两步:(作用维度以url为维度)

1.定义一个拦截器

2.把拦截器注册到项目中

自定义拦截器:实现HandlerInterceptor接口,并重写所有方法

拦截器的定义

自定义拦截器

/* 一级路径    能匹配/user,/book,/login,不能匹配/user/login

/** 任意级路径 能匹配 /user,/user/login,/book

/book/*      /book下的一级路径 能匹配/book/addBook,不能匹配/book/addBook

/book/**    /book下的任意级路径     能匹配/book,/book/addBook,/book/addBook/2...。

正常工作方式

用户调用->(拦截器)->控制器层(Controller)->调用服务层(Service)->数据持久层(Mapper)->数据库

1.添加拦截器后, 执⾏Controller的⽅法之前, 请求会先被拦截器拦截住. 执⾏ preHandle() ⽅法,

这个⽅法需要返回⼀个布尔类型的值. 如果返回true, 就表⽰放⾏本次操作, 继续访问controller中的

⽅法. 如果返回false,则不会放⾏(controller中的⽅法也不会执⾏).

2. controller当中的⽅法执⾏完毕后,再回过来执⾏ postHandle() 这个⽅法以及

afterCompletion() ⽅法,执⾏完毕之后,最终给浏览器响应数据

DispatcherServlet(Dispatcher调度器,servlet生命周期)

源码环节

适配器模式和门面模式区别

1.适配器模式:是适配两者之间的差异(为了补救设计上的缺陷,应用这种模式也是无心之举),门面模式是统合了底层系统(我认为一个像是七巧板把两个不同的连接起来,门面模式就像是给他装了一个套,它里面不变,只是说可以调用他们两个)我们通过外面的套来调用里面。

统一数据格式,要包含状态码,错误信息

supports⽅法: 判断是否要执⾏beforeBodyWrite⽅法. true为执⾏, false不执⾏. 通过该⽅法可以 选择哪些类或哪些⽅法的response要进⾏处理, 其他的不进⾏处理.

beforeBodyWrite⽅法: 对response⽅法进⾏具体操作处理

出现针对String类型的错误

 快速⼊⻔ 统⼀的数据返回格式使⽤ @ControllerAdvice 和 ResponseBodyAdvice 的⽅式实现
@ControllerAdvice 表⽰控制器通知类 添加类 ResponseAdvice , 实现 ResponseBodyAdvice 接⼝, 并在类上添加
@ControllerAdvice 注解
import com.example.demo.model.Result;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import
org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
 }
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, 
MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest 
request, ServerHttpResponse response) {
return Result.success(body);
 }
} 

解决方法:

 
public class TestController {
@RequestMapping("/t1")
public String t1(){
return "t1";
 }
@RequestMapping("/t2")
public boolean t2(){
return true;
 }
@RequestMapping("/t3")
public Integer t3(){
return 200;
 }
} 
解决⽅案:
import com.example.demo.model.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import
org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
@Slf4j
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
private static ObjectMapper mapper = new ObjectMapper();
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
 }
@SneakyThrows
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, 
MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest 
request, ServerHttpResponse response) {
//如果返回结果为String类型, 使⽤SpringBoot内置提供的Jackson来实现信息的序列化
if (body instanceof String){
return mapper.writeValueAsString(Result.success(body));
 }
return Result.success(body);
 }
}

为什么会有这样的错误呢?

SpringMVC默认会注册⼀些⾃带的 HttpMessageConverter (从先后顺序排列分别为

ByteArrayHttpMessageConverter ,

StringHttpMessageConverter , SourceHttpMessageConverter ,

SourceHttpMessageConverter , AllEncompassingFormHttpMessageConverter )

AllEncompassingFormHttpMessageConverter 会根据项⽬依赖情况 添加对应的

HttpMessageConverter

在依赖中引⼊jackson包后,容器会把 MappingJackson2HttpMessageConverter ⾃动注册到

messageConverters 链的末尾.

Spring会根据返回的数据类型, 从 messageConverters 链选择合适的

HttpMessageConverter .

当返回的数据是⾮字符串时, 使⽤的 MappingJackson2HttpMessageConverter 写⼊返回对象.

当返回的数据是字符串时, StringHttpMessageConverter 会先被遍历到,这时会认为

StringHttpMessageConverter 可以使⽤

在 ((HttpMessageConverter) converter).write(body, selectedMediaType,

outputMessage) 的处理中, 调⽤⽗类的write⽅法  

由于 StringHttpMessageConverter 重写了addDefaultHeaders⽅法, 所以会执⾏⼦类的⽅法

然⽽⼦类 StringHttpMessageConverter 的addDefaultHeaders⽅法定义接收参数为String, 此

时t为Result类型, 所以出现类型不匹配"Result cannot be cast to java.lang.String"的异常

最终

为什么要统一

1. ⽅便前端程序员更好的接收和解析后端数据接⼝返回的数据

2. 降低前端程序员和后端程序员的沟通成本, 按照某个格式实现就可以了, 因为所有接⼝都是这样返回

的.

3. 有利于项⽬统⼀数据的维护和修改.

4. 有利于后端技术部⻔的统⼀规范的标准制定, 不会出现稀奇古怪的返回内容.

统一功能来实现捕捉到异常。

Spring的代码在书写统一的过程中,不按照顺序。

捕捉异常的时候,看他报什么异常,最贴近哪个,那么就是哪个

不加ResponseBody -她就会把下面那个异常当成一条数据

package com.example.demo.config;
 
import com.example.demo.model.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
 
@Slf4j
@ResponseBody
@ControllerAdvice
public class ErrorHandler {
    @ExceptionHandler
    public Result exception(Exception e){
        log.error("发生异常e{}",e);
        return Result.fail("内部错误");
    }
    @ExceptionHandler
    public Result exception(NullPointerException e){
        log.info("发生异常");
        return Result.fail("NullPointerException异常,请联系管理员");
    }
    @ExceptionHandler
    public Result exception(ArithmeticException e){
        log.info("发生异常");
        return Result.fail("ArithmeticException 异常,请联系管理员");
    }
 
 
 
}

Spring容器最开始启动时,会进行初始化的工作,其中会对异常进行处理,当异常项有多个匹配的时候,Spring会对其顺序依次排,找出最符合的报异常。

@ControllerAdvice源码分析

述源码可以看出 @ControllerAdvice 派⽣于 @Component 组件, 这也就是为什么没有五

⼤注解, ControllerAdvice 就⽣效的原因

当Controller抛出异常时, DispatcherServlet 通过

ExceptionHandlerExceptionResolver 来解析异常,⽽

ExceptionHandlerExceptionResolver ⼜通过 ExceptionHandlerMethodResolver 来解析异常, ExceptionHandlerMethodResolver 最终解析异常找到适⽤的@ExceptionHandler标注


相关文章
|
4天前
|
消息中间件 缓存 Java
手写模拟Spring Boot启动过程功能
【11月更文挑战第19天】Spring Boot自推出以来,因其简化了Spring应用的初始搭建和开发过程,迅速成为Java企业级应用开发的首选框架之一。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,帮助读者深入理解其工作机制。
20 3
|
4天前
|
Java 开发者 微服务
手写模拟Spring Boot自动配置功能
【11月更文挑战第19天】随着微服务架构的兴起,Spring Boot作为一种快速开发框架,因其简化了Spring应用的初始搭建和开发过程,受到了广大开发者的青睐。自动配置作为Spring Boot的核心特性之一,大大减少了手动配置的工作量,提高了开发效率。
18 0
|
14天前
|
前端开发 Java easyexcel
SpringBoot操作Excel实现单文件上传、多文件上传、下载、读取内容等功能
SpringBoot操作Excel实现单文件上传、多文件上传、下载、读取内容等功能
53 8
|
10天前
|
Dubbo Java 应用服务中间件
深入探讨了“dubbo+nacos+springboot3的native打包成功后运行出现异常”的原因及解决方案
本文深入探讨了“dubbo+nacos+springboot3的native打包成功后运行出现异常”的原因及解决方案。通过检查GraalVM版本兼容性、配置反射列表、使用代理类、检查配置文件、禁用不支持的功能、查看日志文件、使用GraalVM诊断工具和调整GraalVM配置等步骤,帮助开发者快速定位并解决问题,确保服务的正常运行。
26 1
|
15天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
34 2
|
前端开发 JavaScript Java
SpringBoot实现国际化i18n功能
SpringBoot实现国际化i18n功能
1091 0
SpringBoot实现国际化i18n功能
|
1月前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
143 1
|
17天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
95 62
|
18天前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
2月前
|
前端开发 JavaScript Java
基于Java+Springboot+Vue开发的大学竞赛报名管理系统
基于Java+Springboot+Vue开发的大学竞赛报名管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的大学竞赛报名管理系统项目,大学生可以在实践中学习和提升自己的能力,为以后的职业发展打下坚实基础。
218 3
基于Java+Springboot+Vue开发的大学竞赛报名管理系统