2022年3月10日
自定义注解
可以用以上@interface来定义注解,基于java的元注解来创建
常用的元Annotation有@Retention 和@Target。@Retention注解可以简单理解为设置注解的生命周期,而@Target表示这个注解可以修饰哪些地方(比如方法、还是成员变量、还是包等等)
假设实现一个统一日志的功能,需要做哪些处理
1.自定义注解
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Log { String value() default ""; /** * 是否启用 * * @return */ boolean enable() default true; LogActionType type() default LogActionType.SELECT; }
2.记录日志的方法上增加注解
@GetMapping
@Log("查询聊天消息")
@ApiOperation("查询聊天消息")
@PreAuthorize("@el.check('imMessage:list')")
public ResponseEntity<Object> query(ImMessageQueryCriteria criteria, Pageable pageable){
return new ResponseEntity<>(imMessageService.queryAll(criteria,pageable),HttpStatus.OK);
}
3.日志crud一套
4.日志aop
package com.xxx.aspect; import com.xxx.service.LogService; import lombok.extern.slf4j.Slf4j; import com.xxx.domain.Log; import com.xxx.utils.RequestHolder; import com.xxx.utils.SecurityUtils; import com.xxx.utils.StringUtils; import com.xxx.utils.ThrowableUtil; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; /** * @author * @date 2018-11-24 */ @Component @Aspect @Slf4j public class LogAspect { private final LogService logService; ThreadLocal<Long> currentTime = new ThreadLocal<>(); public LogAspect(LogService logService) { this.logService = logService; } /** * 配置切入点 */ @Pointcut("@annotation(com.xxx.annotation.Log)") public void logPointcut() { // 该方法无方法体,主要为了让同类中其他方法使用此切入点 } /** * 配置环绕通知,使用在方法logPointcut()上注册的切入点 * * @param joinPoint join point for advice */ @Around("logPointcut()") public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { Object result; currentTime.set(System.currentTimeMillis()); result = joinPoint.proceed(); Log log = new Log("INFO",System.currentTimeMillis() - currentTime.get()); currentTime.remove(); HttpServletRequest request = RequestHolder.getHttpServletRequest(); logService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request),joinPoint, log); return result; } /** * 配置异常通知 * * @param joinPoint join point for advice * @param e exception */ @AfterThrowing(pointcut = "logPointcut()", throwing = "e") public void logAfterThrowing(JoinPoint joinPoint, Throwable e) { Long ct = currentTime.get(); if(ct == null)ct = 0l; Log log = new Log("ERROR",System.currentTimeMillis() - ct); currentTime.remove(); log.setExceptionDetail(ThrowableUtil.getStackTrace(e).getBytes()); HttpServletRequest request = RequestHolder.getHttpServletRequest(); logService.save(getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request), (ProceedingJoinPoint)joinPoint, log); } public String getUsername() { try { return SecurityUtils.getCurrentUsername(); }catch (Exception e){ return ""; } } }
以上就是一个基础的全局日志的实现
自定义注解的其他实现,我们可以用反射来获取到注解上面的标记的内容,这样,对于习惯使用代码来生成数据库的开发人员,也可以方便的写出一套代码生成器。