一、SPEL表達式
SPEL(Spring Expression Language)即Spring表達式語言,它是一種類似jsp的EL表達式,但是又比后者更強大的表達式語言。
例如,經常使用的@Value注解,比如:
@Value("${saas.baseUrl}") private String baseUrl;
其中參數可以為常量字符串,如:@Value("https://a.valueonline.cn/")
也可以為#{},在大括號類可以為bena的屬性、環境變量,
也可以為${},這時候在大括號類里面的properties資源文件的配置項,如:@Value("${saas.baseUrl}")
二、自定義注解,
我們的目的是需要記錄操作的日志,需要具體到某個業務,所以業務的id為動態變化的,如果在每個業務代碼里面加入日志會使得業務代碼變得更為復雜,所以我們需要自定義注解並且配合使用SPEL表達式
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface IrLog { /** * 模塊名稱 */ ModuleType moduleType(); /** * 關聯業務主鍵 */ String businessId() default ""; /** * 日志內容 */ String content() default ""; enum ModuleType { BASE_INFO("基本信息", "01"), LAW_FILE("相關文件", "02"), ; private final String moduleName; private final String moduleValue; ModuleType(String moduleName, String moduleValue) { this.moduleName = moduleName; this.moduleValue = moduleValue; } public String getModuleName() { return moduleName; } public String getModuleValue() { return moduleValue; } } }
三、日志切面類
@Aspect @Component public class IrLogAspect { private static Logger logger = LoggerFactory.getLogger(IrLogAspect.class); private final ExpressionParser expressionParser = new SpelExpressionParser(); private DefaultParameterNameDiscoverer nameDiscoverer = new DefaultParameterNameDiscoverer(); @Around("@annotation(log)") public Object invoked(ProceedingJoinPoint joinPoint, IrLog log) throws Throwable { String businessId = log.businessId(); String moduleValue = log.moduleType().getModuleValue(); String content = log.content(); Log logDto = new Log(); MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); Method method = methodSignature.getMethod(); String[] paramNames = nameDiscoverer.getParameterNames(method); Expression expression = expressionParser.parseExpression(businessId); EvaluationContext context = new StandardEvaluationContext(); Object[] args = joinPoint.getArgs(); for (int i = 0 ; i < args.length ; i++) { context.setVariable(paramNames[i], args[i]); } String parseBusinessId = expression.getValue(context, String.class); // logger.info("businessId: {}, moduleValue: {}, dbTime: {}", parseBusinessId, moduleValue, dbTime); return joinPoint.proceed(); } }
使用:
@PostMapping("/issueRegulations") @IrLog(moduleType = IrLog.ModuleType.PUBLISH, businessId = "#regulationsId") public void issueRegulations(String regulationsId) { }