面向注解的切面实现
1.
package com.g2.order.server.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface LogAttribute { }
2.
package com.g2.order.server.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MaskLogAttribute { /** * 正则表达式,匹配到的将被转换为 **** * @return */ String value() default ""; }
3.新建切面
package com.g2.order.server.aspect; import com.g2.order.server.annotation.LogAttribute; import com.g2.order.server.annotation.MaskLogAttribute; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.annotation.EnableAspectJAutoProxy; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springside.modules.utils.text.JsonMapper; import java.lang.reflect.Method; import java.util.regex.Matcher; import java.util.regex.Pattern; //开启AspectJ 自动代理模式,如果不填proxyTargetClass=true,默认为false, @EnableAspectJAutoProxy(proxyTargetClass = true) @Component @Aspect @Order(100) public class AnnotationLogAspectConfig { private static Logger logger = LoggerFactory.getLogger(AnnotationLogAspectConfig.class); @Pointcut("@annotation(com.g2.order.server.annotation.LogAttribute)") public void logPointcut() { } @Pointcut("@annotation(com.g2.order.server.annotation.MaskLogAttribute)") public void maskLogPointcut() { } @Around("maskLogPointcut() || logPointcut()") public Object handleControllerMethod(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("进入日志切面"); //获取controller对应的方法. org.aspectj.lang.reflect.MethodSignature methodSignature = (org.aspectj.lang.reflect.MethodSignature) proceedingJoinPoint.getSignature(); //获取方法所在的类(controller) Class beanType = methodSignature.getDeclaringType(); //获取方法 Method method = methodSignature.getMethod(); String input, output; //获取方法参数列表(无需处理讨厌的流了) Object[] args = proceedingJoinPoint.getArgs(); if (args.length == 0) { input = "(null)"; } else { input = JsonMapper.INSTANCE.toJson(args[0]); } Object obj = proceedingJoinPoint.proceed(); //获取返回值的类型,与 Method.getReturnType()一致 output = JsonMapper.INSTANCE.toJson(obj); if (method.isAnnotationPresent(MaskLogAttribute.class)) { MaskLogAttribute maskLogAttribute = method.getAnnotation(MaskLogAttribute.class); String expr = maskLogAttribute.value(); Pattern exprPattern = Pattern.compile(expr); Matcher m = exprPattern.matcher(input); input = m.replaceAll("****"); m = exprPattern.matcher(output); output = m.replaceAll("****"); } logger.info("类{}的方法{}的 输入参数为:{},输出参数为:{}", method.getDeclaringClass().getCanonicalName(), method.getName(), input, output); return obj; } }
5.controller类
package com.g2.order.server.controller; import com.g2.order.dao.mapper.user.UserMapper; import com.g2.order.server.annotation.MaskLogAttribute; import com.g2.order.server.vo.user.UserLoginReq; import com.g2.order.dao.model.user.UserDao; import com.g2.order.server.vo.user.UserLoginResp; import com.g2.order.server.vo.user.UserModel; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; @Api(value = "HomeController", description = "用户登录登出接口") @RestController @RequestMapping("/home") public class HomeController { private static Logger logger = LoggerFactory.getLogger(HomeController.class); @Autowired private UserMapper userMapper; @ApiOperation(value = "用户登录", notes = "用户登录接口") @RequestMapping(value = "/login", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ResponseBody @MaskLogAttribute("\\d{3}") public UserLoginResp login(@RequestBody UserLoginReq req) { logger.info("进入登陆业务"); UserDao userDao = userMapper.getById(1); UserModel userModel = new UserModel(); userModel.setRoleId(123); userModel.setUserId(Integer.toString(userDao.getUserId())); return new UserLoginResp(userModel); } }
6.启动springboot
package com.g2.order.server; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.SpringApplication; import org.springframework.boot.web.servlet.ServletComponentScan; /** * 程序入口 */ @SpringBootApplication @ServletComponentScan public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); } }
7.调用
http://127.0.0.1:88/home/login Post { "userId":"123","password":"123444" }
8.输出
2018-09-26 09:25:55.047 INFO 16716 --- [p-nio-88-exec-1] c.g.o.s.a.AnnotationLogAspectConfig : 类com.g2.order.server.controller.HomeController的方法login的 输入参数为:{"corId":null,"userId":"****","password":"********"},输出参数为:{"success":true,"errorMessage":"","payload":{"userId":"1","roleName":null,"roleId":****}}