controller层统一拦截进行日志处理

前言

在项目中添加统一日志时,我们往往会用到aop进行切面处理,常用在controller层添加切面,以处理请求和返回的各项参数数据。

使用切面进行日志处理

下面我们就看一个例子说明基本的使用方式:

package com.ding.test.core.aspect;

import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Aspect
@Component
public class LogAspect {
    private final static Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);
   //定义切点
    @Pointcut("execution(* com.ding..controller.*.*(..))")
    public void printLog() {

    }
    /**
     * 会话ID
     */
    private final static String SESSION_TOKEN_KEY = "sessionTokenId";

    @Around("printLog()")
    private Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        long startTime = System.currentTimeMillis();
         String token = java.util.UUID.randomUUID().toString().replaceAll("-", "").toUpperCase();
         MDC. put(SESSION_TOKEN_KEY, token);
        RequestAttributes ra = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes sra = (ServletRequestAttributes) ra;
        HttpServletRequest request = sra.getRequest();

        // 获取请求相关信息
        String url = request.getRequestURL().toString();
        String method = request.getMethod();
        String uri = request.getRequestURI();
        String queryString = request.getQueryString();

        // 获取调用方法相信
        Signature signature = pjp.getSignature();
        String className = signature.getDeclaringTypeName();
        String methodName = signature.getName();
    //这里定义log输出的内容,前面是内容格式,{}按照顺序被替换为后面参数的具体值
        LOGGER.info("请求开始, {}#{}() URI: {}, method: {}, URL: {}, params: {}", className, methodName, uri, method, url,
                queryString);
        //result的值就是被拦截方法的返回值
        try {
            //proceed方法是调用实际所拦截的controller中的方法,这里的result为调用方法后的返回值
            Object result = pjp.proceed();
            long endTime = System.currentTimeMillis();
            //定义请求结束时的返回数据,包括调用时间、返回值结果等
            LOGGER.info("请求结束, {}#{}(), URI: {}, method: {}, URL: {}, time: {}ms, result: {} ", className, methodName,
                    uri, method, url, (endTime - startTime), result);
            return result;
        } catch (Exception e) {
            long endTime = System.currentTimeMillis();
            LOGGER.error("请求出错, {}#{}(), URI: {}, method: {}, URL: {}, time: {}ms", className, methodName, uri, method,
                    url, (endTime - startTime), e);
            throw e;
        }finally {
            MDC. remove(SESSION_TOKEN_KEY);
        }
    }
}

本来spring就自带一套aop实现,我们直接使用此实现即可,本来使用aop还需要定义一些xml文件,但由于我们使用的是spring-boot框架,这一步就省略掉了。也就是说,在spring-boot中,我们可以直接使用aop而不需要任何的配置。

这里我们分析一下上面的示例代码:

@Aspect:描述一个切面类,定义切面类的时候需要打上这个注解

@Component:泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

@PointCut("execution(* com.ding..controller.*.*(..))"):定义切点,括号内的为拦截的路径,这里指目录下的controller中所以方法

这里定义切点的方法为printLog(),在进行前置通知、后置通知、环绕通知的时候,就可以根据这个方法进行拦截。这里我们用到了环绕通知的方式: @Around("printLog()"),定义后,在进行controller中方法调用时就会先调用这里的doAround方法。方法中的含义在注释中已经写清楚了,可以打断点再看每段代码的具体含义。

后记

本文通过一个案例讲解了一下使用切面进行日志处理的功能,重点在于配置切点、环绕通知、方法调用。这些成功后就按照自己需求进行日志内容的输出了。

==================================================================================

输出倒逼输入,作为技术人员教是最好的学习方法,我是一名爱思考、爱学习、涉猎广泛想搞事情的程序员。

坚持就是娱乐,因为惊喜更重要

==================================================================================

时间: 2024-08-29 15:38:39

controller层统一拦截进行日志处理的相关文章

【统一异常处理】@ControllerAdvice + @ExceptionHandler 全局处理 Controller 层异常

1.利用springmvc注解对Controller层异常全局处理 对于与数据库相关的 Spring MVC 项目,我们通常会把 事务 配置在 Service层,当数据库操作失败时让 Service 层抛出运行时异常,Spring 事物管理器就会进行回滚. 如此一来,我们的 Controller 层就不得不进行 try-catch Service 层的异常,否则会返回一些不友好的错误信息到客户端.但是,Controller 层每个方法体都写一些模板化的 try-catch 的代码,很难看也难维护

@ControllerAdvice + @ExceptionHandler全局处理Controller层异常(转)

0.前言 对于与数据库相关的Spring MVC项目,我们通常会把事务配置在 Service层,当数据库操作失败时让Service层抛出运行时异常,Spring事物管理器就会进行回滚. 如此一来,我们的Controller层就不得不进行try-catch Service层的异常,否则会返回一些不友好的错误信息到客户端.但是,Controller层每个方法体都写一些模板化的try-catch的代码,很难看也难维护,特别是还需要对Service层的不同异常进行不同处理的时候.例如以下 Control

用户操作拦截并作日志记录--自定义注解+AOP拦截

作为运营除了处理系统生产问题,还要处理大量的用户上报事件,这部分工作占用了大量的人力.所有考虑把一部分事件查询处理做成一个自助平台,让用户自行核查处理.于是就有了用户自助系统.考虑到如何计量这个工具平台具体的实现价值,需要做用户操作统计才能给出可信服的数据. 以上就是本文的背景.自助系统的架构就是传统的springmvc+spinrg+mybatis+oracle.想到日志记录首先想到的就是AOP拦截处理.网上相关的技术贴很多.简单的小项目遇到的问题一般度娘都能给解决了~\(≧▽≦)/~ 自定义

Spring Mvc 在非controller层 实现获取request对象

一般我们在Controller层,会编写类似这样的方法 @Controller @RequestMapping(value="/detail") public class GetURIDetailController { @SystemControllerLog(description = "id") @RequestMapping(value="/{id}",method={RequestMethod.GET}) public ModelAnd

spring-mvc 非 controller 层获取HttpServletRequest

在项目中记录操作日志,是一种很常见的需求. 有时我们在service或者dao层记录日志,需要同时保存访问ip.登录用户名等.如果从controller层把HttpServletRequest 对象传过去会显得很麻烦.HttpSession可以通过HttpServletRequest 间接获取. 在web.xml配置 <listener>   <listener-class>org.springframework.web.context.request.RequestContext

关于model层变更如何通知controller层

在IOS的mvvm模式中,model层的变更主要有两种方式,一种是delegate,一种是kvo delegate就是定义一套协议,然后controller实现这套协议,在数据变更的时候直接通过delegate通知controller层,因为delefate需要实现很多协议,会有一点低耦合,而kvo的解决办法是,在controller层 去监听某个model的某个属性,然后写一个统一的方法去相应属性的变更,这样的好处就是 我不需要去指定实现某种协议,所以的变更控制都在controller层.那这

DAO层,Service层,Controller层、View层介绍

来自:http://jonsion.javaeye.com/blog/592335 DAO层 DAO 层主要是做数据持久层的工作,负责与数据库进行联络的一些任务都封装在此,DAO层的设计首先是设计DAO的接口,然后在Spring的配置文件中定义此 接口的实现类,然后就可在模块中调用此接口来进行数据业务的处理,而不用关心此接口的具体实现类是哪个类,显得结构非常清晰,DAO层的数据源配置,以及 有关数据库连接的参数都在Spring的配置文件中进行配置. Service层 Service 层主要负责业

sqlmap批量扫描burpsuite拦截的日志记录

1.功能上,sqlmap具备对burpsuite拦截的request日志进行批量扫描的能力 python sqlmap.py -l hermes.log --batch -v 3 --batch:会自动选择yes -l : 指定日志文件 -v: 调试信息等级,3级的话,可以看大注入的payload信息 2.如何配置burpsuite拦截扫描对象? 4.其他方式拦截的request日志文件,也可以 5.使用--smart智能探测效果不是很好,还是采用一些配置,加深扫描比较好 python sqlm

Junit mockito 测试Controller层方法有Pageable异常

1.问题 在使用MockMVC+Mockito模拟Service层返回的时候,当我们在Controller层中参数方法调用有Pageable对象的时候,我们会发现,我们没办法生成一个Pageable的对象,会报一个Pageable是一个接口的错误.当我们把所有的参数从Pageable接口变成Pageable的实现类PageRequest的时候,所有的方法参数都换成PageRequest,又会出现一个新的错误,且不说PageRequest不能作为参数用于hibernate的分页查询,另一方面,它没