-
创建自定义注解接口
package com.example.lambda.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * @author: WZ * @create: 2022-10-17 09:18 * @description: 1、自定义日志注解接口 * @Target(ElementType.TYPE) // 接口、类、枚举、注解 * @Target(ElementType.FIELD) // 字段、枚举的常量 * @Target(ElementType.METHOD) //方法 * @Target(ElementType.PARAMETER) //方法参数 * @Target(ElementType.CONSTRUCTOR) //构造函数 * @Target(ElementType.LOCAL_VARIABLE)//局部变量 * @Target(ElementType.ANNOTATION_TYPE)//注解 * @Target(ElementType.PACKAGE) ///包 * @Retention注解: 这个参数有三种,一般默认第三种 * <p> * 1. RetentionPolicy.SOURCE —— 这种类型的Annotations只在源代码级别保留, * <p> * 编译时就会被忽略 * <p> * 2. RetentionPolicy.CLASS —— 这种类型的Annotations编译时被保留,在class文件中存在, * <p> * 但JVM将会忽略 * <p> * 3. RetentionPolicy.RUNTIME —— 这种类型的Annotations将被JVM保留, * <p> * 所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。 * 第二种写法: * @Documented 和 @Order(优先级:数字越小优先级越高) * @Documented 注解表明这个注解应该被 javadoc工具记录. 默认情况下,javadoc是不包括注解的. 但如果声明注解时指定了 @Documented,则它会被 javadoc 之类的工具处理, 所以注解类型信息也会被包括在生成的文档中。 * @Order标记定义了组件的加载顺序,这个标记包含一个value属性。属性接受整形值。 如:1,2 等等。值越小拥有越高的优先级。 * <p> * Ordered.HIGHEST_PRECEDENCE这个属性值是最高优先级的属性,它的值是-2147483648,对应的最低属性值是Ordered.LOWEST_PRECEDENCE,它的值是2147483647。 */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Log { /** * 模块 */ String title() default ""; /** * 是否保存请求的参数 */ boolean isSaveRequestData() default true; /** * 是否保存响应的参数 */ boolean isSaveResponseData() default true; }
-
创建LogAspect类对自定义注解进行操作
package com.example.lambda.annotation; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import org.springframework.validation.BindingResult; import org.springframework.web.context.request.RequestAttributes; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.Collection; import java.util.Map; /** * 操作日志记录处理 * * @author: WZ * @create: 2022-10-17 09:18 * @description: 2、自定义注解操作 */ @Aspect @Component @Slf4j public class LogAspect { /** * 配置织入点 */ @Pointcut("@annotation(com.example.lambda.annotation.Log)") public void logPointCut() { } /** * 处理完请求后执行 * * @param joinPoint 切点 */ @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult") public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult) { handleLog(joinPoint, controllerLog, null, jsonResult); } /** * 拦截异常操作 * * @param joinPoint 切点 * @param e 异常 */ @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e") public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e) { handleLog(joinPoint, controllerLog, e, null); } protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult) { try { //获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息 Signature signature = joinPoint.getSignature(); //获取传入目标方法的参数对象 Object[] args = joinPoint.getArgs(); //获取被代理的对象 Object target = joinPoint.getTarget(); //获取代理的对象 Object aThis = joinPoint.getThis(); //接口请求方式 String method = getHttpMethod(); String params = argsArrayToString(joinPoint.getArgs()); /** * 是否保存请求的参数 */ if (controllerLog.isSaveRequestData()) { } /** * 是否保存响应的参数 */ if (controllerLog.isSaveResponseData()) { } log.info("---------------------signature:{}", signature); log.info("---------------------params:{}", params); log.info("---------------------target:{}", target); log.info("---------------------aThis:{}", aThis); log.info("---------------------method:{}", method); log.info("---------------------异常信息:{}", e); log.info("---------------------jsonResult:{}", jsonResult); } catch (Exception exp) { // 记录本地异常日志 log.error("==前置通知异常=="); log.error("异常信息:{}", exp.getMessage()); exp.printStackTrace(); } } /** * 获取请求方式 * * @return */ public static ServletRequestAttributes getAttributes() { RequestAttributes attributes = RequestContextHolder.getRequestAttributes(); return (ServletRequestAttributes) attributes; } public static String getHttpMethod() { String method = getAttributes().getRequest().getMethod(); return method; } /** * 参数拼装 */ private String argsArrayToString(Object[] paramsArray) { String params = ""; if (paramsArray != null && paramsArray.length > 0) { for (Object o : paramsArray) { if (o != null && !isFilterObject(o)) { try { Object jsonObj = JSONObject.toJSONString(o); params += jsonObj.toString() + " "; } catch (Exception e) { } } } } return params.trim(); } /** * 判断是否需要过滤的对象。 * * @param o 对象信息。 * @return 如果是需要过滤的对象,则返回true;否则返回false。 */ @SuppressWarnings("rawtypes") public boolean isFilterObject(final Object o) { Class<?> clazz = o.getClass(); if (clazz.isArray()) { return clazz.getComponentType().isAssignableFrom(MultipartFile.class); } else if (Collection.class.isAssignableFrom(clazz)) { Collection collection = (Collection) o; for (Object value : collection) { return value instanceof MultipartFile; } } else if (Map.class.isAssignableFrom(clazz)) { Map map = (Map) o; for (Object value : map.entrySet()) { Map.Entry entry = (Map.Entry) value; return entry.getValue() instanceof MultipartFile; } } return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse || o instanceof BindingResult; } }
-
使用自定义注解@Log
@PostMapping("test2") @Log(title = "测试自定义日志post") public Object test1(@RequestBody Map map) { return new HashMap<String,Object>(){ { put("name", "张三"); put("age", 18); put("sex", "男"); } }; }
springboot自定义日志注解@Log
于 2022-10-17 14:00:24 首次发布