SpringBoot

Spring Boot

pom xml格式

2.x版本的格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
<!-- 声明这是一个 Maven POM 文件 -->
<?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,表示用的 POM 版本模型。
groupId:项目组织 ID(一般是公司/组织域名反写)。
artifactId:项目名(模块名)。
version:项目版本号,-SNAPSHOT 表示开发中的快照版本
-->
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>maven_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>

<!--
name:项目的名字,主要给人看。
description:项目描述。
-->
<name>maven_demo</name>
<description>maven_demo</description>

<!-- properties:定义变量,便于复用 -->
<properties>
<java.version>1.8</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.6.13</spring-boot.version>
</properties>

<!-- 项目所需依赖库 -->
<dependencies>
<!-- Spring Boot 基础依赖,包含 Spring 核心、日志等 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>

<!-- 测试依赖,包含 JUnit、Mockito 等,scope=test 表示只在测试时使用 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<!-- 依赖版本的“字典”,统一管理依赖的版本 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<!-- 定义构建相关配置,比如插件、编译器版本、打包方式 -->
<build>
<plugins>
<!--
指定用的编译插件。
source:源码使用的 Java 版本。
target:编译生成的字节码版本。
encoding:文件编码。
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>

<!--
spring-boot-maven-plugin:Spring Boot 的打包插件。
默认会把项目打成 可运行的 fat jar(内含所有依赖)。
mainClass:指定入口类(@SpringBootApplication 的那个类)。
skip=true:是否跳过插件执行。这里写了 true,说明当前配置可能只做演示/测试用。
executions/repackage:repackage 目标会把普通 jar 包重新打包成 Spring Boot 可执行 jar。
-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<mainClass>org.example.maven_demo.MavenDemoApplication</mainClass>
<skip>true</skip>
</configuration>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>

</plugins>
</build>

</project>

3.x版本的格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?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>

<!-- 指定父POM,继承父 POM 的依赖管理(版本统一)、默认插件配置等 -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.6</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

<groupId>com.xw</groupId>
<artifactId>consultant</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consultant</name>
<description>consultant</description>

<!-- 项目的主页地址,可以填 GitHub/GitLab -->
<url/>

<!-- 项目许可证信息 -->
<licenses>
<license/>
</licenses>

<!-- 项目开发者信息 -->
<developers>
<developer/>
</developers>

<!-- 项目的源码仓库信息 -->
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>

<properties>
<java.version>17</java.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</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>

配置文件

默认配置文件

放在src/main/resources下,名称必须为application.yml

使用环境变量

1
2
3
# 首先从环境变量DB_HOST中找,否则使用默认值localhost
db:
host: ${DB_HOST:localhost}

日志配置文件

名称为logback-spring.xml,用来定义日志级别、日志格式、日志输出位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="10 seconds">
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
<!-- scan:当此属性设置为true时,配置文件如果发生改变,将会被重新加载,默认值为true -->
<!-- scanPeriod:设置监测配置文件是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->

<contextName>logback</contextName>
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义变量后,可以使“${}”来使用变量。 -->
<property name="log.path" value="F:/yygh_log" />

<!-- 彩色日志 -->
<!-- 配置格式变量:CONSOLE_LOG_PATTERN 彩色日志格式 -->
<!-- magenta:洋红 -->
<!-- boldMagenta:粗红-->
<!-- cyan:青色 -->
<!-- white:白色 -->
<!-- magenta:洋红 -->
<property name="CONSOLE_LOG_PATTERN"
value="%yellow(%date{yyyy-MM-dd HH:mm:ss}) |%highlight(%-5level) |%blue(%thread) |%blue(%file:%line) |%green(%logger) |%cyan(%msg%n)"/>


<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
<!-- 例如:如果此处配置了INFO级别,则后面其他位置即使配置了DEBUG级别的日志,也不会被输出 -->
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>INFO</level>
</filter>
<encoder>
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>


<!--输出到文件-->

<!-- 时间滚动输出 level为 INFO 日志 -->
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_info.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset>
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!-- 每天日志归档路径以及格式 -->
<fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录info级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!-- 时间滚动输出 level为 WARN 日志 -->
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_warn.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/warn/log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录warn级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>warn</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>


<!-- 时间滚动输出 level为 ERROR 日志 -->
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<!-- 正在记录的日志文件的路径及文件名 -->
<file>${log.path}/log_error.log</file>
<!--日志文件输出格式-->
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
</encoder>
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/error/log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<!--日志文件保留天数-->
<maxHistory>15</maxHistory>
</rollingPolicy>
<!-- 此日志文件只记录ERROR级别的 -->
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>

<!--
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、以及指定<appender>。
<logger>仅有一个name属性,
一个可选的level和一个可选的addtivity属性。
name:用来指定受此logger约束的某一个包或者具体的某一个类。
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
如果未设置此属性,那么当前logger将会继承上级的级别。
-->
<!--
使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
第一种把<root level="INFO">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
第二种就是单独给mapper下目录配置DEBUG模式,代码如下,这样配置sql语句会打印,其他还是正常DEBUG级别:
-->
<!--开发环境:打印控制台-->
<springProfile name="dev">
<!--可以输出项目中的debug日志,包括mybatis的sql日志-->
<logger name="com.guli" level="INFO" />

<!--
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,默认是DEBUG
可以包含零个或多个appender元素。
-->
<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="WARN_FILE" />
<appender-ref ref="ERROR_FILE" />
</root>
</springProfile>


<!--生产环境:输出到文件-->
<springProfile name="pro">

<root level="INFO">
<appender-ref ref="CONSOLE" />
<appender-ref ref="DEBUG_FILE" />
<appender-ref ref="INFO_FILE" />
<appender-ref ref="ERROR_FILE" />
<appender-ref ref="WARN_FILE" />
</root>
</springProfile>

</configuration>

不同环境下的配置

最上面的为默认配置,通过---隔开不同环境的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
server:
port: 8080

---

# 开发
spring:
config:
activate:
on-profile: native

server:
port: 8081

---

# 测试
spring:
config:
activate:
on-profile: test

server:
port: 8082

---

# 生产
spring:
config:
activate:
on-profile: production

server:
port: 8083
  • 在idea中通过添加虚拟机参数-Dspring.profiles.active=环境名指定环境

  • 在命令行通过java -Dspring.profiles.active=环境名 -jar xxx.jar 指定环境

  • 不指定环境名时为default

读取配置

通过@Value注解一个个读取配置

1
2
3
4
5
6
7
8
9
10
@Value("${app.name}")
private String name;

// 带默认值
@Value("${app.port:8080}")
private int port;

// 读取数组
@Value("${app.servers[0]}")
private String firstServer;

通过@ConfigurationProperties一次性读取多个配置

1
2
3
4
5
6
@Configuration
@ConfigurationProperties("storage.local")
public class StorageConfiguration {
// 会根据变量名来匹配
...
}

打包项目

通过spring-boot-maven-plugin插件来打包

1
2
3
4
5
6
7
8
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
  • mvn clean:只清理,不构建

  • mvn package:直接打包,但不会删除旧文件

  • mvn clean install :清理 + 构建 + 把包安装到本地仓库(~/.m2/repository),方便别的项目依赖

  • mvn clean deploy :清理 + 构建 + 部署到远程仓库

  • mvn clean package:打包项目

    打包完项目会在target/目录下生成xxx.jar(包含依赖)和xxx.jar.original(不包含依赖)

    可通过java -jar xxx.jar直接运行

常用注解

启动类上

  • @SpringBootApplication:启动Spring Boot应用程序,标注在启动类上

    注解包含了

    • @SpringBootConfiguration:本质上就是 @Configuration,表示这是一个配置类
    • @EnableAutoConfiguration:开启自动配置,会根据项目中的 classpath 依赖 和 定义的配置,自动配置 Spring 应用所需要的 Bean
    • @ComponentScan:负责扫描Bean,默认会扫描启动类所在包及其子包下的组件
  • @EnableTransactionManagement:开启事务管理@Transactional

  • @MapperScan:MyBatis 项目里常用,指定 Mapper 接口包路径

  • @ComponentScan:指定扫描的包,自动发现并注册组件

  • @Import:显式导入类/配置到容器

配置类上

  • @Configuration:声明当前类是一个配置类,配合@Bean使用

  • @Bean:用于方法上,把返回值对象交给 Spring 容器管理

    方法的返回值就是要注册到容器中的对象,默认 Bean 名称是方法名

    @Lazy:bean 会在第一次使用才创建

    方法的参数会被容器解析,相当于@Autowired自动注入

  • @Conditional:条件装配,根据条件判断是否加载这个Bean

    • @ConditionalOnClass:某个类存在时才生效
    • @ConditionalOnMissingBean:容器里没有某个 Bean 时才加载
    • @ConditionalOnProperty:配置文件里存在某属性时才生效

    ….

  • @ConfigurationProperties:把配置文件里的属性绑定到类的属性里

  • @Profile:只在指定环境下加载Bean

监控运行状态

Actuator 是 Spring Boot 提供的一个监控和管理工具。它可以暴露 应用运行状态、指标、健康信息、日志级别动态修改等 端点(Endpoints)。对生产环境运维和监控非常有用

  • 引入依赖

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
  • 添加配置

    1
    2
    3
    4
    5
    6
    7
    # Actuator会把它能收集到的所有信息都暴露给JMX,出于安全原因,只会把health和infoo暴露给Web
    # 可以设置Web能访问的端点
    management:
    endpoints:
    web:
    exposure:
    include: info, health, beans, env, metrics
  • 访问

    1
    http://localhost:8080/actuator/health

使用过滤器

1.实现Filter接口

可以重写Filter中的三个方法

name 说明
init(FilterConfig) 创建filter时会调用一次
doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 拦截客户端请求时调用
destroy() 销毁filter时会调用一次

2.注册拦截器

方式1: 注解注册

通过@WebFilter(filterName, urlPatterns)注解来说明这是一个过滤器

参数 说明
filterName 过滤器名字
urlPatterns 拦截的路径

然后在主启动类上使用@ServletComponentScan注解开启扫描

加上这个注解可以扫描@Servlet@Filter@Listener

方式2: 配置类方式注入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Configuration
public class FilterConfig {
@Autowired
private Filter1 filter;

@Bean
public FilterRegistrationBean filter() {
//通过FilterRegistrationBean注入Bean
FilterRegistrationBean registration = new FilterRegistrationBean();
//设置过滤器
registration.setFilter(filter);
//设置过滤器名和拦截路径
registration.setName("filter");
registration.addUrlPatterns("/*");
//设置优先级别
registration.setOrder(1);
return registration;
}
}

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
@WebFilter(filterName = "loginCheckFilter", urlPatterns = "/*")
public class LoginCheckFilter implements Filter {
//路径匹配器
public static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;

//获取请求的uri
String requestURI = request.getRequestURI();

//判断是否需要处理
String[] urls = new String[]{
//不需要处理的路径
"/employee/login",
"/employee/logout",
"/backend/**",
"/front/**",
"/common/**"
};
if (check(urls, requestURI)) {
//不用处理, 放行
filterChain.doFilter(request, response);
return;
} else if (request.getSession().getAttribute("employee") != null) {
//网页端验证有没有登录
Long id = (Long) request.getSession().getAttribute("employee");
BaseContext.setCurrentId(id);
//已登录, 放行
filterChain.doFilter(request, response);
return;
} else {
//未登录, 拦截
response.getWriter().write(JSON.toJSONString(R.error("NOTLOGIN")));
return;
}
}

/**
* 匹配请求路径是否不需要处理
*
* @param urls
* @param requestURI
* @return
*/
private boolean check(String[] urls, String requestURI) {
for (String url : urls) {
if (PATH_MATCHER.match(url, requestURI)) {
return true;
}
}
return false;
}
}

自定义异常处理器

案例

  1. 自定义异常类

    • 基础异常类

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      @Data
      public class BaseException extends Exception{
      private final Integer code;

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

      public BaseException(ResultStatus status) {
      super(status.getDescription());
      this.code = status.getCode();
      }
      }
    • 根据业务场景派生不同异常

      1
      2
      3
      4
      5
      6
      7
      8
      /**
      * 用户权限异常
      */
      public class UnauthorizedException extends BaseException{
      public UnauthorizedException(String message) {
      super(ResultStatus.UNAUTHORIZED.getCode(), message);
      }
      }
  2. 添加全局异常处理类

    添加@RestControllerAdvice注解来统一捕获所有异常

    @RestControllerAdvice = @ControllerAdvice + @ResponseBody

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    @RestControllerAdvice
    public class GlobalExceptionHandler {
    // 处理自定义业务异常
    @ExceptionHandler(BaseException.class)
    public CommonResult<?> handleBaseException(BaseException e) {
    return CommonResult.fail(e.getCode(), e.getMessage());
    }

    // 处理空指针等运行时异常
    @ExceptionHandler(NullPointerException.class)
    public CommonResult<?> handleNullPointerException(NullPointerException e) {
    return CommonResult.fail(500, "空指针异常");
    }

    // 处理所有其他异常
    @ExceptionHandler(Exception.class)
    public CommonResult<?> handleException(Exception e) {
    return CommonResult.fail(500, "服务器内部错误: " + e.getMessage());
    }
    }
  3. 业务代码中抛出异常

    1
    2
    3
    4
    5
    6
    7
    8
    @GetMapping("/test")
    public CommonResult<String> test() throws BaseException {
    if(true) {
    throw new BaseException(666, "testException");
    }

    return CommonResult.success("test");
    }

SpringBoot
http://xwww12.github.io/2022/10/11/Spring&SpringBoot/SpringBoot/
作者
xw
发布于
2022年10月11日
许可协议