晋江网站建设qzdzi,深圳手机商城网站设计费用,兰州百度网站建设,建设银行怎么网站定制短信通知文章目录前言自定义过滤器并验证关于排除某些请求的方式创建测试接口请求测试验证异常过滤器的执行流程注意事项资料参考前言
在Java-web的开发领域#xff0c;对于过滤器和拦截器用处还是很多#xff0c;但两者的概念却极易混淆。
过滤器和拦截器都是采用AOP的核心思想对于过滤器和拦截器用处还是很多但两者的概念却极易混淆。
过滤器和拦截器都是采用AOP的核心思想对具体的实现方法进行增强都能拦截请求方法。
不同点过滤器拦截器研发者由Servlet研发由SpringMVC研发拦截对象拦截WEB请求拦截器不仅可以拦截请求还能拦截普通方法。执行顺序过滤器会比拦截器优先执行拦截器在过滤器之后执行但使用比过滤器简单。使用场景编码格式转化、跨域解决、xss攻击等权限控制、日志打印、参数验证、回话信息等。
【资料参考】
过滤器和拦截器的异同(小计)springboot配置监听器、过滤器和拦截器
以实际生活中的栗子作为各个名词的描述
过滤器 过滤器好比就是筛子只有满足大小要求的颗粒才能通过过滤器不满足的则会筛出来。拦截器 拦截器就好比是一个门户只能满足要求才能进入
这两者本身上其实都差不多只是在技术层面为了区别各个不同的原理和技术才定义了不同的名词。
本篇博客不说拦截器只说过滤器的使用和基本准则。
自定义过滤器并验证
创建Springboot项目并创建两个自定义的过滤器如下所示
MyFilter1
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;Slf4j
Order(1) // 数字越小 优先级越高
WebFilter(filterName myFilter1,urlPatterns {/*})
public class MyFilter1 implements Filter {Overridepublic void init(FilterConfig filterConfig) throws ServletException {log.info(#### MyFilter1 init ####);}Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {log.info(#### MyFilter1 doFilter ####);log.info(#### MyFilter1 doFilter before ####);chain.doFilter(request,response);log.info(#### MyFilter1 doFilter after ####);}Overridepublic void destroy() {log.info(#### MyFilter1 destroy ####);}
}MyFilter2
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;Slf4j
Order(2) // 数字越小 优先级越高
WebFilter(filterName myFilter2,urlPatterns {/*}) // urlPatterns 设置需要拦截过滤的请求可以正则表达式未指定时会拦截所有请求
public class MyFilter2 implements Filter {Overridepublic void init(FilterConfig filterConfig) throws ServletException {log.info(#### MyFilter2 init ####);}Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {log.info(#### MyFilter2 doFilter ####);log.info(#### MyFilter2 doFilter before ####);String msg request.getParameter(msg);if(err.equalsIgnoreCase(msg)){throw new RuntimeException(传递参数有误验证过滤器....);}chain.doFilter(request,response);log.info(#### MyFilter2 doFilter after ####);}Overridepublic void destroy() {log.info(#### MyFilter2 destroy ####);}
}
可以看到本次使用的是注解方式除了新增这两个自定义的Filter之外还需要在启动类上增加一个注解标识否则自定义的过滤器并不会被加载如下所示
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;SpringBootApplication
ServletComponentScan // 扫描filter
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class,args);}
} ServletComponentScan // 扫描filter 在自定义的过滤器中使用的WebFilter注解方式该注解中需要设定某些值这些参数信息又有什么含义呢
参数名含义filterName给过滤器定义别名称需要唯一区别。urlPatterns过滤器针对的请求url路径默认或者不配置时是过滤所有的请求。此处可以写正则表达式。initParams自定义过滤器初始化参数的数组此参数可以通过自定义过滤器 init() 的入参FilterConfig对象的 getInitParameter() 方法获取由于过滤器没有直接排除自定义URL不拦截的设定如果我们需要在自定义拦截的URL中排除部分不需要拦截的URL可以通过将需要排除的URL放到initParams参数中再在doFilter方法中排除
关于排除某些请求的方式 参考SpringBoot自定义过滤器Filter使用详解 其中有这么一个栗子如下所示
WebFilter(filterName testFilter, urlPatterns /*, initParams WebInitParam(name noFilterUrl, value /test)) // 给定初始化参数
public class TestFilter implements Filter {private ListString noFilterUrls; Overridepublic void init(FilterConfig filterConfig) throws ServletException {// 从过滤器配置中获取initParams参数String noFilterUrl filterConfig.getInitParameter(noFilterUrl);// 将排除的URL放入成员变量noFilterUrls中if (StringUtils.isNotBlank(noFilterUrl)) {noFilterUrls new ArrayList(Arrays.asList(noFilterUrl.split(,)));}}Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)throws IOException, ServletException {// 过滤器配置的 urlPatterns 为 /* 表示过滤所有的请求// 有请求进来时会先进入到过滤器中此时则获取请求的uri地址String url ((HttpServletRequest)servletRequest).getRequestURI();Boolean flag false;if (!CollectionUtils.isEmpty(noFilterUrls)) {for (String noFilterUrl : noFilterUrls) {// 如果请求的地址中包含有 initParams 传递的参数值则不继续向下执行if (url.contains(noFilterUrl)) {flag true;break;}}}if (!flag) {...... //过滤请求响应逻辑} // 继续向下执行调用该方法filterChain.doFilter(servletRequest, servletResponse);}Overridepublic void destroy() {}
}感叹这个作者的奇妙思维方式 创建测试接口
回归正题创建上面两个自定义的过滤器之后还需要创建一个测试接口如下所示
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;RestController
RequestMapping(/test1)
Api(tags 测试控制器 1)
Slf4j
public class TestController {PostMapping(/demo1)ApiOperation(demo1)public String demo1(){log.info(请求被调用了!!!!!);return demo 1 .....;}
}启动项目观察控制台打印。 这里的顺序是加在时的顺序并不是Order(int) 设定的原因 请求测试
清空控制台的日志信息请求测试接口观察控制台日志输出情况如下所示
通过调用自定义过滤器filter的日志打印可以很清楚的了解到请求的执行过程。如下所示 由最开始的客户端请求–》MyFilter1–》MyFilter2–》指定的controller–》MyFilter2–》MyFilter1–》客户端。闭环操作。
这里为什么是MyFilter1在MyFilter2之前根本原因就是定义filter时设定了Order(1)给定了优先级。 数字越小优先级越高 验证异常过滤器的执行流程
在MyFilter2中给定了请求参数 msgerr时抛出异常。
出现异常了后面的filter还会继续执行不接下来再次进行请求测试 查看控制台观察日志信息如下所示 在执行到MyFilter1、MyFilter2后由于MyFilter1中抛出了异常还没有执行对应的chain.doFilter(request,response);后续的链路所以日志在此处戛然而止 出现异常后并不会继续执行后续的filter 注意事项
自定义的Filter类上不要添加 Component 注解不然会导致程序启动报错启动不成功
资料参考
SpringBoot自定义过滤器Filter使用详解
这个大佬博客中给出了第二种方式但总感觉哪里有问题关于第二种方式的配置操作可以参考下列资料
springboot 自定义过滤器