前面,我们对spring boot 启用Filter 进行了学习与使用。
现在,让我们来使用一些简单的Filter 来完成 请求日志
日志,可以说是API-Server最不可或缺的组件,完整的日志,是错误排查的第一步。在不能线上debug的环境,日志几乎是我们错误排查的唯一途径。
http请求日志,最简单的办法就是在每次请求前,手动打一行日志,看起来比较傻,优点是十分灵活,每个接口都可以按需打印日志,并补充相关信息,日志可读性更强。
比较省时省力的是统一的接口日志,就是将每个请求,在某个统一的地方,打印日志。
这里有三种方式
- Filter 日志
针对request 请求, 使用Servlet 的Filter 用来打印Http 日志 可以说 十分合适。非spring 项目 也可以使用。
public abstract class HttpRequestLogFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpUtils.httpRequestLog(request); // 根据request 中的信息 打印 所需 数据
chain.doFilter(request, resp);
}
}
- Interceptor 日志
相比于 Filter
优点是 Interceptor 的生命周期被 spring context 所管理,所以可以使用 spring 中的 bean。
缺点是,Interceptor 的执行顺序相对靠后,可能存在一些请求在进入 spring 容器前就提前返回了,导致请求无法打印。
Interceptor 中,可以 借助 spring的强大机制,读取 到 Controller方法上 所使用的 注解,并读取到注解所注解的值,当我们需要对不同Controller方法 进行简单的 区分 处理的时候,这个 机制就可以派上用场,比如我可以通过在 controller 上 添加一个注解,并补充 一些接口简介,在Interceptor 中 便可以读取并打印。
public class HttpRequestLogInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
HttpUtils.httpRequestLog(req);
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
super.afterCompletion(request, response, handler, ex);
}
}
- AOP 日志
这里,其实也可以 直接使用 强大的 Spring AOP,相对于 前面的 两种依赖 Http请求的日志,
优点: AOP日志 更为 灵活,同时可以在不是接口调用的 地方(比如业务逻辑处理层) 继续打印日志。还可以结合注解深度定制。完成各种自定义日志。
缺点: 性能损耗较大,同时丢失了请求 本身的 http相关信息,如 HttpMethod,url,ip 等等信息。 - 网关日志
在打日志这个需求上,其实可以跳出 应用程序本身的限制。一般 网络 请求,在落在我们的服务之前,还会有个网关层,如Kong/Nginx,经过合理的配置,可以通过网关来打印日志,优点是,打印的地点非常早,可以做到不漏任何异常情况,与代码充分解耦,每个项目都不需要去处理http入口日志工作。缺点是不好做一些自定义的个性化的请求日志。每个项目配置不同的日志打印姿势,又失去了网关日志的简单粗暴原则。
网友评论