设计模式-拦截过滤器模式
背景
每次登陆手机版的各大商城,点击购买的时候都会进行拦截有没有登陆过,若存在的鉴权在有效期或者已经登陆过了,就直接进入支付环节,若登陆信息不存在或失效则直接被要求重新登陆,其中这里面如果用户是没有登陆会被过滤器过滤,是否可能继续请求。
拦截过滤器模式是什么?
拦截过滤器模式(Intercepting Filter Pattern)用于对应用程序的请求或响应做一些预处理/后处理。定义过滤器,并在把请求传给实际目标应用程序之前应用在请求上。过滤器可以做认证/授权/记录日志,或者跟踪请求,然后把请求传给相应的处理程序。
角色:
过滤器(Filter):过滤器在请求处理程序执行请求之前或之后,执行某些任务。
过滤器链(Filter Chain):过滤器链带有多个过滤器,并在 Target 上按照定义的顺序执行这些过滤器。
处理程序(Target ):请求处理程序;
过滤管理器(Filter Manager):过滤管理器管理过滤器和过滤器链。
客户端(Client):Client 是向 Target 对象发送请求的对象。
优点:
低耦合高内聚:通过过滤管理器统一内聚了过滤链,将所有的过滤器统一聚合在一起,而之间耦合度非常低;
复用性高:由于有过滤链,所以可以建立很多的不同链而链中的过滤器是一样的,可以提高过滤器复用性;
预处理:由于用户请求可以在未进入主程序就被拦截到,所有可以提前就预处理了该用户请求的信息;
缺点:
增加程序的复杂度,由于增加了非常多的过滤器会导致该程序复杂度变高;
拦截过滤器模式可以干嘛?
过滤器主要是用来过滤一些非法请求,设置一些请求的编码或格式,将请求中的rquest信息进行过滤或添加一些请求头信息,常用的是配置统一编码或者配置cors一些非法攻击等。
个人理解:
拦截过滤器就像你去坐地铁,首先要通过检查,符合才能进,不符合可能直接被拉走,然后进入地铁,要刷卡、扫码或投币,如果刚好手机没电了那不好意思用投币或刷卡吧,当进入后,会根据你乘的信息出站时统一收费。
拦截过滤器模式类图
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
实现代码
/**
* @Auther: csh
* @Date: 2020/7/3 15:13
* @Description:抽象过滤器(abstract filter)
*/
public interface IFilter {
public void execute(String request);
}
/**
* @Auther: csh
* @Date: 2020/7/3 15:20
* @Description: 权限过滤器(filter)
*/
public class AuthorizationFilter implements IFilter {
@Override
public void execute(String request) {
if(request.contains("admin")){
System.out.println("进入管理后台");
}else{
System.out.println("没有权限");
}
}
}
/**
* @Auther: csh
* @Date: 2020/7/3 15:21
* @Description:日志记录过滤器(filter)
*/
public class LogFitler implements IFilter {
@Override
public void execute(String request) {
System.out.println("日志记录:"+request);
}
}
/**
* @Auther: csh
* @Date: 2020/7/3 15:30
* @Description:请求进行处理
*/
public class Target {
public void execute(String request){
String user = request.contains("admin")?"管理员":"用户";
System.out.println(user+"进行登陆");
}
}
/**
* @Auther: csh
* @Date: 2020/7/3 15:31
* @Description:过滤链
*/
public class FilterChain {
private List<IFilter> filters = new ArrayList <IFilter>();
private Target target;
public void addFilter(IFilter filter){
filters.add(filter);
}
public void excute(String request){
for (IFilter filter : filters) {
filter.execute(request);
}
target.execute(request);
}
public void setTarget(Target target){
this.target = target;
}
}
/**
* @Auther: csh
* @Date: 2020/7/3 15:37
* @Description:过滤管理器
*/
public class FilterManager {
FilterChain filterChain;
public FilterManager(Target target){
filterChain = new FilterChain();
filterChain.setTarget(target);
}
public void setFilter(IFilter filter) {
filterChain.addFilter(filter);
}
public void filterRequest(String request){
filterChain.excute(request);
}
}
/**
* @Auther: csh
* @Date: 2020/7/3 15:40
* @Description:用户
*/
public class Client {
FilterManager filterManager;
public void setFilterManager(FilterManager filterManager){
this.filterManager = filterManager;
}
public void sendRequest(String request){
filterManager.filterRequest(request);
}
}
/**
* @Auther: csh
* @Date: 2020/7/3 15:41
* @Description:
*/
public class Test {
public static void main(String[] args) {
FilterManager filterManager = new FilterManager(new Target());
filterManager.setFilter(new AuthorizationFilter());
filterManager.setFilter(new LogFitler());
Client client = new Client();
client.setFilterManager(filterManager);
client.sendRequest("admin");
client.sendRequest("USER");
}
}
结果
进入管理后台
日志记录:admin
管理员进行登陆
没有权限
日志记录:USER
用户进行登陆
源码下载:https://gitee.com/hong99/design-model/issues/I1IMES
最后
拦截过滤器,其实过滤器是过滤器,拦截器是拦截器,在实际spring、springboot或其他框架中,过滤器主要用来过滤一些非法的用户请求或用户请求的时候在请求头中添加特定的定信息,而拦截器则通过过滤器传递过来的信息对用户进行拦截,然后再转发到相应的下一层。
过滤器场景使用:
在web.xml中
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.allowOrigin</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET, POST, HEAD, PUT, DELETE</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>Access-Control-Allow-Origin,Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
</init-param>
<init-param>
<param-name>cors.exposedHeaders</param-name>
<param-value>Set-Cookie</param-value>
</init-param>
<init-param>
<param-name>cors.supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
</filter>
参考文章:
https://www.cnblogs.com/syuf/p/6845406.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Centos7.2 编译安装PHP7.0.2的步骤
- Linux系统下为Nginx安装多版本PHP
- Linux系统下多版本php共存的解决方案(超简单)
- 宝塔Windows面板的安装Discuz! Q方法
- 并发情况下,单例模式之双重检验锁陷阱
- Android多种方式实现相机圆形预览的示例代码
- composer 下载太慢,无法完成安装
- 数字签名与数字证书
- Android TreeView实现带复选框树形组织结构
- Discuz! Q在Windows下CA根证书库错误
- 6种查看Linux进程占用端口号的方法详解
- Flutter 侧滑栏及城市选择UI的实现方法
- 使用iptable和Firewalld工具来管理Linux防火墙连接规则
- 如何使用Flutter开发一款电影APP详解
- Linux获取10个你最常用的终端命令列表