相信各位同道在写代码的时候, 肯定会写一些日志打印, 因为这对往后的运维而言, 至关重要的.
那么我们请求一个 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.MINVALUE)
- 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("RequestId");
- if (requestId == null) requestId = request.getRequestedSessionId();
- System.out.println();
- log.info("Http Request RequestId :" + requestId);
- log.info("Http Request Information : {\"URI\":\"" + request.getRequestURL() +
- "\",\"RequestMethod\":\"" + request.getMethod() +
- "\",\"ClientIp\":\"" + HttpUtil.getIpAddress(request) +
- "\",\"ContentType\":\"" + 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.INTERNALSERVERERROR;
- 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/springbootcontrollerlogger
感谢各位提出意见和支持.
来源: https://www.cnblogs.com/ealenxie/p/9618693.html