多平台统一管理软件接口,如何实现多平台统一管理软件接口
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.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小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~