您的位置:首页 > 编程语言 > Java开发

两种基于AOP的日志管理方法(springboot)

2017-07-10 22:00 656 查看
AOP基于切面编程,这里的日志管理俩种分别是

不需要配置xml文件

1、切面类不做实际操作,切入点针对所有的controller类,各个需要保存日志的操作方法,分别执行日志保存的方法,更具有针对性。

2、通过自定义注解,针对方法级别,各个需要保存日志的方法上加自定义注解进行保存操作,实际相当于将日志保存方法提取出来,然后以注解方式应用在每个需要的方法上。

先把第一种介绍一下

LogAspect.java

@Aspect
@Component
public class LogAspect {

/**
* 这句话是方法切入点
* 1 execution (* com.my.blog.website.controller..*.*(..))
* 2 execution : 表示执行
* 3 第一个*号 : 表示返回值类型, *可以是任意类型
* 4 com.my.blog.website.controller : 代表扫描的包
* 5 .. : 代表其底下的子包也进行拦截
* 6 第二个*号 : 代表对哪个类进行拦截,*代表所有类
* 7 第三个*号 : 代表方法  *代表任意方法
* 8 (..) : 代表方法的参数有无都可以
*/
//配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点
@Pointcut("execution( * com.my.blog.website.controller..*.*(..))")
public void webLog(){}
//前置通知等可以没有JoinPoint参数
@Before("webLog()")
public void doBefore(JoinPoint joinPoint) throws Throwable {
// 接收到请求,记录请求内容
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
// 记录下请求内容
LOGGER.info("URL : " + request.getRequestURL().toString() + ",IP : " + request.getRemoteAddr() + ",CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName() + ",ARGS : " + Arrays.toString(joinPoint.getArgs()));
}

//配置后置返回通知,使用在方法webLog()上注册的切入点
@AfterReturning(returning = "object", pointcut = "webLog()")
public void doAfterReturning(Object object) throws Throwable {
// 处理完请求,返回内容
LOGGER.info("RESPONSE :" + object);
}
}


应用:

@PostMapping(value = "/profile")
@ResponseBody
@Transactional(rollbackFor = TipException.class)
public RestResponseBo saveProfile(@RequestParam String screenName, @RequestParam String email, HttpServletRequest request, HttpSession session) {

UserVo users = this.user(request);
if (StringUtils.isNotBlank(screenName) && StringUtils.isNotBlank(email)) {
UserVo temp = new UserVo();
temp.setUid(users.getUid());
temp.setScreenName(screenName);
temp.setEmail(email);
userService.updateByUid(temp);
//这里需要单独保存日志信息,
logService.insertLog(LogActions.UP_INFO.getAction(), GsonUtils.toJsonString(temp), request.getRemoteAddr(), this.getUid(request));

//更新session中的数据
UserVo original = (UserVo) session.getAttribute(WebConst.LOGIN_SESSION_KEY);
original.setScreenName(screenName);
original.setEmail(email);
session.setAttribute(WebConst.LOGIN_SESSION_KEY, original);
}
return RestResponseBo.ok();
}


第二种

SysLogAspect.java

@Aspect      //定义切面
@Component   //声明组件
public class SysLogAspect {

@Autowired
private ILogService logService;
//这里切入点是自定义注解,下面有注解的代码
@Pointcut("@annotation(com.my.blog.website.annotation.SysLog)")
public void logPointCut(){

}
//配置环绕通知,使用在方法logPointCut()上注册的切入点
@Around("logPointCut()")
public Object around(ProceedingJoinPoint point)throws Throwable{
long beginTime=System.currentTimeMillis();
//执行方法
Object result=point.proceed();
//可以设置time,监控方法执行的时间,但是我没有去实现
long time=System.currentTimeMillis()-beginTime;
saveSysLog(point,time);
return result;
}

private void saveSysLog(Pro
4000
ceedingJoinPoint point, long time){

MethodSignature signature=(MethodSignature) point.getSignature();

Method method=signature.getMethod();

LogVo log=new LogVo();
SysLog sysLog=method.getAnnotation(SysLog.class);

HttpServletRequest request=((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
//从session中获取用户
UserVo user=(UserVo) request.getSession().getAttribute(WebConst.LOGIN_SESSION_KEY);

//获取请求参数
Object[] args=point.getArgs();

logService.insertLog(sysLog.value().getAction(), GsonUtils.toJsonString(args[0]), request.getRemoteAddr(), user.getUid());

}

}


注解代码:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface SysLog {

LogActions value() default LogActions.LOGIN;
}


枚举类用来存放操作的名字

public enum LogActions {

LOGIN("登录后台"), UP_PWD("修改密码"), UP_INFO("修改个人信息"),
DEL_ARTICLE("删除文章"), DEL_PAGE("删除页面"), SYS_BACKUP("系统备份"),DEL_COMMENT("删除评论"),
SYS_SETTING("保存系统设置"), INIT_SITE("初始化站点");

private String action;

public String getAction() {
return action;
}

public void setAction(String action) {
this.action = action;
}

LogActions(String action) {
this.action = action;
}


应用:

@SysLog(LogActions.UP_INFO)
@PostMapping(value = "/profile")
@ResponseBody
@Transactional(rollbackFor = TipException.class)
public RestResponseBo saveProfile(@RequestParam String screenName, @RequestParam String email, HttpServletRequest request, HttpSession session) {

UserVo users = this.user(request);
if (StringUtils.isNotBlank(screenName) && StringUtils.isNotBlank(email)) {
UserVo temp = new UserVo();
temp.setUid(users.getUid());
temp.setScreenName(screenName);
temp.setEmail(email);
userService.updateByUid(temp);

//更新session中的数据
UserVo original = (UserVo) session.getAttribute(WebConst.LOGIN_SESSION_KEY);
original.setScreenName(screenName);
original.setEmail(email);
session.setAttribute(WebConst.LOGIN_SESSION_KEY, original);
}
return RestResponseBo.ok();
}


这种只需要在你的方法上加上注解@SysLog(LogActions.UP_INFO),LogActions.UP_INFO这个是自定义的一个类型,这里可以直接放string类型的数据,不过需要修改注解定义那里。

至此,两种AOP日志管理搞定,主要是要做个记录,同时熟悉熟悉AOP这个技巧,真的很实用,希望可以帮到需要的人。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  aop 应用 日志
相关文章推荐