springCloud和springboot版本之间的对应关系:https://spring.io/projects/spring-cloud springboot和kafka的版本对应关系:https://spring.io/projects/spring-kafka
SpringBoot全局异常处理
package com.example.demo01.infra.advice;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* 全局异常处理器
*
* @author Alfred.Ning
* @since 2024年08月15日 21:17:00
*/
@RestControllerAdvice
@ResponseBody
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(value = {MethodArgumentNotValidException.class})
public ResponseResult<String> handleValidException(MethodArgumentNotValidException ex, HttpServletResponse httpServletResponse) {
log.error("[GlobalExceptionHandler][handleValidException] 参数校验exception", ex);
return wrapperBindingResult(ex.getBindingResult(), httpServletResponse);
}
private ResponseResult<String> wrapperBindingResult(BindingResult bindingResult, HttpServletResponse httpServletResponse) {
StringBuilder errorMsg = new StringBuilder();
for (ObjectError error : bindingResult.getAllErrors()) {
if (error instanceof FieldError) {
errorMsg.append(((FieldError) error).getField()).append(": ");
}
errorMsg.append(error.getDefaultMessage() == null ? "" : error.getDefaultMessage());
}
httpServletResponse.setStatus(HttpStatus.BAD_REQUEST.value());
return ResponseResult.failed(ResultCode.FAILED.getCode(),null);
}
}
请求日志记录
package com.example.demo01.infra.advice;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.buf.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.BindingResult;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
/**
* @author Alfred.Ning
* @since 2024年08月15日 21:24:00
*/
@Configuration
@Slf4j
public class WebLogAspect {
@Pointcut("@within(org.springframework.stereotype.Controller) || @within(org.springframework.web.bind.annotation.RestController)")
public void cutController() {
}
@Before("cutController()")
public void doBefore(JoinPoint point) {
//获取拦截方法的参数
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String url = request.getRequestURL().toString();
List<Object> list = new ArrayList<>();
for (Object object : point.getArgs()) {
if (object instanceof MultipartFile || object instanceof HttpServletRequest
|| object instanceof HttpServletResponse || object instanceof BindingResult) {
continue;
}
list.add(object);
}
log.info("请求 uri:[{}],params:[{}]", url, list);
}
/**
* 返回通知: 1. 在目标方法正常结束之后执行 1. 在返回通知中补充请求日志信息,如返回时间,方法耗时,返回值,并且保存日志信息
*
* @param response
* @throws Throwable
*/
@AfterReturning(returning = "response", pointcut = "cutController()")
public void doAfterReturning(Object response) {
if (response != null) {
log.info("请求返回result:[{}]", response);
}
}
}
通过Filter接口也可以实现