SpringCloudGateway自定义Filter
使用Gateway的时候,时长会有一些需求,要放在Gateway中去处理,如果一些登陆校验,权限校验之类的,从而降低一些应用服务器的压力。这个时候就需要在Gateway项目中自定义Filte去处理。
步骤
创建自定义filter的步骤
创建XxxGatewayFilterFactory,继承AbstractGatewayFilterFactory,如CheckLoginGatewayFilterFactory,必须以GatewayFilterFactory为结尾
重写apply方法
通过@Bean的方式将自定义的Filter添加到spring容器中,在类上加@Service的方式无法添加
在配置中引入自定义Filter,名称为XxxGatewayFilterFactory中的Xxx,如CheckLogin,
如果需要增加一些配置,用于Filter的逻辑判断,如官方的PrefixPathGatewayFilte中可以配置prefilx的值,那么可以在当前类创建一个静态内部类,然后声明在类上,如
public class RejectUrlGatewayFilterFactory extends AbstractBaseCheckGatewayFilterFactory<RejectUrlGatewayFilterFactory.Config>
- 写入到配置文件中,由于我们不引入Order,所以默认我们写的自定义Filter的Order都是0,引入多个filter时,执行顺序按配置的顺序执行
示例
普通的自定义filter
比如校验请求的header中是否包含必须的自定义的参数
创建CheckHeaderParamGatewayFilterFactory,然后创建一个Config,用来配置需要被校验的header,
然后继承AbstractGatewayFilterFactory,重写applay方法,apply方法中的Config参数就是我们自己定义的Config
public class CheckHeaderParamGatewayFilterFactory extends AbstractGatewayFilterFactory<CheckHeaderParamGatewayFilterFactory.Config> {@Overridepublic GatewayFilter apply(Config config) {return null;}@Datapublic static class Config {/*** 要校验的header的key,用逗号分隔*/private String header;}
}
编写处理逻辑
@Slf4j
public class CheckHeaderParamGatewayFilterFactory extends AbstractGatewayFilterFactory<CheckHeaderParamGatewayFilterFactory.Config> {private final ObjectMapper objectMapper = new ObjectMapper();@Overridepublic GatewayFilter apply(Config config) {return (exchange, chain) -> {String[] checkHeaderArr = getCheckHeaderArr(config);// 没有配置,进入下一个filterif (checkHeaderArr == null){log.info("check header config is null");return chain.filter(exchange);}log.info("requestUri:【{}】 校验 header", exchange.getRequest().getURI().toString());// 获取请求的所有headerHttpHeaders headers = exchange.getRequest().getHeaders();for (String headerName : checkHeaderArr) {if (StringUtils.isBlank(headerName)){continue;}// 如果要被校验的header不存在,直接编写响应信息给接口调用方if (!headers.containsKey(headerName)) {return writeParamErrorResponse(exchange, headerName + "不能为空");}}log.info("requestUri:【{}】 校验 header 通过", exchange.getRequest().getURI().toString());// 校验通过,进入下一个filterreturn chain.filter(exchange);};}/*** 处理失败时的返回*/private Mono<Void> writeParamErrorResponse(ServerWebExchange exchange, String message) {ApiResponse<Void> response = new ApiResponse<>();response.setResultCode("PA_PARAM_ERROR");response.setMessage(message);return writeErrorResponse(exchange, response);}/*** 处理失败时的返回*/private Mono<Void> writeErrorResponse(ServerWebExchange exchange, Object responseBody) {ServerHttpResponse response = exchange.getResponse();response.getHeaders().setContentType(MediaType.APPLICATION_JSON);response.setStatusCode(HttpStatus.OK);return response.writeWith(Mono.fromSupplier(() -> {DataBufferFactory bufferFactory = response.bufferFactory();try {log.info("校验失败:{}", responseBody);return bufferFactory.wrap(objectMapper.writeValueAsBytes(responseBody));} catch (JsonProcessingException e) {log.error("json转换异常", e);return bufferFactory.wrap(new byte[0]);}}));}/*** 从Config中获取配置*/private String[] getCheckHeaderArr(Config config) {String[] checkHeaderArr;String header = config.getHeader();if (StringUtils.isBlank(header)) {checkHeaderArr = null;} else {checkHeaderArr = header.split(",");}return checkHeaderArr;}@Datapublic static class Config {/*** 要校验的header的key,用逗号分隔*/private String header;}
}
将filter注册到Spring容器中
@Configuration
public class GatewayFilterConfig {@Beanpublic CheckHeaderParamGatewayFilterFactory checkHeaderParamGatewayFilterFactory(){return new CheckHeaderParamGatewayFilterFactory();}
}
在配置文件中配置的模式
yaml
filters:- CheckHeaderParam=token,visitorId
本人项目中采用在nacos中通过json的模式进行动态路由的配置,json中的对应格式为
"filters": [{"name": "CheckHeaderParam","args":{"header":"token,visitorId"}}
]
继承了Spring中某些特殊filter
比如某些场景下,我们需要对某个路由中的响应做数据类型转换,这个时候,可以直接继承Spring的ModifyResponseBodyGatewayFilterFactory
@Slf4j
public class ConvertBankResponseGatewayFilterFactory extends ModifyResponseBodyGatewayFilterFactory {public ConvertBankResponseGatewayFilterFactory(List<HttpMessageReader<?>> messageReaders, Set<MessageBodyDecoder> messageBodyDecoders, Set<MessageBodyEncoder> messageBodyEncoders) {super(messageReaders, messageBodyDecoders, messageBodyEncoders);}@Autowiredprivate BankCodeMappingConfig bankCodeMappingConfig;@Overridepublic GatewayFilter apply(Config config) {// 创建一个新的ConfigConfig conf = new Config();// 处理类型转换conf.setRewriteFunction(BankResponse.class, ApiResponse.class,(serverWebExchange, response) -> {Optional<BankResponse> resp = Optional.ofNullable(response);ApiResponse<Object> apiResponse = new ApiResponse<>();apiResponse.setBody(resp.map(BankResponse::getData).orElse(null));apiResponse.setResultCode(resp.map(BankResponse::getCode).map(e->bankCodeMappingConfig.getCodeMapping(e)).orElse(StringUtils.EMPTY));apiResponse.setMessage(resp.map(BankResponse::getMsg).orElse(StringUtils.EMPTY));log.info("BankResponse:【{}】, ApiResponse:【{}】",response,apiResponse);return Mono.just(apiResponse);});// 将新创建的config传入return super.apply(conf);}
}
添加到Spring容器
@Bean
public ConvertBankResponseGatewayFilterFactory convertBankResponseGatewayFilterFactory(ServerCodecConfigurer codecConfigurer, Set<MessageBodyDecoder> bodyDecoders,Set<MessageBodyEncoder> bodyEncoders) {return new ConvertBankResponseGatewayFilterFactory(codecConfigurer.getReaders(), bodyDecoders, bodyEncoders);
}
在配置文件中配置的模式
yaml
filters:- ConvertBankResponse
json
"filters": [{"name": "ConvertBankResponse"}
]
SpringCloudGateway自定义Filter相关推荐
- Spring Security 入门(四):自定义-Filter
前文导读 - Spring Security入门(一):登录与退出 - Spring Security入门(二):基于数据库验证 - Spring Security入门(三):密码加密 本文解决问题 ...
- 【SpringBoot】SpringBoot拦截器实战和 Servlet3.0自定义Filter、Listener
=================6.SpringBoot拦截器实战和 Servlet3.0自定义Filter.Listener ============ 1.深入SpringBoot2.x过滤器Fi ...
- java filter 注解_Spring常用注解及自定义Filter的实现
@Configuration通常用在配置类上,告诉spring这是一个配置类(配置类类似配置文件,区别在于用类的形式来表现xml: @Service用于标注业务层组件service层, @Contro ...
- Django(模板语言-自定义filter和simple_tag)
filter过滤器的主要形式:变量|函数,意思是将变量交给函数处理,而自定义filter就是自己定义函数,因为用到已有的很少. 1.在当前app中创建templatetags模块(包:带__init_ ...
- Spring-Security 自定义Filter完成验证码校验
Spring-Security的功能主要是由一堆Filter构成过滤器链来实现,每个Filter都会完成自己的一部分工作.我今天要做的是对UsernamePasswordAuthenticationF ...
- java自定义 filter,HBase自定义Filter
必需要提前说明下:不建议使用自定义的Filter.所有的Filter都是在服务端生效:就是说需要将自定义的Filter封装为jar,上传到HBase的类路径下,并重启HBase使之生效.对于生产环境的 ...
- SpringBoot自定义Filter
SpringBoot自定义Filter SpringBoot自动添加了OrderedCharacterEncodingFilter和HiddenHttpMethodFilter,当然我们可以自定 义F ...
- Python框架篇之Django(Template模版:标签tag、自定义filter、extend模板继承)
文章目录 一.标签的使用(tag) 二.自定义filter和simple_tag 三.extend模板继承 一.标签的使用(tag) 1.语法格式:{% tags %} 2.提供的几种标签 {% if ...
- Python学习(三十七)—— 模板语言之自定义filter和中间件
一.模板语言之自定义filter 自定义filter文件存放位置 模板中自定义函数- 在已注册的app中创建一个名字叫 templatetags 文件夹- 任意创建一个py文件- 创建名字交 regi ...
最新文章
- 类型参数的约束(C# 编程指南)
- 分布式技术比较(RPC,CORBA,WebService)
- 《他其实没那么喜欢你》经典台词
- Hadoop_计算框架MapReduce
- hadoop--Map Join
- 文件系统04 - 零基础入门学习Delphi37
- 【BCS2021】软件供应链完整演讲回看
- 用@Scheduled完成定时任务
- 《计算机组成原理》唐朔飞第三版知识点总结
- CellCtrl控件完美破解研究
- 折叠屏要来了,适配逼死 Android 开发?谷歌有办法!
- Dynamic Web TWAIN:网页扫描过程中如何自动检测和删除空白页?
- 两个9014三极管简易开关电路分析
- springboot 解决 woff2、ttf 跨域无法解析问题
- 信息系统开发方法-生命周期法
- BC20 MQTT与GPS功能测试
- BlumNet: Graph Component Detection for Object Skeleton Extraction阅读笔记
- JAVA SM2 数字证书生成
- flash控件使用手册
- Linux进程亲族关系图
热门文章
- 【第一篇】学习与奋斗,不努力就会与社会脱节
- uni.app小程序实现跳转获取数据
- 已解决nltk.download(‘punkt’) [nltk_data] Error loading punkt: [WinError 10060] [nltk_data]
- html制作在线视频音乐播放器,用html5制作音乐播放器,这3款就足够了!
- 广东教国笔怎样才能提高自制力!
- python爬虫天气
- Android 开发小仓库
- PR2019 (二)比较基本
- PyCharm使用教程:选择性忽略 PEP8 警告
- 4面字节跳动拿到2-2-Offer,入职就是30K16薪,全靠这份Android知识点PDF大全