The common package of a project

Using AOP to Record System Logs:

1.Custom Annotation Class

Define a custom annotation class:

package com.java.common.annotion;
import java.lang.annotation.*;

@Target({ElementType.METHOD, ElementType.PARAMETER}) // This annotation applies to methods and parameters
@Retention(RetentionPolicy.RUNTIME) // Runtime annotation
public @interface SystemControllerLog {
    String description() default "Default Controller Interface";
}

2. Define an Aspect Class

In the aspect class, define pointcuts for classes or methods with the custom annotation from step one:

package com.java.common.aspect;

import com.java.common.annotion.SystemControllerLog;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * Aspect class to record common logs
 */
@Component
@Aspect
public class LogAspect {
    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);

    // Pointcut for Controllers
    @Pointcut("@annotation(com.java.common.annotion.SystemControllerLog)")
    public void controllerAspect() {
    }

    // Pointcut for Services
    @Pointcut("@annotation(com.java.common.annotion.SystemServiceLog)")
    public void serviceAspect() {
    }

    /**
     * Before advice to log user actions in Controller layer
     */
    @Before("controllerAspect()")
    public void doBefore(JoinPoint joinPoint) {
        try {
            logger.info("============== Before Advice Start ==============");
            logger.info("Request Method: " + (joinPoint.getTarget().getClass().getName() + "." + joinPoint.getSignature().getName()));
            logger.info("Method Description: " + getControllerMethodDescription(joinPoint));
        } catch (Exception exception) {
            logger.error("== Before Advice Exception ==");
            logger.error("Exception Message: {}", exception.getMessage());
        }
    }

    /**
     * Get method description from annotation in Controller layer
     */
    private String getControllerMethodDescription(JoinPoint joinPoint) throws ClassNotFoundException {
        String targetName = joinPoint.getTarget().getClass().getName();
        String methodName = joinPoint.getSignature().getName();
        Object[] arguments = joinPoint.getArgs();
        Class targetClass = Class.forName(targetName);
        Method[] methods = targetClass.getMethods();
        String description = "";
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                Class[] clazzs = method.getParameterTypes();
                if (clazzs.length == arguments.length) {
                    description = method.getAnnotation(SystemControllerLog.class).description();
                    break;
                }
            }
        }
        return description;
    }
}

3. Implement the Logging Logic in the Aspect Class

4. Add Annotations to the Classes or Methods that Require Logging

@GetMapping("/user")
@SystemControllerLog(description = "Test API Log")
@ResponseBody
public User user() {
    User user = new User();
    user.setName("theonefx");
    user.setAge(6666);
    return user;
}

Assume that the logging code and the business code are in different packages. You need to scan the corresponding aspect class; otherwise, it will not achieve the logging effect.

In the actual development process, we generally put logging code into a separate module, which may cause the startup class of the package that needs to be logged can not scan the common package, and it needs to be configured

在实际开发的过程中我们一般将公共日志记录相关的逻辑放入到单独的模块中,这样有可能导致需要记录日志的包的启动类扫描不到日志记录所在的公共包,需要进行配置

公共异常记录

在项目中我们可以对业务层面的异常进行统一的封装处理,异常类有几个值得注意的点:
@ControllerAdvice表示是对接口层进行增强处理,利用这个特点可以对接口层进行异常的处理。
@ExceptionHandler用于在特定的处理器类、方法中处理异常的注解



/**
 * 统一异常处理、数据预处理等
 */
@ControllerAdvice
public class ControllerExceptionHandler {

    private static final Logger LOG = LoggerFactory.getLogger(ControllerExceptionHandler.class);

    /**
     * 所有异常统一处理
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public CommonResp exceptionHandler(Exception e) {
        CommonResp commonResp = new CommonResp();
        LOG.error("系统异常:"+e);
        commonResp.setSuccess(false);
        commonResp.setMessage("系统出现异常,请联系管理员");
        return commonResp;
    }


    @ExceptionHandler(value = BindException.class)
    @ResponseBody
    public CommonResp exceptionHandler(BindException e) {
        CommonResp commonResp = new CommonResp();
        LOG.error("系统异常:"+e.getAllErrors().get(0).getDefaultMessage());
        commonResp.setSuccess(false);
        commonResp.setMessage(e.getAllErrors().get(0).getDefaultMessage());
        return commonResp;
    }


}

引入spring校验框架

引入了校验框架,需要在公共模块里引入validate坐标

 	<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>

然后在需要校验的接口参数上加上对应的注解@Valid

    @PostMapping("/register")
    public CommonResp<Long> register(@Valid MemberRegisterReq memberRegisterReq){
        long register = memberService.register(memberRegisterReq);
        return new CommonResp<>(register);
    }
posted @ 2024-05-17 10:55  PostMan_Zc  阅读(27)  评论(0)    收藏  举报