写点什么

cat 监控 http 请求 -CatFilter

用户头像
青乡之b
关注
发布于: 2021 年 04 月 13 日

背景

CatFilter 是用于 http 监控,即 web 项目里的 controller 类里的方法的监控。


实现原理其实就是 servlet 里的 filter。


本文主要讲 springboot web 项目和非 springboot web 项目如何实现监控 url 监控。

CatFilter

是 cat 客户端 jar 里的类,实现了 servlet 里的 Filter 接口。

非 springboot web 项目

直接配置即可,配置 filter 之后,就相当于引入了过滤器,这个和 servlet filter 的使用方法一样。




web.xml


<!-- cat监控http请求-->  <filter>    <filter-name>cat-filter</filter-name>    <filter-class>com.dianping.cat.servlet.CatFilter</filter-class>  </filter>  <filter-mapping>    <filter-name>cat-filter</filter-name>    <url-pattern>*.do</url-pattern>  </filter-mapping>
复制代码

springboob web 项目

如果是拦截所有请求,就直接用 cat 自带的 CatFilter 即可。


但是如果要排除静态资源,就需要扩展 CatFilter,因为 springboot filter 不支持排除资源路径,只支持 pattern 匹配。

扩展 CatFilter

package com.xxx.qrcode.ugate.payment.filter;
import com.dianping.cat.servlet.CatFilter;import java.io.IOException;import java.util.Arrays;import java.util.List;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import org.springframework.util.AntPathMatcher;
/** * 重写CatFilter,排除.js/.css/.html等静态资源 * * @author gzh * @createTime 2021/2/23 2:54 PM */public class QrcodeCatFilter extends CatFilter {
/** * 排除.js/.css/.html等静态资源 */ private static List<String> excludeUrlPatterns = Arrays.asList("/**/*.html", "/**/*.jsp", "/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg", "/**/*.gif", "/**/*.svg");
private static AntPathMatcher antPathMatcher = new AntPathMatcher();
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //获取当前请求的相对路径(即去掉域名/项目名字之后的路径) HttpServletRequest httpServletRequest = (HttpServletRequest)request; String ServletPath = httpServletRequest.getServletPath();
//校验路径是否匹配 boolean b = excludeUrlPatterns.stream() .anyMatch(e -> antPathMatcher.match(e, ServletPath)); if (b) { //如果是静态资源,不走CatFilter chain.doFilter(request, response); }else { //如果不是静态资源,才走CatFilter super.doFilter(request, response, chain); } }}
复制代码


说明


1.自定义扩展类,覆盖了拦截方法 doFilter,会根据是否是静态资源请求路径,来决定要不要被拦截。


2.启动的时候,CatFilter 的 init 等方法,还是会被执行,因为自定义的扩展类继承了 CatFilter。

配置过滤器

配置过滤器


/**   * 配置过滤器   * @return   */  @Bean  public FilterRegistrationBean registerFilter() {    FilterRegistrationBean registration = new FilterRegistrationBean();    registration.setFilter(new QrcodeCatFilter());//    registration.addUrlPatterns("*.do");//    registration.addInitParameter("exclusions", "*.css");//    registration.setName("CatFilter");    return registration;  }
复制代码




完整配置


package com.xxx.xxx.ugate.payment.config.webconfig;
import com.xxx.qrcode.ugate.payment.filter.QrcodeCatFilter;import com.xxx.qrcode.ugate.payment.intercepter.LogPreInterceptor;import xxx.log.logback.web.LogbackConfigListener;import org.springframework.boot.web.servlet.FilterRegistrationBean;import org.springframework.boot.web.servlet.ServletListenerRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/** * LogbackConfigListener配置 * 输出日志文件 */@Configurationpublic class WebConfig implements WebMvcConfigurer {
@Bean public ServletListenerRegistrationBean<LogbackConfigListener> initLogbackConfigListener() { ServletListenerRegistrationBean<LogbackConfigListener> result = new ServletListenerRegistrationBean<>(); result.setListener(new LogbackConfigListener()); return result; }
/** * 配置拦截器 * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new LogPreInterceptor())// .addPathPatterns("/**/*.do") .excludePathPatterns("/**/*.html", "/**/*.jsp", "/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg", "/**/*.gif", "/**/*.svg"); }
/** * 配置过滤器 * @return */ @Bean public FilterRegistrationBean registerFilter() { FilterRegistrationBean registration = new FilterRegistrationBean(); registration.setFilter(new QrcodeCatFilter());// registration.addUrlPatterns("*.do");// registration.addInitParameter("exclusions", "*.css");// registration.setName("CatFilter"); return registration; }}
复制代码

参考

https://github.com/spring-projects/spring-boot/issues/7426

jdk8 知识点

如何排除静态资源请求路径?


自定义扩展过滤器的源码


package com.xxx.qrcode.ugate.payment.filter;
import com.dianping.cat.servlet.CatFilter;import java.io.IOException;import java.util.Arrays;import java.util.List;import javax.servlet.FilterChain;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import javax.servlet.http.HttpServletRequest;import org.springframework.util.AntPathMatcher;
/** * 重写CatFilter,排除.js/.css/.html等静态资源 * * @author gzh * @createTime 2021/2/23 2:54 PM */public class QrcodeCatFilter extends CatFilter {
/** * 排除.js/.css/.html等静态资源 */ private static List<String> excludeUrlPatterns = Arrays.asList("/**/*.html", "/**/*.jsp", "/**/*.css", "/**/*.js", "/**/*.png", "/**/*.jpg", "/**/*.jpeg", "/**/*.gif", "/**/*.svg");
private static AntPathMatcher antPathMatcher = new AntPathMatcher();
@Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { //获取当前请求的相对路径(即去掉域名/项目名字之后的路径) HttpServletRequest httpServletRequest = (HttpServletRequest)request; String ServletPath = httpServletRequest.getServletPath();
//校验路径是否匹配 boolean b = excludeUrlPatterns.stream() .anyMatch(e -> antPathMatcher.match(e, ServletPath)); if (b) { //如果是静态资源,不走CatFilter chain.doFilter(request, response); }else { //如果不是静态资源,才走CatFilter super.doFilter(request, response, chain); } }}
复制代码


排除静态资源的时候,用了 jdk8 的知识点。


1.得到流 stream


主要是从集合得到流,这个是 jdk8 才有的功能和方法。


2.得到流之后,要对流数据进行计算


什么计算?匹配数据。怎么匹配?用 anyMatch 方法来匹配。


3.anyMatch 方法的入参是 Predicate 类型


源码


public interface Stream<T> extends BaseStream<T, Stream<T>> {/**     * Returns whether any elements of this stream match the provided     * predicate.  May not evaluate the predicate on all elements if not     * necessary for determining the result.  If the stream is empty then     * {@code false} is returned and the predicate is not evaluated.     *     * <p>This is a <a href="package-summary.html#StreamOps">short-circuiting     * terminal operation</a>.     *     * @apiNote     * This method evaluates the <em>existential quantification</em> of the     * predicate over the elements of the stream (for some x P(x)).     *     * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,     *                  <a href="package-summary.html#Statelessness">stateless</a>     *                  predicate to apply to elements of this stream     * @return {@code true} if any elements of the stream match the provided     * predicate, otherwise {@code false}     */    boolean anyMatch(Predicate<? super T> predicate);
复制代码


Predicate 类型是函数式接口


/** * Represents a predicate (boolean-valued function) of one argument. * * <p>This is a <a href="package-summary.html">functional interface</a> * whose functional method is {@link #test(Object)}. * * @param <T> the type of the input to the predicate * * @since 1.8 */@FunctionalInterface //有函数式接口注解,说明就是函数式接口,即入参可以是lambda表达式语句或代码块public interface Predicate<T> {
复制代码


4.e 是什么?


e 是遍历流的时候,流里的当前元素。


5.AntPathMatcher


pattern 模式匹配路径,spring 框架自带的匹配路径功能。核心有两点:


1)*.do  *,表示匹配0或多个字符  2)/**  /**,表示匹配0或多个目录
复制代码




参考


jdk8 实战




总结


除了用 Jdk8 里的知识点,去排除静态资源请求路径,当然也可以用传统的代码去排除。具体实现就是遍历集合数据,然后一个个数据去匹配当前请求路径。


参考:https://blog.csdn.net/qq_23934475/article/details/80941877

发布于: 2021 年 04 月 13 日阅读数: 14
用户头像

青乡之b

关注

还未添加个人签名 2014.04.28 加入

还未添加个人简介

评论

发布
暂无评论
cat监控http请求-CatFilter