网站首页 > 技术文章 正文
背景:项目是老项目,而且比较旧为springmvc项目。项目使用的框架为公司内部自己开发,目前已经没有框架的源码可供修改,配置文件写在底层框架内,可以看到但修改不到。
目的是为了实现日志记录功能:
底层框架已经配置了aop 在applicationContext.xml
<aop:aspectj-autoproxy proxy-target-class="true" />配置自动扫描包在applicationContext-servlet.xml
<context:component-scan base-package="com.xxx"></context:component-scan>自定义注解类
**
 * 自定义操作日志记录注解
 * 
 *
 */
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
{
    /**
     * 模块 
     */
    public String title() default "";
    /**
     * 功能
     */
    public BusinessType businessType() default BusinessType.OTHER;
    /**
     * 操作人类别
     */
    public OperatorType operatorType() default OperatorType.MANAGE;
    /**
     * 是否保存请求的参数
     */
    public boolean isSaveRequestData() default true;
}
自定义切面类
@Aspect
@Component
public class LogAspect {
    private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
    // 配置织入点
    @Pointcut("within(com.transin..*) && @annotation(com.transin.waste.annotation.Log)")
    public void logPointCut()
    {
    }
    /**
     * 处理完请求后执行
     *
     * @param joinPoint 切点
     */
    @AfterReturning(pointcut = "logPointCut()", returning = "jsonResult")
    public void doAfterReturning(JoinPoint joinPoint, Object jsonResult)
    {
        handleLog(joinPoint, null, jsonResult);
    }
    /**
     * 拦截异常操作
     *
     * @param joinPoint 切点
     * @param e 异常
     */
    @AfterThrowing(value = "logPointCut()", throwing = "e")
    public void doAfterThrowing(JoinPoint joinPoint, Exception e)
    {
        handleLog(joinPoint, e, null);
    }
    protected void handleLog(final JoinPoint joinPoint, final Exception e, Object jsonResult)
    {
        try
        {
            // 获得注解
            Log controllerLog = getAnnotationLog(joinPoint);
            if (controllerLog == null)
            {
                return;
            }
            // 获取当前的用户
            LoginUser loginUser = SpringUtils.getBean(TokenService.class).getLoginUser(ServletUtils.getRequest());
            // *========数据库日志=========*//
            SysOperLog operLog = new SysOperLog();
            operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
            // 请求的地址
            String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
            operLog.setOperIp(ip);
            // 返回参数
            operLog.setJsonResult(JSON.toJSONString(jsonResult));
            operLog.setOperUrl(ServletUtils.getRequest().getRequestURI());
            if (loginUser != null)
            {
                operLog.setOperName(loginUser.getUsername());
            }
            if (e != null)
            {
                operLog.setStatus(BusinessStatus.FAIL.ordinal());
                operLog.setErrorMsg(e.getMessage().substring(0, 2000));
            }
            // 设置方法名称
            String className = joinPoint.getTarget().getClass().getName();
            String methodName = joinPoint.getSignature().getName();
            operLog.setMethod(className + "." + methodName + "()");
            // 设置请求方式
            operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
            // 处理设置注解上的参数
            getControllerMethodDescription(joinPoint, controllerLog, operLog);
            // 保存数据库
            AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
        }
        catch (Exception exp)
        {
            // 记录本地异常日志
            log.error("==前置通知异常==");
            log.error("异常信息:{}", exp.getMessage());
            exp.printStackTrace();
        }
    }
    /**
     * 获取注解中对方法的描述信息 用于Controller层注解
     *
     * @param log 日志
     * @param operLog 操作日志
     * @throws Exception
     */
    public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog) throws Exception
    {
        // 设置action动作
        operLog.setBusinessType(log.businessType().ordinal());
        // 设置标题
        operLog.setTitle(log.title());
        // 设置操作人类别
        operLog.setOperatorType(log.operatorType().ordinal());
        // 是否需要保存request,参数和值
        if (log.isSaveRequestData())
        {
            // 获取参数的信息,传入到数据库中。
            setRequestValue(joinPoint, operLog);
        }
    }
    /**
     * 获取请求的参数,放到log中
     *
     * @param operLog 操作日志
     * @throws Exception 异常
     */
    private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog) throws Exception
    {
        String requestMethod = operLog.getRequestMethod();
        if (HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod))
        {
            String params = argsArrayToString(joinPoint.getArgs());
            operLog.setOperParam(params.substring(0, 2000));
        }
        else
        {
            Map<?, ?> paramsMap = (Map<?, ?>) ServletUtils.getRequest().getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
            operLog.setOperParam(paramsMap.toString().substring( 0, 2000));
        }
    }
    /**
     * 是否存在注解,如果存在就获取
     */
    private Log getAnnotationLog(JoinPoint joinPoint) throws Exception
    {
        Signature signature = joinPoint.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method != null)
        {
            return method.getAnnotation(Log.class);
        }
        return null;
    }
    /**
     * 参数拼装
     */
    private String argsArrayToString(Object[] paramsArray)
    {
        String params = "";
        if (paramsArray != null && paramsArray.length > 0)
        {
            for (int i = 0; i < paramsArray.length; i++)
            {
                if (!isFilterObject(paramsArray[i]))
                {
                    Object jsonObj = JSON.toJSON(paramsArray[i]);
                    params += jsonObj.toString() + " ";
                }
            }
        }
        return params.trim();
    }
    /**
     * 判断是否需要过滤的对象。
     *
     * @param o 对象信息。
     * @return 如果是需要过滤的对象,则返回true;否则返回false。
     */
    public boolean isFilterObject(final Object o)
    {
        return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse;
    }
}
测试方法
@ResponseBody
@RequestMapping("/change_pwd")
@Log(title = "密码修改",businessType = BusinessType.UPDATE)
public ResultVo changePwd(String pwd,HttpServletRequest request){
    。。。。。。。。。。。。
}如上配置之后发现怎么测试aop都无法成功。
做以下调整之后aop成功
1、在applicationContext-servlet.mxl 添加如下配置
<context:component-scan base-package="com....."></context:component-scan>//切面所在包路径
<aop:aspectj-autoproxy proxy-target-class="true" />2、将切面类采用Bean的方法在配置文件进行注入,我是写在applicationContext.mxl中
<bean id="logAspect" class="com.。。。。。"/>做了以上两步调整之后aop就可以成功了。
总结两点
1、<aop:aspectj-autoproxy proxy-target-class="true" />要写在SpringMVC的配置文件中。
2、如果还是不行就把切面类采用Bean的方法在配置文件进行注入。
以上内容仅个人实践得来,有错误欢迎批评指正。
猜你喜欢
- 2024-12-25 Spring Boot整合Spring Cloud GateWay代理第三方应用的调用接口?
 - 2024-12-25 Java 近期新闻:Hibernate 6.0、JobRunr 5.0、JHipster 7.8.0
 - 2024-12-25 Keycloak Servlet Filter Adapter使用
 - 2024-12-25 如何在Spring Boot中保证RESTful接口的安全性?
 - 2024-12-25 Java项目实战第6天:登录业务的实现
 - 2024-12-25 JavaEE概述总结:Servlet生命周期+JSP内置对象
 - 2024-12-25 SpringBoot 无感刷新 Token springboot的token
 - 2024-12-25 若依开发框架解析笔记(7)-jwt的应用
 - 2024-12-25 Spring MVC中提供了哪些扩展机制?如何使用这些扩展机制?
 - 2024-12-25 49个Spring经典面试题总结(附带答案)
 
- 最近发表
 - 
- 聊一下 gRPC 的 C++ 异步编程_grpc 异步流模式
 - [原创首发]安全日志管理中心实战(3)——开源NIDS之suricata部署
 - 超详细手把手搭建在ubuntu系统的FFmpeg环境
 - Nginx运维之路(Docker多段构建新版本并增加第三方模
 - 92.1K小星星,一款开源免费的远程桌面,让你告别付费远程控制!
 - Go 人脸识别教程_piwigo人脸识别
 - 安卓手机安装Termux——搭建移动服务器
 - ubuntu 安装开发环境(c/c++ 15)_ubuntu安装c++编译器
 - Rust开发环境搭建指南:从安装到镜像配置的零坑实践
 - Windows系统安装VirtualBox构造本地Linux开发环境
 
 
- 标签列表
 - 
- cmd/c (90)
 - c++中::是什么意思 (84)
 - 标签用于 (71)
 - 主键只能有一个吗 (77)
 - c#console.writeline不显示 (95)
 - pythoncase语句 (88)
 - es6includes (74)
 - sqlset (76)
 - apt-getinstall-y (100)
 - node_modules怎么生成 (87)
 - chromepost (71)
 - flexdirection (73)
 - c++int转char (80)
 - mysqlany_value (79)
 - static函数和普通函数 (84)
 - el-date-picker开始日期早于结束日期 (76)
 - js判断是否是json字符串 (75)
 - c语言min函数头文件 (77)
 - asynccallback (87)
 - localstorage.removeitem (77)
 - vector线程安全吗 (73)
 - java (73)
 - js数组插入 (83)
 - mac安装java (72)
 - 无效的列索引 (74)
 
 
