ssm版本:
1、首先自定义一个注解,该注解有两个属性,一个是模块名,一个是操作的内容。该注解是用来修饰Service层中的方法的。
2、创建一个切面类,该切面使用@Aspect和@Component注解修饰,该页面需要注入一个HttpSession对象。
注意:一个普通的java类是不能注入HttpSession对象的,因此需要在web.xml文件中配置
org.springframework.web.util.IntrospectorCleanupListener
org.springframework.web.context.request.RequestContextListener
3、在applicationContext.xml文件中配置aop:aspectj-autoproxy,扫描@Aspect注解。
springboot版本:
日志管理:
1、首先自定义一个注解,自定义的注解需要使用@Target(ElementType.METHOD),@Retention(RetentionPolicy.RUNTIME)修饰,然后给几个属性。
2、定义一个切面然后切面使用@Component,@Aspect修饰,然后定义扫描切入点表达式@After(“execution(* com.syzw.test…service…*(…))”),创建通知类型,通知类型里面可以使用 HttpServletRequest request=((ServletRequestAttributes)(RequestContextHolder.getRequestAttributes())).getRequest();去获取requet对象。
3、在该方法中就可以通过JoinPoint形参去获取实际操作对象的class类,然后就可以获取该到方法,然后可以获取到自定义的注解了就完成了日志的管理。
缺点:
如果需要进行比较信息的日志管理的话,需要在每一个操作dao接口的方法上添加自定义的注解,较为麻烦。
解决方式:
一般会在切面上判断url然后根据url去做相应的操作的,但是这种操作较不灵活。
JoinPoint是一个切入点,它封装了切入点和真实对象的一些信息。
JoinPoint常用的一些api:
getSignature():获取真实访问方法的全路径签名。
getArgs():获取传入目标方法的参数对象。
getTarget():获取被代理的对象。
getThis():获取代理对象。
Signature:
getName():获取操作的方法名。
getClass():获取方法所在的Class类。
注意:
其实每一个注解都对应了一个切面,注解只是其一个声明作用,并没有实际的意义。
使用Spring Aop自定义注解实现自动记录日志
(1)首先配置文件:
<!-- 声明自动为spring容器中配置@aspectj切面的bean建立代理 ,织入切面 -->
<aop:aspectj-autoproxy />
<!-- 开启注解扫描 -->
<context:component-scan base-package="com.ky.zhjd.**"/>
<!-- 为true说明代理基于类被建立(默认false,基于接口被建立) -->
<aop:config proxy-target-class="true"></aop:config>
(2)建立一个自定义注解类spring
注意建立时选Annotation,类名我叫ArchivesLog(日志档案的意思)。
ArchivesLog.java内容:
package com.ky.zhjd.common.log;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* 自定义注解类
*
*/
@Target({ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ArchivesLog {
/** 要执行的操做类型好比:添加操做 **/
public String operationType() default "";
/** 要执行的操做名称好比:添加一条用户数据 **/
public String operationName() default "";
}
(3)新建一个切面类,我叫LogAspect.java
package com.ky.zhjd.common.log;
import java.lang.reflect.Method;
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.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
/**
* 切面类
*/
@Aspect
@Component("logAspect")
public class LogAspect {
private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
// 配置织入点
@Pointcut("@annotation(ArchivesLog)")
public void logPointCut() {
}
/**
* 前置通知 用于拦截操做,在方法返回后执行
*
* @param joinPoint 切点
*/
@AfterReturning(pointcut = "logPointCut()")
public void doBefore(JoinPoint joinPoint) {
handleLog(joinPoint, null);
}
/**
* 拦截异常操做,有异常时执行
*
* @param joinPoint
* @param e
*/
@AfterThrowing(value = "logPointCut()", throwing = "e")
public void doAfter(JoinPoint joinPoint, Exception e) {
handleLog(joinPoint, e);
}
private void handleLog(JoinPoint joinPoint, Exception e) {
try {
// 得到注解
ArchivesLog controllerLog = getAnnotationLog(joinPoint);
System.out.println("---------------自定义注解:" + controllerLog);
if (controllerLog == null) {
return;
}
// 得到方法名称
String className = joinPoint.getTarget().getClass().getName();
String methodName = joinPoint.getSignature().getName();
String type = controllerLog.operationType();
String name = controllerLog.operationName();
// 打印日志 这里能够进行插入数据库操做
log.info(">>>>>>>>>>>>>操做类型:", type);
log.info(">>>>>>>>>>>>>操做名称:", name);
log.info(">>>>>>>>>>>>>类名:", className);
log.info(">>>>>>>>>>>>>方法名:", methodName);
} catch (Exception exp) {
// 记录本地异常日志
log.error("==前置通知异常==");
log.error("异常信息:", exp.getMessage());
exp.printStackTrace();
}
}
/**
* 是否存在注解,若是存在就获取
*/
private static ArchivesLog getAnnotationLog(JoinPoint joinPoint) throws Exception {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
if (method != null) {
// 拿到自定义注解中的信息
return method.getAnnotation(ArchivesLog.class);
}
return null;
}
}
(4)在方法上使用注解 , 而后调用该方法(这里在Controller层进行操作,也可以在Service层操作)
@ArchivesLog(operationType="查询操做",operationName="查询一条用户详情")
@RequestMapping(value = "/findByid", produces={"application/json;charset=UTF-8"})
public @ResponseBody BaseResult<Object> findByid(String id) {
String s="11";
BaseResult<Object> r=userService.findById(s);
System.out.println(r+">>>>>>>>>>");
return r;
}
ok 上效果:
有什么不完善的地方欢迎指出,一块儿学习