一、springboot整合全局异常处理器
1. 非前后端分离(了解)
适用于传统mvc应用,返回视图页面:
@component
public class globalexceptionresolver implements handlerexceptionresolver {
@override
public modelandview resolveexception(httpservletrequest request,
httpservletresponse response,
object handler,
exception ex) {
modelandview mv = new modelandview();
// 设置错误信息
mv.addobject("message", ex.getmessage());
mv.addobject("exception", ex);
// 跳转到错误页面
mv.setviewname("error");
return mv;
}
}2. 前后端分离(重点)
适用于restful api,返回json格式数据:
@restcontrolleradvice
public class globalexceptionhandler {
/**
* 处理所有异常
*/
@exceptionhandler(exception.class)
public result handleexception(exception e) {
// 记录日志
log.error("系统异常: ", e);
// 返回统一格式
return result.error("系统异常,请联系管理员");
}
/**
* 处理业务异常
*/
@exceptionhandler(businessexception.class)
public result handlebusinessexception(businessexception e) {
return result.error(e.getmessage());
}
/**
* 处理参数验证异常
*/
@exceptionhandler(methodargumentnotvalidexception.class)
public result handlevalidexception(methodargumentnotvalidexception e) {
string message = e.getbindingresult().getfielderrors().stream()
.map(fielderror::getdefaultmessage)
.collect(collectors.joining(", "));
return result.error(message);
}
}
// 统一返回结果类
@data
public class result<t> {
private integer code;
private string message;
private t data;
public static <t> result<t> success(t data) {
result<t> result = new result<>();
result.setcode(200);
result.setmessage("操作成功");
result.setdata(data);
return result;
}
public static <t> result<t> error(string message) {
result<t> result = new result<>();
result.setcode(500);
result.setmessage(message);
return result;
}
}二、springboot整合junit
1. 添加依赖
<!-- pom.xml -->
<dependency>
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-test</artifactid>
<scope>test</scope>
</dependency>2. 编写测试类
import org.junit.jupiter.api.test;
import org.springframework.beans.factory.annotation.autowired;
import org.springframework.boot.test.context.springboottest;
/**
* 测试演进历程:
* 1. 传统方式:main方法启动spring
* new classpathxmlapplicationcontext("applicationcontext.xml");
*
* 2. spring整合junit4:
* @runwith(springjunit4classrunner.class)
* @contextconfiguration("applicationcontext.xml")
*
* 3. springboot整合junit5(推荐):
* @springboottest
*/
@springboottest
class userservicetest {
@autowired
private userservice userservice;
@test
void testgetuserbyid() {
// 模拟测试
user user = userservice.getuserbyid(1l);
assertnotnull(user);
assertequals("张三", user.getname());
}
@test
@transactional
@rollback
void testsaveuser() {
user user = new user();
user.setname("李四");
user.setage(25);
user saveduser = userservice.save(user);
assertnotnull(saveduser.getid());
}
// mock测试示例
@test
void testwithmock() {
// 使用mockito模拟依赖
userrepository mockrepo = mock(userrepository.class);
when(mockrepo.findbyid(1l)).thenreturn(optional.of(new user(1l, "王五")));
userservice service = new userservice(mockrepo);
user user = service.getuserbyid(1l);
assertequals("王五", user.getname());
}
}三、springboot多环境配置
1. 多环境配置语法
- 主配置文件:
application.yml - 环境配置文件:
application-{profile}.yml
2. 创建多套环境配置
application-dev.yml(开发环境):
server:
port: 8081
servlet:
context-path: /dev-api
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.driver
url: jdbc:mysql://localhost:3306/dev_db?usessl=false&servertimezone=asia/shanghai
username: dev_user
password: dev123
logging:
level:
com.example: debugapplication-test.yml(测试环境):
server:
port: 8082
servlet:
context-path: /test-api
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.driver
url: jdbc:mysql://test-server:3306/test_db?usessl=false&servertimezone=asia/shanghai
username: test_user
password: test123
logging:
level:
com.example: infoapplication-prod.yml(生产环境):
server:
port: 8083
servlet:
context-path: /api
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.driver
url: jdbc:mysql://prod-master:3306/prod_db?usessl=false&servertimezone=asia/shanghai
username: ${db_username}
password: ${db_password}
logging:
level:
com.example: warn
file:
name: logs/application.log3. 激活环境
方式一:在application.yml中指定
# application.yml
spring:
profiles:
active: dev方式二:启动参数指定
# 命令行启动 java -jar myapp.jar --spring.profiles.active=prod # 或使用系统属性 java -dspring.profiles.active=test -jar myapp.jar
方式三:通过环境变量
# 设置环境变量 export spring_profiles_active=prod
方式四:使用分组(spring boot 2.4+)
# application.yml
spring:
profiles:
active: dev,audit
group:
dev: dev,debug
prod: prod,audit,metrics四、springboot整合logback日志
1. 添加依赖(已包含在starter中)
springboot默认使用logback,无需额外配置依赖。
2. logback配置文件
创建logback-spring.xml在resources目录下:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!-- 定义日志输出格式 -->
<property name="console_log_pattern" value="%d{yyyy-mm-dd hh:mm:ss.sss} [%thread] %-5level %logger{50} - %msg%n"/>
<property name="file_log_pattern" value="%d{yyyy-mm-dd hh:mm:ss.sss} [%thread] %-5level %logger{50} - %msg%n"/>
<!-- 控制台输出 -->
<appender name="console" class="ch.qos.logback.core.consoleappender">
<encoder>
<pattern>${console_log_pattern}</pattern>
<charset>utf-8</charset>
</encoder>
</appender>
<!-- 文件输出 -->
<appender name="file" class="ch.qos.logback.core.rolling.rollingfileappender">
<file>logs/app.log</file>
<encoder>
<pattern>${file_log_pattern}</pattern>
<charset>utf-8</charset>
</encoder>
<rollingpolicy class="ch.qos.logback.core.rolling.timebasedrollingpolicy">
<!-- 按天归档,保存30天 -->
<filenamepattern>logs/app.%d{yyyy-mm-dd}.%i.log</filenamepattern>
<timebasedfilenamingandtriggeringpolicy class="ch.qos.logback.core.rolling.sizeandtimebasedfnatp">
<maxfilesize>100mb</maxfilesize>
</timebasedfilenamingandtriggeringpolicy>
<maxhistory>30</maxhistory>
</rollingpolicy>
</appender>
<!-- 错误日志单独输出 -->
<appender name="error_file" class="ch.qos.logback.core.rolling.rollingfileappender">
<file>logs/error.log</file>
<encoder>
<pattern>${file_log_pattern}</pattern>
<charset>utf-8</charset>
</encoder>
<rollingpolicy class="ch.qos.logback.core.rolling.timebasedrollingpolicy">
<filenamepattern>logs/error.%d{yyyy-mm-dd}.log</filenamepattern>
<maxhistory>30</maxhistory>
</rollingpolicy>
<filter class="ch.qos.logback.classic.filter.thresholdfilter">
<level>error</level>
</filter>
</appender>
<!-- 多环境配置 -->
<springprofile name="dev">
<root level="debug">
<appender-ref ref="console"/>
</root>
<logger name="com.example" level="debug" additivity="false">
<appender-ref ref="console"/>
</logger>
</springprofile>
<springprofile name="test">
<root level="info">
<appender-ref ref="console"/>
<appender-ref ref="file"/>
</root>
</springprofile>
<springprofile name="prod">
<root level="warn">
<appender-ref ref="file"/>
<appender-ref ref="error_file"/>
</root>
<logger name="com.example" level="info" additivity="false">
<appender-ref ref="file"/>
</logger>
</springprofile>
</configuration>3. 在代码中使用日志
import org.slf4j.logger;
import org.slf4j.loggerfactory;
import org.springframework.web.bind.annotation.restcontroller;
@restcontroller
public class usercontroller {
private static final logger logger = loggerfactory.getlogger(usercontroller.class);
public user getuser(long id) {
// 不同级别的日志
logger.trace("trace级别日志");
logger.debug("debug级别日志,用户id: {}", id);
logger.info("info级别日志");
logger.warn("warn级别日志");
logger.error("error级别日志");
// 使用占位符,避免字符串拼接
logger.info("用户查询: id={}, time={}", id, system.currenttimemillis());
return userservice.getuserbyid(id);
}
}五、完整项目结构示例
src/main/java/
├── com.example.demo
│ ├── config/
│ │ └── globalexceptionhandler.java
│ ├── controller/
│ │ └── usercontroller.java
│ ├── service/
│ │ └── userservice.java
│ └── demoapplication.java
├── resources/
│ ├── application.yml
│ ├── application-dev.yml
│ ├── application-test.yml
│ ├── application-prod.yml
│ └── logback-spring.xml
└── test/java/
└── com.example.demo
└── userservicetest.java总结要点
- 异常处理:前后端分离项目使用
@restcontrolleradvice+@exceptionhandler - 单元测试:使用
@springboottest注解,支持依赖注入 - 多环境配置:通过
application-{profile}.yml和spring.profiles.active管理 - 日志配置:使用
logback-spring.xml,支持多环境不同日志级别 - 最佳实践:生产环境关闭调试日志,使用文件日志并配置滚动策略
到此这篇关于spring boot整合全局异常处理器、junit、多环境、logback的过程的文章就介绍到这了,更多相关spring boot全局异常处理器内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论