当前位置: 首页 > news >正文

聊一聊SpringBoot中的自定义Starter

前言


自己动手简单的封装、应用一个starter

该starter的作用是被引入后,会对项目中Controller出现的异常做统一的处理及反馈

starter的思想在实际开发过程被大量的应用


一、新建starter项目

使用IDE创建一个maven构建方式的空白项目

1.1pom.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.lazy.snail</groupId><artifactId>exception-handler-spring-boot-starter</artifactId><version>1.0.0</version><packaging>jar</packaging><properties><java.version>17</java.version><encoding>UTF-8</encoding></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.7.12</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.8.1</version><configuration><source>17</source><target>17</target></configuration></plugin></plugins></build></project>
  • 自定义的starter命名为xxx-spring-boot-starter
  • spring-boot-starter-web依赖的引入是由于开发starter过程中会使用到相关的类或注解,如:@RestControllerAdvice、@ExceptionHandler等
  • 构建安装时(clean install)可以去掉spring-boot-starter-web依赖
  • exception-handler-spring-boot-starter的应用场景就是基于springboot的web项目,所以相关的依赖在应用项目中都会有

1.2自定义一个Api异常

package com.lazy.snail.exceptionhandler;/*** @ClassName ApiException* @Description TODO* @Author lazysnail* @Date 2024/11/7 15:06* @Version 1.0*/
public class ApiException extends RuntimeException {private int code;private String message;public ApiException(int code, String message) {super(message);this.code = code;this.message = message;}public int getCode() {return code;}@Overridepublic String getMessage() {return message;}
}
  • 引入项目中可以根据实际业务抛出该异常

1.3自定义反馈结果

package com.lazy.snail.exceptionhandler;/*** @ClassName ApiResponse* @Description TODO* @Author lazysnail* @Date 2024/11/7 15:06* @Version 1.0*/
public class ApiResponse<T> {private int status;   // 状态码private String message;  // 错误信息或成功提示private T data;  // 业务数据public ApiResponse(int status, String message, T data) {this.status = status;this.message = message;this.data = data;}public int getStatus() {return status;}public void setStatus(int status) {this.status = status;}public String getMessage() {return message;}public void setMessage(String message) {this.message = message;}public T getData() {return data;}public void setData(T data) {this.data = data;}
}

出现异常情况时,简单的封装一个反馈对象

1.4异常处理配置类

package com.lazy.snail.exceptionhandler;import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** @ClassName ExceptionHandlerAutoConfiguration* @Description TODO* @Author lazysnail* @Date 2024/11/7 15:32* @Version 1.0*/
@Configuration
public class ExceptionHandlerAutoConfiguration {@Bean@ConditionalOnMissingBean(GlobalExceptionHandler.class)public GlobalExceptionHandler globalExceptionHandler() {return new GlobalExceptionHandler();}
}

普通的配置类,当springboot启动过程中,容器中没有GlobalExceptionHandler类型的bean时,将创建一个

1.5异常处理类

package com.lazy.snail.exceptionhandler;import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;/*** @ClassName GlobalExceptionHandler* @Description TODO* @Author lazysnail* @Date 2024/11/7 15:06* @Version 1.0*/
@RestControllerAdvice
public class GlobalExceptionHandler {@ExceptionHandler(ApiException.class)public ResponseEntity<ApiResponse<Object>> handleApiException(ApiException ex) {// 捕获 ApiException,返回指定的状态码和信息ApiResponse<Object> response = new ApiResponse<>(ex.getCode(), ex.getMessage(), null);return new ResponseEntity<>(response, HttpStatus.valueOf(ex.getCode()));}@ExceptionHandler(Exception.class)public ResponseEntity<ApiResponse<Object>> handleException(Exception ex) {// 捕获其他未处理的异常,返回500状态码ApiResponse<Object> response = new ApiResponse<>(500, "Internal Server Error", null);return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);}
}

@RestControllerAdvice

  • Spring 提供的注解,用于定义全局的异常处理器、数据绑定和数据格式化。它是 @ControllerAdvice@ResponseBody 的组合,表示该类中的方法返回的对象会自动被序列化为 JSON 或 XML 格式,直接返回给客户端。
  • @RestControllerAdvice 的作用范围是整个应用的控制层,它会捕获所有标注了 @RequestMapping 的控制器中的异常。

@ExceptionHandler(ApiException.class)

  • 该注解标注的方法用于捕获 ApiException 类型的异常。通过将异常类型作为参数传入,Spring 可以在控制器中抛出 ApiException 时自动调用此方法。
  • @ExceptionHandler 注解的作用是捕获指定类型的异常,使得不同的异常处理逻辑可以分开,实现精细化处理。

@ExceptionHandler(Exception.class)

  • 该注解标注的方法用于捕获 Exception 类型的异常,这意味着它将处理所有未被其他 @ExceptionHandler 方法处理的异常,起到“兜底”作用。
  • 当出现任何未预料的异常时,Spring 会调用这个方法,为这些异常提供一个默认的错误响应,避免未处理的异常暴露到前端。

1.6spring.factories

# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.lazy.snail.exceptionhandler.ExceptionHandlerAutoConfiguration

实现自动配置机制

  • Spring Boot 会在启动时扫描 META-INF/spring.factories 文件中的 EnableAutoConfiguration 配置,加载所有指定的自动配置类。这里指定了 ExceptionHandlerAutoConfiguration 作为自动配置类,因此 Spring Boot 会在启动时自动加载 com.lazy.snail.exceptionhandler.ExceptionHandlerAutoConfiguration

简化项目中的配置

  • 通过将异常处理逻辑配置为自动配置类,可以在不同项目中只需要引入该 starter,就可以自动获得其中定义的异常处理逻辑,而不需要手动配置。模块化的设计方便了复用和维护。

按需加载组件

  • ExceptionHandlerAutoConfiguration 中,通常会定义与异常处理相关的 @Bean,如 GlobalExceptionHandler 或其他配置项。通过这种自动配置机制,Spring Boot 会自动加载这些 Bean,确保全局异常处理器在项目启动时生效。
  • ExceptionHandlerAutoConfiguration 还可以通过条件注解(例如 @ConditionalOnMissingBean)判断是否需要创建某些 Bean,可以在主项目中进行定制,避免重复配置或冲突。

支持条件加载

  • Spring Boot 的自动配置类通常可以配置成启用或禁用。通过在 ExceptionHandlerAutoConfiguration 中使用条件注解(如 @ConditionalOnProperty),可以控制自动配置的加载,比如通过属性开关来启用或禁用异常处理功能。

二、构建打包

2.1命令行

mvn clean install

2.2IDE

image-20241107194541834

2.3说明

clean:执行清理操作

  • mvn clean 命令会删除项目的 target 目录,这个目录包含了之前构建生成的所有文件(如 .class 文件、JAR 包、WAR 包等)。这一步的作用是确保项目在全新的环境下进行构建,避免使用上一次构建中遗留的文件。

install:构建并安装项目

  • mvn install 命令会触发 Maven 的完整构建流程(编译、测试、打包等),并将生成的构件(例如 JAR、WAR 文件)安装到本地 Maven 仓库(默认在 ~/.m2/repository 目录下,也可自定义)。安装到本地仓库后,其他 Maven 项目可以通过依赖管理使用该构件。
  • 具体来说,install 命令会顺序执行以下几个阶段:
    • validate:检查项目是否正确,所有必要的信息是否完整。
    • compile:编译源代码。
    • test:运行测试代码。
    • package:将编译后的代码打包成 JAR、WAR 等文件。
    • install:将打包后的文件安装到本地 Maven 仓库,以便其他项目可以使用。

2.4结果

本地仓库中打包好了exception-handler-spring-boot-starter

image-20241107194810347

三、应用

3.1新建一个springboot项目

3.1.1pom文件

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.12</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.lazy.snail</groupId><artifactId>SpringBoot</artifactId><version>0.0.1-SNAPSHOT</version><name>SpringBoot</name><description>SpringBoot</description><properties><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><exclusions><exclusion><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-logging</artifactId></exclusion></exclusions></dependency><dependency><groupId>com.lazy.snail</groupId><artifactId>exception-handler-spring-boot-starter</artifactId><version>1.0.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-log4j2</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
  • pom中引入了exception-handler-spring-boot-starter

3.1.2测试controller

package com.lazy.snail.controller;import com.lazy.snail.exceptionhandler.ApiException;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;/*** @ClassName TestController* @Description TODO* @Author lazysnail* @Date 2024/11/7 15:44* @Version 1.0*/
@RestController
public class TestController {@GetMapping("/test")public String test() {// 手动抛出一个自定义的异常throw new ApiException(400, "Bad Request");}@GetMapping("/error")public String error() {int a = 1/0;return "error";}}
  • "/test"模拟ApiException
  • "/error"模拟不可预见的异常

3.2postman测试结果

  • /test

image-20241107200144601

  • /error

image-20241107200227738

四、总结

4.1Starter的作用

  1. 简化配置

    通过自动配置,减少了手动配置的工作量,特别是在常见功能(如数据库连接、消息队列等)的配置上。

  2. 模块化功能

    可以将某些通用功能封装到独立的模块中(例如日志、缓存、事务、消息队列等),使得其他项目可以通过引入该 starter 直接使用。

  3. 增强可复用性

    将项目中的一些通用代码和配置抽象成 starter,方便在多个项目中复用,提升开发效率。

4.2Starter的简要开发流程

  1. 定义功能模块

    明确 starter 要解决的具体功能,例如统一的异常处理、日志管理、缓存配置等。

  2. 创建自动配置类

    在starter中编写自动配置类(通常使用 @Configuration 注解)。这个类包含自动配置所需的 bean 和逻辑,比如 @Bean 定义一些默认的配置或功能。

    使用 @Conditional 注解来控制某些配置是否生效,例如 @ConditionalOnProperty 可根据配置文件中的属性来启用某些功能。

  3. 提供依赖项

    确定starter所需的依赖项,并将其添加到 pom.xml 中。例如,如果starter需要连接数据库,就需要引入相关的数据库驱动。

  4. 包装和发布

    将 starter 打包为一个可发布的 JAR 文件,并发布到本地或远程 Maven 仓库。

    在META-INF/spring.factories中注册自动配置类,使得Spring Boot能够自动识别和加载该starter。

4.3Starter的应用场景

  1. 统一配置和功能封装:

    统一的异常处理:将异常处理封装到starter中,其他项目只需引入即可自动获得一致的异常处理机制。

    统一的日志配置:将日志配置封装为starter,让不同的项目能够使用统一的日志配置和日志格式。

    统一的响应格式:提供统一的 API 响应封装类,确保所有项目的返回格式一致。

    统一的安全配置:例如身份认证、授权、权限管理等功能的配置封装。

  2. 通用功能模块:

    缓存管理:封装Spring Cache的配置,统一管理缓存的实现,减少每个项目单独配置的工作量。

    数据库连接配置:封装常见的数据源配置,如 HikariCP 或 DBCP2,简化数据源的初始化和管理。

    消息队列配置:封装对消息队列(如 RabbitMQ、Kafka)的配置,简化消息队列的使用和管理。

  3. 跨项目共享功能:

    在多个项目中有相同的需求时,使用 starter 可以将功能抽象出来,减少每个项目重复编写相同代码的工作。比如,团队内部有多个微服务,可能都需要统一的异常处理和响应格式,这时可以开发一个starter让每个项目都能复用这部分功能。

  4. 支持不同的模块或服务:

    适用于微服务架构中,每个微服务通过引入不同的starter来简化配置和功能实现。例如,可以为每个服务创建一个starter,统一管理日志、异常处理、监控等功能。

  5. 简化常见配置的开发和维护:

    健康检查、审计日志、事务管理、定时任务 等常见功能可以通过starter提供自动化配置,无需重复编写。


http://www.mrgr.cn/news/68064.html

相关文章:

  • 力扣排序455题(分发饼干)
  • 简单又便宜的实现电脑远程开机唤醒方法
  • WordPress中最佳Instagram插件:专家级指南
  • js-v-for 指令来循环展示数组中的数据,并在每条数据后添加一个删除按钮 items.splice(index, 1)
  • Ubuntu - 进入紧急模式,无法进入桌面
  • 天气雷达PPI图绘制之python中cinrad库离线安装应用
  • 移除元素(java)
  • 【猜数字】C语言小游戏
  • day05(单片机)SPI+数码管
  • 算法通关(4)-- 前缀树
  • 介绍一下memcpy(c基础)
  • 那些在Nop代码生成器中用到的DSL
  • 汉诺塔问题代码分享及思路分享(c基础)
  • 高德 阿里231滑块 分析
  • STM32项目---水质水位检测
  • D365 使用电子邮件模板在 X++ 中发送电子邮件
  • 【UE5】Cesium GlobePawn 如何Fly To
  • uniapp中使用原生ajax上传文件并携带其他数据,实时展示上传进度
  • 备考25年二建,最好这样选专业!
  • nacos注册中心简介
  • vue2与vue3的全局通信插件,如何实现自定义的插件
  • 杨辉三角,洗牌算法
  • 探索C语言数据类型
  • 前端基础-html-注册界面
  • [Docker#1] 专栏前言 | 亿级高并发架构演进之路
  • 【大数据学习 | kafka高级部分】kafka的数据同步和数据均衡