详解AOP与Filter拦截请求打印日志实用例子

 更新时间:2018年09月10日 15:25:26   作者:EalenXie  
这篇文章主要介绍了详解AOP与Filter拦截请求打印日志实用例子,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

相信各位同道在写代码的时候,肯定会写一些日志打印,因为这对往后的运维而言,至关重要的。

那么我们请求一个restfull接口的时候,哪些信息是应该被日志记录的呢?

以下做了一个基本的简单例子,这里只是示例说明基本常规实现记录的信息,根据项目的真实情况选用:

1 . Http请求拦截器(Filter) : 从HttpServletRequest获取基本的请求信息

import name.ealen.util.HttpUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by EalenXie on 2018/9/7 15:56.
 * Http请求拦截器,日志打印请求基本相关信息
 */
@Configuration
public class FilterConfiguration {

  private static final Logger log = LoggerFactory.getLogger(FilterConfig.class);

  @Bean
  @Order(Integer.MIN_VALUE)
  @Qualifier("filterRegistration")
  public FilterRegistrationBean filterRegistration() {
    FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
    registration.setFilter(controllerFilter());
    registration.addUrlPatterns("/*");
    return registration;
  }

  private Filter controllerFilter() {
    return new Filter() {
      @Override
      public void init(FilterConfig filterConfig) {
        log.info("ControllerFilter init Success");
      }

      @Override
      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        String requestId = request.getHeader("Request-Id");
        if (requestId == null) requestId = request.getRequestedSessionId();
        System.out.println();
        log.info("Http Request Request-Id : " + requestId);
        log.info("Http Request Information : {\"URI\":\"" + request.getRequestURL() +
            "\",\"RequestMethod\":\"" + request.getMethod() +
            "\",\"ClientIp\":\"" + HttpUtil.getIpAddress(request) +
            "\",\"Content-Type\":\"" + request.getContentType() +
            "\"}");
        chain.doFilter(request, response);
      }

      @Override
      public void destroy() {
        log.info("ControllerFilter destroy");
      }
    };
  }
}

2 . Controller的拦截AOP : 获取 请求的对象,请求参数,返回数据,请求返回状态,内部方法耗时。

import com.alibaba.fastjson.JSON;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * Created by EalenXie on 2018/9/7 14:19.
 * AOP打印日志 : 请求的对象,请求参数,返回数据,请求状态,内部方法耗时
 */
@Aspect
@Component
public class ControllerInterceptor {

  private static final Logger log = LoggerFactory.getLogger(ControllerInterceptor.class);
  @Resource
  private Environment environment;

  @Around(value = "execution (* name.ealen.web.*.*(..))")
  public Object processApiFacade(ProceedingJoinPoint pjp) {
    String appName;
    try {
      appName = environment.getProperty("spring.application.name").toUpperCase();
    } catch (Exception e) {
      appName = "UNNAMED";
    }
    long startTime = System.currentTimeMillis();
    String name = pjp.getTarget().getClass().getSimpleName();
    String method = pjp.getSignature().getName();
    Object result = null;
    HttpStatus status = null;
    try {
      result = pjp.proceed();
      log.info("RequestTarget : " + appName + "." + name + "." + method);
      log.info("RequestParam : " + JSON.toJSON(pjp.getArgs()));
      if (result instanceof ResponseEntity) {
        status = ((ResponseEntity) result).getStatusCode();
      } else {
        status = HttpStatus.OK;
      }
    } catch (Throwable throwable) {
      status = HttpStatus.INTERNAL_SERVER_ERROR;
      result = new ResponseEntity<>("{\"Internal Server Error\" : \"" + throwable.getMessage() + "\"}", status);
      throwable.printStackTrace();
    } finally {
      log.info("ResponseEntity : {" + "\"HttpStatus\":\"" + status.toString() + "\"" + ",\"ResponseBody\": " + JSON.toJSON(result) + "}");
      log.info("Internal Method Cost Time: {}ms", System.currentTimeMillis() - startTime);
    }
    return result;
  }
}

3 . 提供一个简单的restfull接口 :

package name.ealen.web;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by EalenXie on 2018/9/7 14:24.
 */
@RestController
public class SayHelloController {

  @RequestMapping("/sayHello")
  public String sayHello() {
    return "hello world";
  }

  @RequestMapping("/say")
  public ResponseEntity<?> say(@RequestBody Object o) {
    return new ResponseEntity<>(o, HttpStatus.OK);
  }

}

4 . 使用Postman进行基本测试 :

5 . 控制台可以看到基本效果 :

以上只是关于Controller应该记录日志的一个简单的例子,完整代码可见 https://github.com/EalenXie/springboot-controller-logger

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 浅谈java8 stream flatMap流的扁平化操作

    浅谈java8 stream flatMap流的扁平化操作

    这篇文章主要介绍了浅谈java8 stream flatMap流的扁平化操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • IDEA java出现无效的源发行版14解决方案

    IDEA java出现无效的源发行版14解决方案

    这篇文章主要介绍了IDEA java出现无效的源发行版14解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • Spring boot中PropertySource注解的使用方法详解

    Spring boot中PropertySource注解的使用方法详解

    这篇文章主要给大家介绍了关于Spring boot中PropertySource注解的使用方法,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧。
    2017-12-12
  • Java ArrayList实现删除指定位置的元素

    Java ArrayList实现删除指定位置的元素

    目标:list中有0到39共40个元素,删除其中索引是10、20、30的元素。本文为大家整理了三个不同的方法,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-01-01
  • Java 十大排序算法之堆排序刨析

    Java 十大排序算法之堆排序刨析

    堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构
    2021-11-11
  • Spring  AOP的两种使用方法

    Spring  AOP的两种使用方法

    这篇文章主要介绍了Spring AOP的两种使用方法,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下
    2022-08-08
  • Java实现八种排序算法详细代码举例

    Java实现八种排序算法详细代码举例

    排序问题一直是程序员工作与面试的重点,今天特意整理研究下与大家共勉!这篇文章主要介绍了Java实现八种排序算法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-10-10
  • 阿里云OSS域名配置及简单上传的示例代码

    阿里云OSS域名配置及简单上传的示例代码

    这篇文章主要介绍了阿里云OSS域名配置及简单上传的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • Java如何基于wsimport调用wcf接口

    Java如何基于wsimport调用wcf接口

    这篇文章主要介绍了Java如何基于wsimport调用wcf接口,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • java输入时如何通过回车(enter)来结束输入

    java输入时如何通过回车(enter)来结束输入

    这篇文章主要介绍了java输入时如何通过回车(enter)来结束输入,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05

最新评论