SpringBoot-全局处理异常,时间格式,跨域,拦截器,监听器
目录
引言
随着微服务架构的流行,Spring Boot 已经成为了开发 RESTful API 的热门选择。在实际的开发过程中,我们经常会遇到一些通用的需求,比如全局异常处理、时间格式化、跨域请求处理、请求拦截以及事件监听等。本文将详细介绍这些功能的实现方式,并通过实例来阐述每个部分的应用场景。
全局处理异常
在 Spring Boot 应用中,异常处理是非常重要的一部分。我们希望能够统一处理所有的异常情况,以便向用户提供一致的错误信息。
1.1 使用 @ControllerAdvice 处理异常
@ControllerAdvice
是一个用于全局处理控制器异常的注解。它能够捕获所有控制器抛出的异常。
javaCopy Codeimport org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleAllExceptions(Exception ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
场景:当系统出现未被捕获的异常时,可以使用此方法返回一个统一的错误响应。
1.2 自定义异常类
我们可以定义自定义异常类,以便更精确地控制异常信息。
javaCopy Codepublic class CustomException extends RuntimeException {
public CustomException(String message) {
super(message);
}
}
在 GlobalExceptionHandler
中添加对 CustomException
的处理:
javaCopy Code@ExceptionHandler(CustomException.class)
public ResponseEntity<String> handleCustomException(CustomException ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
}
1.3 返回统一格式
为了统一返回格式,我们可以定义一个响应体类。
javaCopy Codepublic class ErrorResponse {
private String message;
private int status;
public ErrorResponse(String message, int status) {
this.message = message;
this.status = status;
}
// getters and setters
}
然后在异常处理器中返回这个对象:
javaCopy Code@ExceptionHandler(CustomException.class)
public ResponseEntity<ErrorResponse> handleCustomException(CustomException ex) {
ErrorResponse errorResponse = new ErrorResponse(ex.getMessage(), HttpStatus.BAD_REQUEST.value());
return new ResponseEntity<>(errorResponse, HttpStatus.BAD_REQUEST);
}
时间格式处理
在处理日期和时间时,常常需要将其格式化为特定的字符串形式。
2.1 使用 Jackson 配置时间格式
Spring Boot 默认使用 Jackson 进行 JSON 序列化,我们可以通过配置属性来指定时间格式。
在 application.properties
文件中添加:
propertiesCopy Codespring.jackson.date-format=yyyy-MM-dd HH:mm:ss
2.2 自定义时间格式化
如果我们需要在代码中动态控制时间格式,可以使用 @JsonFormat
注解。
javaCopy Codeimport com.fasterxml.jackson.annotation.JsonFormat;
public class User {
private String name;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date createdAt;
// getters and setters
}
跨域处理
跨域请求是指在不同域之间发送请求。为了支持跨域,我们需要进行相应的配置。
3.1 使用 @CrossOrigin 注解
在 Controller 类上使用 @CrossOrigin
注解可以允许跨域请求。
javaCopy Codeimport org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://localhost:8080")
public class MyController {
@GetMapping("/api/data")
public String getData() {
return "Hello World";
}
}
3.2 全局跨域配置
如果希望全局处理跨域请求,可以在配置类中进行设置。
javaCopy Codeimport org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:8080");
}
}
拦截器
拦截器可以用于对请求进行预处理和后处理。
4.1 创建拦截器
我们可以创建一个实现 HandlerInterceptor
接口的拦截器。
javaCopy Codeimport org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 请求前处理
System.out.println("Request URL: " + request.getRequestURL());
return true; // 返回 true 继续执行,返回 false 将终止请求
}
}
4.2 注册拦截器
在配置类中注册拦截器。
javaCopy Codeimport org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor).addPathPatterns("/api/**");
}
}
4.3 拦截器中的逻辑
在 preHandle
方法中,我们可以添加逻辑,比如验证用户身份、记录日志等。
监听器
监听器用于监听特定的事件并作出响应。
5.1 事件发布与监听
Spring 提供了事件发布和监听的机制。我们可以自定义事件。
javaCopy Codeimport org.springframework.context.ApplicationEvent;
public class CustomEvent extends ApplicationEvent {
private final String message;
public CustomEvent(Object source, String message) {
super(source);
this.message = message;
}
public String getMessage() {
return message;
}
}
发布事件:
javaCopy Codeimport org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
@Service
public class EventService {
@Autowired
private ApplicationEventPublisher publisher;
public void publishEvent(String message) {
CustomEvent event = new CustomEvent(this, message);
publisher.publishEvent(event);
}
}
5.2 使用 ApplicationListener
我们可以创建一个监听器来处理发布的事件。
javaCopy Codeimport org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
@Component
public class CustomEventListener implements ApplicationListener<CustomEvent> {
@Override
public void onApplicationEvent(CustomEvent event) {
System.out.println("Received event: " + event.getMessage());
}
}
总结
本文详细介绍了 Spring Boot 中全局处理异常、时间格式化、跨域处理、拦截器和监听器的实现方法。通过示例代码和场景描述,相信读者能够对这些概念有更深入的理解。在实际开发中,根据业务需求灵活运用这些特性,将有助于提升应用的可维护性和用户体验。