一、基于责任链模式封装网关拦截

上一篇文章中已经使用建造者模式对网关拦截进行封装,存在一个问题,在连接器build中,每一个拦截都要进行true判断,代码看起来冗余,下面使用责任链模式封装

1、基于责任链设计模式封装: 创建网关请求拦截接口

/**
* @Description: 基于责任链设计模式封装: 网关请求拦截
* @Author: kevin
* @CreateTime: 2019-08-26 22:09
* @Version: V1.0
*/
public interface GatewayHandler {
/**
* Handler处理器: 网关拦截处理请求
*/
public void service(RequestContext ctx, String ipAddress, HttpServletRequest request, HttpServletResponse response); /**
* 指向下一个handler
*/
public void setNextHandler(GatewayHandler nextGatewayHandler); /**
* 获取下一个Handler
*
* @return
*/
public GatewayHandler getNextHandler();
}

2、实现接口业务逻辑

/**
* @Description: 相同的Handler业务逻辑重构
* @Author: kevin
* @CreateTime: 2019-08-26 23:02
* @Version: V1.0
*/
public class BaseHandler { protected GatewayHandler nextGatewayHandler; public void setNextHandler(GatewayHandler nextGatewayHandler) {
this.nextGatewayHandler=nextGatewayHandler;
} /**
* 网关拦截
* @param ctx
* @param code
* @param errorMsg
*/
protected void resultError(RequestContext ctx, String errorMsg) {
ctx.setResponseStatusCode(401);
// 网关响应为false 不会转发服务
ctx.setSendZuulResponse(false);
ctx.setResponseBody(errorMsg); }
}
/**
* @Description: [流程1] 基于责任链设计模式封装: 黑名单拦截
* @Author: kevin
* @CreateTime: 2019-08-26 22:17
* @Version: V1.0
*/
@Slf4j
//@Component
public class BlackBlockHandler extends BaseHandler implements GatewayHandler { @Override
public void service(RequestContext ctx, String ipAddress, HttpServletRequest request, HttpServletResponse response) {
// 4.从数据库动态读取,判断是黑名单,设置网关响应为false
if("127.0.0.1".equals(ipAddress)){
resultError(ctx, "ip:" + ipAddress + ",Insufficient access rights");
// 直接停止了,不继续走后面的Handler
return;
}
log.info(">>>>>>ip:{},验证通过>>>>>>>", ipAddress);
// 执行下一个流程Handler
nextGatewayHandler.service(ctx,ipAddress,request,response);
} @Override
public GatewayHandler getNextHandler() {
return null;
} }
/**
* @Description: [流程2] 基于责任链设计模式封装: 参数验签拦截
* @Author: kevin
* @CreateTime: 2019-08-26 22:18
* @Version: V1.0
*/
@Slf4j
//@Component
public class ParamsValidateHandler extends BaseHandler implements GatewayHandler {
@Override
public void service(RequestContext ctx, String ipAddress, HttpServletRequest request, HttpServletResponse response) {
// 5.外网传递参数签名拦截
Map<String, String> verifyMap = SignUtil.toVerifyMap(request.getParameterMap(), false);
if(!SignUtil.verify(verifyMap)){
resultError(ctx, "ip:" + ipAddress + ",Sign fail");
return;
}
// 执行下一个流程Handler
nextGatewayHandler.service(ctx,ipAddress,request,response);
} @Override
public void setNextHandler(GatewayHandler gatewayHandler) { } @Override
public GatewayHandler getNextHandler() {
return null;
}
}
/**
* @Description: [流程3] 基于责任链设计模式封装: API权限控制
* @Author: kevin
* @CreateTime: 2019-08-26 22:19
* @Version: V1.0
*/
@Slf4j
//@Component
public class ApiAuthorizeHandler extends BaseHandler implements GatewayHandler {
@Override
public void service(RequestContext ctx, String ipAddress, HttpServletRequest request, HttpServletResponse response) {
String servletPath = request.getServletPath();
log.info(">>>>>servletPath:" + servletPath + ",servletPath.substring(0, 5):" + servletPath.substring(0, 5));
// 内部服务调用不需要accessToken验证,如果public开头,表示授权公司访问接口
if (!servletPath.substring(0, 7).equals("/public")) {
// 执行下一个流程Handler
nextGatewayHandler.service(ctx,ipAddress,request,response);
return;
}
String accessToken = request.getParameter("accessToken");
log.info(">>>>>accessToken验证:" + accessToken);
if (StringUtils.isEmpty(accessToken)) {
resultError(ctx, "AccessToken cannot be empty");
return;
}
// 调用接口验证accessToken是否失效
BaseResponse<JSONObject> appInfo = verificaCodeServiceFeign.getAppInfo(accessToken);
log.info(">>>>>>data:" + appInfo.toString());
if (!isSuccess(appInfo)) {
resultError(ctx, appInfo.getMsg());
return;
}
// 执行下一个流程Handler
nextGatewayHandler.service(ctx,ipAddress,request,response);
} @Override
public GatewayHandler getNextHandler() {
return null;
}
}

3、基于责任链设计模式封装: 使用工厂获取Handler

/**
* @Description: 基于责任链设计模式封装: 使用工厂获取Handler
* @Author: kevin
* @CreateTime: 2019-08-26 22:27
* @Version: V1.0
*/
public class FactoryHandler { /**
* 责任链启动方式:
*
* 1.将每一个Handler存放到集合中实现遍历
* 可以把handler放入数据库,设置开关,不用每次修改代码
*
* @return
*/
public static GatewayHandler getOneHandler() {
// 1.黑名单判断
GatewayHandler gatewayHandler1 = (GatewayHandler) SpringContextUtil.getBean("blackBlockHandler");
// 2.api验证签名
GatewayHandler gatewayHandler2 = (GatewayHandler) SpringContextUtil.getBean("paramsValidateHandler");
gatewayHandler1.setNextHandler(gatewayHandler2);
// 3.api接口验证token
GatewayHandler gatewayHandler3 = (GatewayHandler) SpringContextUtil.getBean("apiAuthorizeHandler");
gatewayHandler2.setNextHandler(gatewayHandler3);
return gatewayHandler1; }
}

4、基于责任链设计模式封装: 责任链调用方

/**
* @Description: 基于责任链设计模式封装: 责任链调用方
* @Author: kevin
* @CreateTime: 2019-08-26 22:35
* @Version: V1.0
*/
//@Component
public class ResponsibilityClient {
/**
* 责任链调用
*/
public void responsibility(RequestContext ctx, String ipAddress, HttpServletRequest request,
HttpServletResponse response) {
GatewayHandler oneHandler = FactoryHandler.getOneHandler();
oneHandler.service(ctx, ipAddress, request, response);
}
}

5、网关过滤器中调用

@Override
public Object run() throws ZuulException { RequestContext ctx = RequestContext.getCurrentContext();
// 1.获取请求对象
HttpServletRequest request = ctx.getRequest();
// 2.获取响应对象
HttpServletResponse response = ctx.getResponse(); // 3.获取客户端真实ip地址
String ipAddr = IpUtil.getIpAddr(request);
if (StringUtils.isEmpty(ipAddr)) {
resultError(ctx, "未能够获取到ip地址");
} // 4 设计模式二: 基于责任链模式封装
responsibilityClient.responsibility(ctx,ipAddr,request,response); return null; }

基于【 责任链模式】二 || 网关zuul过滤器封装的更多相关文章

  1. 基于【 建造者模式】一 || 网关zuul过滤器封装

    一.springcloud的zuul网关拦截 1.黑名单拦截 2.参数验签 3.Api接口权限验证 二.网关拦截实现方式 1.继承ZuulFilter方法,实现业务逻辑 @Component @Slf ...

  2. 设计模式学习笔记(十四)责任链模式实现以及在Filter中的应用

    责任链模式(Chain Of Responsibility Design Pattern),也叫做职责链,是将请求的发送和接收解耦,让多个接收对象都有机会处理这个请求.当有请求发生时,可将请求沿着这条 ...

  3. GOF23设计模式之责任链模式(chain of responsibility)

    一.责任链模式概述 将能够处理同一类请求的对象连成一条链,所提交的请求沿着链传递,链上的对象逐个判断是否有能力处理该请求. 如果能则处理,否则传递给链上的下一个对象去处理. 定义责任链 (1)通过链表 ...

  4. 网络编程Netty入门:责任链模式介绍

    目录 责任链模式 责任链模式的简单实现 Netty中的ChannelPipeline责任链 服务端接收客户端连接 pipeline初始化 入站事件和出站事件 Pipeline中的Handler Pip ...

  5. Java 设计模式系列(二二)责任链模式

    Java 设计模式系列(二二)责任链模式 责任链模式是一种对象的行为模式.在责任链模式里,很多对象由每一个对象对其下家的引用而连接起来形成一条链.请求在这个链上传递,直到链上的某一个对象决定处理此请求 ...

  6. 由浅入深讲解责任链模式,理解Tomcat的Filter过滤器

    本文将从简单的场景引入, 逐步优化, 最后给出具体的责任链设计模式实现. 场景引入 首先我们考虑这样一个场景: 论坛上用户要发帖子, 但是用户的想法是丰富多变的, 他们可能正常地发帖, 可能会在网页中 ...

  7. 二十四种设计模式:责任链模式(Chain of Responsibility Pattern)

    责任链模式(Chain of Responsibility Pattern) 介绍为解除请求的发送者和接收者之间耦合,而使多个对象都有机会处理这个请求.将这些对象连成一条链,并沿着这条链传递该请求,直 ...

  8. 设计模式之二十:责任链模式(Chain of Responsibility)

    感觉这个设计模式和组合模式一样是一种非常巧妙的设计模式,在须要使用它的地方假设不使用这样的设计模式代码会变的非常复杂,可是这样的设计模式的基本原理又是非常easy的. 责任链模式: 通过使多个对象都有 ...

  9. C#设计模式:责任链模式

    设计模式是面向对象编程的基础,是用于指导程序设计.在实际项目开发过程中,并不是一味将设计模式进行套用,也不是功能设计时大量引入设计模式.应该根据具体需求和要求应用适合的设计模式.设计模式是一个老话题了 ...

随机推荐

  1. VS Code 通过文件名查询文件并打开

    On Windows press Ctrl+p or Ctrl+e On Mac press Cmd+p on the Linux press also Ctrl+p works Older Mac ...

  2. shell编程系列21--文本处理三剑客之awk中数组的用法及模拟生产环境数据统计

    shell编程系列21--文本处理三剑客之awk中数组的用法及模拟生产环境数据统计 shell中的数组的用法: shell数组中的下标是从0开始的 array=("Allen" & ...

  3. shell编程系列8--文本处理三剑客之grep和egrep

    grep和egrep 第一种形式:grep [option] [pattern] [file1,file2...] 第二种形式:command | grep [option] [pattern] gr ...

  4. osg编译日志3

    1>------ 已启动生成: 项目: ZERO_CHECK, 配置: Debug x64 ------1> Checking Build System1> CMake does n ...

  5. MyBatis原理总结(代码实现流程)

    我们在实际开发中,越简单越好,所以都是采用不写Dao实现类的方式.不管是使用xml还是直接配置. 但是MyBatis是支持写Dao实现类的 注意sqlSession是这里面的一个灵魂,有很多执行api ...

  6. CentOS7下yum安装Redis

    (1).Redis概述 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value(键值型)数据库(非关系型数据库),并提供多种语言的API. Redi ...

  7. 查找searching

    查找searching 在有序数列中查找某一个数据时候的算法设计 查找表的分类 静态查找表:只进行查找操作 动态查找表:不断的插入不存在,删除已存在 查找表的操作 查找.插入.删除 查找也叫检索,是根 ...

  8. js 判断字符串是否为JSON格式

    function isJSON(str) { if (typeof str == 'string') { try { var obj=JSON.parse(str); if(typeof obj == ...

  9. mysql 查询的所有操作

    数据查询语言DQL 基本查询语法形式 select [all | distinct] 字段或表达式列表 [from子句] [where子句] [group by子句] [having子句] [orde ...

  10. 任务调度之Quartz.Net配置文件

    前面介绍的任务的创建执行是通过代码来实现的,当要添加一个任务的时候就非常的不灵活,做不到热插拔.而通过配置文件的方式实现配置化,可以做到在添加一个任务的话,我们可以新建一个类库来定义Job做到热插拔. ...