首页 > 编程 > Java > 正文

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

2019-11-26 09:39:47
字体:
来源:转载
供稿:网友

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

那么我们请求一个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请求拦截器,日志打印请求基本相关信息 */@Configurationpublic 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@Componentpublic 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. */@RestControllerpublic 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

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表