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

网友投稿 442 2023-01-22


详解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 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 http://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_SQsDJPeHYERROR;

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


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Java中ArrayList在foreach里remove的问题详析
下一篇:如何动态改变Retrofit的base url和rest版本详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~