SpringBoot项目基础设施搭建( 二 )

<>();private Map buildRequestParam(String[] paramNames, Object[] paramValues) {try {Map requestParams = new HashMap<>(paramNames.length);for (int i = 0; i < paramNames.length; i++) {Object value = paramValues[i];//如果是文件对象if (value instanceof MultipartFile) {MultipartFile file = (MultipartFile) value;//获取文件名value = file.getOriginalFilename();requestParams.put(paramNames[i], value);return requestParams;} catch (Exception e) {return new HashMap<>(1);复制代码
上述切面是在执行 Controller 方法时 , 打印出调用方IP、请求URL、HTTP 请求类型、调用的方法名、耗时等 。
除了上述这种形式进行日志记录 , 还可以自定义注解 , 
@Target({ElementType.PARAMETER, ElementType.METHOD})//作用于参数或方法上@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface SystemLog {* 日志描述* @returnString description() default "";复制代码
具体使用为:
@GetMApping(value = https://www.isolves.com/it/cxkf/kj/2022-11-18/"/queryPage")@Operation(description = "获取用户分页列表")@SystemLog(description = "获取用户分页列表")public Result> queryPage(@RequestBody UserQueryPageDTO dto) {Page userVOPage = userService.queryPage(dto);return Result.ok(PageResult.ok(userVOPage));复制代码
我们只需要修改一下 RequestLogAspect 文件中的 requestServer()方法
@Pointcut("@annotation(com.xxx.annotation.SystemLog)")public void requestServer() {复制代码
除了方便前后端排查问题 , 健壮的项目还会做日志分析 , 这里介绍一种我了解的日志分析系统——ELK(ELasticsearch+Logstash+Kibana) , 在 RequestLogAspect 文件中可以将日志信息输出到 ELK 上 , 本项目不做过多介绍 。
除了日志分析 , 还有一种玩法 , 如果项目比较复杂 , 比如说分布式项目 , 微服务个数过多 , 一次请求往往需要涉及到多个服务 , 这样一来 , 调用链路就会很复杂 , 一旦出现故障 , 如何快速定位问题需要考虑 。一种解决方案就是在日志记录时增加一个 traceId 字段 , 一条调用链路上的 traceId 是相同 。
全局异常
在日常项目开发中 , 异常是常见的 , 虽然 SpringBoot 对于异常有自己的处理方案 , 但是对于开发人员不够友好 。我们想要友好地抛出异常 , 针对运行时异常 , 想要一套全局异常捕获手段 。因此如何处理好异常信息 , 对我们后续开发至关重要 。
1、定义基础接口类
public interface IError {* 错误码String getResultCode();* 错误描述String getResultMsg();复制代码
2、异常枚举类
public enum ExceptionEnum implements IError {// 数据操作状态码和提示信息定义SUCCESS("200", "操作成功"),VALIDATE_FAILED("400", "参数检验失败"),NOT_FOUND("404", "参数检验失败"),UNAUTHORIZED("401", "暂未登录或token已经过期"),FORBIDDEN("403", "没有相关权限"),REQUEST_TIME_OUT("408", "请求时间超时"),INTERNAL_SERVER_ERROR("500", "服务器内部错误!"),SERVER_BUSY("503", "服务器正忙 , 请稍后再试!");* 错误码private String resultCode;* 错误描述private String resultMsg;private ExceptionEnum(String resultCode, String resultMsg) {this.resultCode = resultCode;this.resultMsg = resultMsg;@Overridepublic String getResultCode() {return resultCode;@Overridepublic String getResultMsg() {return resultMsg;复制代码
3、自定义业务异常类
public class BusinessException extends RuntimeException {* 错误码private String errorCode;* 错误描述private String errorMsg;public BusinessException() {super();public BusinessException(IError error) {super(error.getResultCode());this.errorCode = error.getResultCode();this.errorMsg = error.getResultMsg();public BusinessException(IError error, Throwable cause) {super(error.getResultCode(), cause);this.errorCode = error.getResultCode();this.errorMsg = error.getResultMsg();public BusinessException(String message) {super(message);public BusinessException(String errorCode, String errorMsg) {super(errorCode);this.errorCode = errorCode;this.errorMsg = errorMsg;public BusinessException(String errorCode, String errorMsg, Throwable cause) {super(errorCode, cause);this.errorCode = errorCode;this.errorMsg = errorMsg;public BusinessException(Throwable cause) {super(cause);public BusinessException(String message, Throwable cause) {super(message, cause);public static void validateFailed(String message) {throw new BusinessException(ExceptionEnum.VALIDATE_FAILED.getResultCode(), message);public static void fail(String message) {throw new BusinessException(message);public static void fail(IError error) {throw new BusinessException(error);public static void fail(String errorCode, String errorMsg) {throw new BusinessException(errorCode, errorMsg);复制代码


推荐阅读