发表于: 2019-11-08 20:13:34

1 1168


今天完成的事:
1、实现使用AOP统一处理日志。
Spring也有自己的AOP开发,但是比较繁琐复杂,所以一般都是基于Aspectj的AOP开发,这里需要导入相应的jar包,依赖如下。
首先了解下AOP相关的概念、术语。
通过下面的方法说明,可以知道AOP就是对业务逻辑的各个部分进行隔离,从而使相互之间的耦合度降低,提高程序的可重用性。以日志为例,如果有相关的方法需要添加特定的日志信息,我们就可以在不修改源码的前提下
如下,划线部分为AOP统一的日志处理。这里测试了两个接口,相应的日志输出在每个接口(方法)执行时都进行了操作,这里执行的就是相应的前置、后置通知。
需要编写切面类,定义切面,而后在springmvc.xml中进行配置。
(1)基于配置的xml实现
使用常规类以及基于配置的xml来实现AOP的统一管理。代码如下。
切面类。
springmvc配置,需要先添加aop头部信息,而后定义切面、切入点,并且需要配置切面类的bean,因为springmvc中设置的只扫描controller类的自动装配。
(2)基于注解的实现
同样需要编写切面类,只不过添加了注解,springmvc配置中只是简单的配置,如下。
切面类:
@Aspect
public class LogUtil {
    private static final Logger logger = Logger.getLogger("LogUtil");
    // 定义了一个名为 ‘selectAll’ 的切入点
    // 该切入点将与 com.chuilun.controller.service 包下的类中可用的每一个方法相匹配
    // controller后的“ * ”分别代表所有类、类下的所有方法,“(..)”代表方法内的任意参数
    @Pointcut("execution(* com.chuilun.controller.*.*(..))")
    private void selectAll(){}
    // 在一个方法执行之前,执行通知
    @Before("selectAll()")
    public void beforeAdvice(){
        logger.info("基于注解,准备执行方法");
    }
    // 在一个方法执行之后,不考虑其结果,执行通知
    @After("selectAll()")
    public void afterAdvice(){
        logger.info("基于注解,方法结束");
    }
    // 在一个方法执行之后,只有在方法成功完成时,才能执行通知
    @AfterReturning(pointcut = "selectAll()", returning="retVal")
    public void afterReturningAdvice(Object retVal){
        logger.info("基于注解,方法成功返回:" + retVal.toString() );
    }
    // 在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知
    @AfterThrowing(pointcut = "selectAll()", throwing = "ex")
    public void AfterThrowingAdvice(IllegalArgumentException ex){
        logger.info("基于注解,方法异常为: " + ex.toString());
    }
    // 环绕通知 = 前置 + 目标方法执行 + 后置通知
    @Around("selectAll()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        // 获取方法名
        String methodName=joinPoint.getSignature().getName();
        //getTarget() 获得被织入增强处理的目标对象,类路径
        String className = joinPoint.getTarget().getClass().getName();
        logger.info("环绕前增强=====方法名:" + methodName + ",类路径:" + className);
        // ProceedingJoinPoint 执行 proceed 方法的作用是让目标方法执行,返回结果
        Object obj  = joinPoint.proceed();
        logger.info("环绕后增强=====");
        logger.info("方法成功返回:" + obj.toString());
        return obj;
    }
    // 在一个方法执行之后,只有在方法成功完成时,才能执行通知
/*    @AfterReturning(pointcut = "selectAll()", returning="retVal")
    public void afterReturningAdvice(JoinPoint jp, Object retVal){
        //getTarget() 获得被织入增强处理的目标对象,类路径
        String className = jp.getTarget().getClass().getName();
        // 获取方法名
        String methodName=jp.getSignature().getName();
        logger.info("运行方法名:" + methodName + ",类路径:" + className);
        logger.info("基于注解,方法成功返回:" + retVal.toString() );
    }*/
}
 测试接口,输出如下,基于注解的AOP统一处理也能实现。
查看后,发现少了一个环绕通知。
于是查找相关知识,了解到环绕通知就相当于前置、后置通知各执行一次。入参的ProceedingJoinPoint类的proceed方法作用就是让目标方法执行,而后返回结果。
也就是说 环绕通知 = 前置 + 目标方法执行 + 后置通知。
而ProceedingJoinPoint类继承JoinPoint类,在其基础上暴露出proceed方法,这个方法才能支持aop:around这种切面,其他几种切面只需要用到JoinPoint类即可。
JoinPoint类可以用getTarget方法获得被处理的目标对象以及类路径,也可以用getSignature().getName()方法获得方法名称。
同样,ProceedingJoinPoint类也可以使用这些方法。
2、使用validator进行校验,国际化配置错误信息。
这里controller类需要注意的是,之前任务二编写的有jsp页面,将错误信息直接获取全部,传递到jsp,使用form标签即可按照对应的字段显示错误信息。但是现在没有jsp页面,只能使用postman进行测试,如果还是使用 getAllErrors() 方法,直接遍历填入map集合中,输出的有很多无用代码,错误信息查看不直观。
百度后得知,使用 getFieldErrors() 方法获取错误信息,而后遍历,再使用 getField() 获取错误变量名,getDefaultMessage() 方法获取错误信息,填入map集合,就是键值对的关系体现,清晰明了。配置信息没有变化,这里就不放了。
实体类检验的变量。
国际化配置文件中的错误信息。
使用AOP统一管理日志输出的信息。
postman成功返回的错误信息。
3、以mybatis逆向工程生成的项目整理代码,用于提交任务。
测试两个接口,成功返回数据,明天部署服务器。

明天计划的事:
1、项目代码部署服务器。
2、提交任务,进行总结。
3、查看深度思考。
遇到的问题:
收获:
1、实现使用AOP统一处理日志。
(1)使用常规类以及基于配置的xml来实现。
(2)常规类内添加注解,基于注解的方式实现。
了解了如何编写切面、切入点,通知的分类以及设置,ProceedingJoinPoint类以及JoinPoint类的相关使用。
2、使用validator进行校验,国际化配置错误信息。
controller类需要注意使用 getFieldErrors() 方法获取错误信息,而后遍历,再使用 getField() 获取错误变量名,getDefaultMessage() 方法获取错误信息,填入map集合,就是键值对的关系体现,清晰明了。
3、以mybatis逆向工程生成的项目整理代码,用于部署服务器。

返回列表 返回列表
评论

    分享到