记录日志不是属于
业务需求
,而是系统需求
。
原始的方法就是:比如对业务做一个日志管理,如上图,那么代码耦合度比较高,又是业务代码,又是系统代码;有的业务中加日志,有的不加,就会很复杂,一个要改就会导致代码改动比较大。
所以最好办法
就是就将系统需求拆分出去,单独实现;比如记录日志、权限检查、事务管理等;
那么什么技术能做到这一点呢?那就是Spring中的一大核心 ——AOP
.
demo创建在community项目之上
@Component
@Aspect
public class AlphaAspect {
//定义一个切入点
@Pointcut("execution(* com.yty.community.service.*.*(..))") //范围:第一个*表示什么返回值都行,然后service包下所有的类,所有的方法,所有的参数
public void pointcut(){
}
@Before("pointcut()")
public void before(){
System.out.println("before");
}
@After("pointcut()")
public void after(){
System.out.println("after");
}
@AfterReturning("pointcut()")
public void afterReturning(){
System.out.println("afterReturning");
}
@AfterThrowing("pointcut()")
public void afterThrowing(){
System.out.println("afterThrowing");
}
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
System.out.println("around before");
Object obj = joinPoint.proceed();
System.out.println("around after");
return obj;
}
}
写完之后,目前这些代码针对所有的service就都有效,并且service一行代码也没有改;这就是SpringAOP的强大之处。
启动项目,并clear all 控制台,然后访问首页index
没有抛出这个:
是因为还没报错,报错就回抛,这里不试了。
所有的业务组件进行日志
@Component
@Aspect
public class ServiceLogAspect {
//因为要记日志,所以实例化一个log/或者直接使用后@Sl4j注解
private static final Logger logger = LoggerFactory.getLogger(ServiceLogAspect.class);
//1.声明切点
@Pointcut("execution(* com.yty.community.service.*.*(..))") //范围:第一个*表示什么返回值都行,然后service包下所有的类,所有的方法,所有的参数
public void pointcut(){
}
@Before("pointcut()")
public void before(JoinPoint joinPoint){
//格式: 用户[1.2.3.4],在[xxxTime],访问了[com.yty.community.service.xxx()]
//要想获取这么一个格式,用户ip怎么获取?可通过request获取,但是这个方法里怎么去获取request对象呢,不能直接声明一个request对象,而是利用工具类,然后直接获取request了
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
String ip = request.getRemoteHost();
String now = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
//访问的是某个类某个方法,怎么知道我访问的是哪个类那个方法呢 —— 加一个参数JointPoint
String target = joinPoint.getSignature().getDeclaringTypeName() + "." +joinPoint.getSignature().getName();
logger.info(String.format("用户[%s],在[%s],访问了[%s].", ip,now,target));
}
}
[0:0:0:0:0:0:0:1] 代表的是本机localhost
看着不习惯,localhost可改成127.0.0.1