Gateway 网关 之 自定义过滤器
接口 ServerWebExchange:
关于 过滤器 相关接口解说请看: https://www.cnblogs.com/fdzang/p/11812348.html
ServerWebExchange的注释: ServerWebExchange是一个HTTP请求-响应交互的契约。提供对HTTP请求和响应的访问,并公开额外的服务器端处理相关属性和特性,如请求属性。
其实,ServerWebExchange命名为服务网络交换器,存放着重要的请求-响应属性、请求实例和响应实例等等,有点像Context的角色。
public interface ServerWebExchange { // 日志前缀属性的KEY,值为org.springframework.web.server.ServerWebExchange.LOG_ID // 可以理解为 attributes.set("org.springframework.web.server.ServerWebExchange.LOG_ID","日志前缀的具体值"); // 作用是打印日志的时候会拼接这个KEY对饮的前缀值,默认值为"" String LOG_ID_ATTRIBUTE = ServerWebExchange.class.getName() + ".LOG_ID"; String getLogPrefix(); // 获取ServerHttpRequest对象 ServerHttpRequest getRequest(); // 获取ServerHttpResponse对象 ServerHttpResponse getResponse(); // 返回当前exchange的请求属性,返回结果是一个可变的Map Map<String, Object> getAttributes(); // 根据KEY获取请求属性 @Nullable default <T> T getAttribute(String name) { return (T) getAttributes().get(name); } // 根据KEY获取请求属性,做了非空判断 @SuppressWarnings("unchecked") default <T> T getRequiredAttribute(String name) { T value = getAttribute(name); Assert.notNull(value, () -> "Required attribute '" + name + "' is missing"); return value; } // 根据KEY获取请求属性,需要提供默认值 @SuppressWarnings("unchecked") default <T> T getAttributeOrDefault(String name, T defaultValue) { return (T) getAttributes().getOrDefault(name, defaultValue); } // 返回当前请求的网络会话 Mono<WebSession> getSession(); // 返回当前请求的认证用户,如果存在的话 <T extends Principal> Mono<T> getPrincipal(); // 返回请求的表单数据或者一个空的Map,只有Content-Type为application/x-www-form-urlencoded的时候这个方法才会返回一个非空的Map -- 这个一般是表单数据提交用到 Mono<MultiValueMap<String, String>> getFormData(); // 返回multipart请求的part数据或者一个空的Map,只有Content-Type为multipart/form-data的时候这个方法才会返回一个非空的Map -- 这个一般是文件上传用到 Mono<MultiValueMap<String, Part>> getMultipartData(); // 返回Spring的上下文 @Nullable ApplicationContext getApplicationContext(); // 这几个方法和lastModified属性相关 boolean isNotModified(); boolean checkNotModified(Instant lastModified); boolean checkNotModified(String etag); boolean checkNotModified(@Nullable String etag, Instant lastModified); // URL转换 String transformUrl(String url); // URL转换映射 void addUrlTransformer(Function<String, String> transformer); // 注意这个方法,方法名是:改变,这个是修改ServerWebExchange属性的方法,返回的是一个Builder实例,Builder是ServerWebExchange的内部类 default Builder mutate() { return new DefaultServerWebExchangeBuilder(this); } interface Builder { // 覆盖ServerHttpRequest Builder request(Consumer<ServerHttpRequest.Builder> requestBuilderConsumer); Builder request(ServerHttpRequest request); // 覆盖ServerHttpResponse Builder response(ServerHttpResponse response); // 覆盖当前请求的认证用户 Builder principal(Mono<Principal> principalMono); // 构建新的ServerWebExchange实例 ServerWebExchange build(); } }
全局过滤器:
全局过滤器不需要工厂,也不需要配置,直接对所有的路由都生效。
可以使用GlobalFilter实现统一的权限验证、日志记录 等 希望对所有代理的项目都生效的内容都可以配置在全局过滤器中。
且在项目中可以配置多个 GlobalFilter 的实现类。都可以自动执行;多个过滤器,按照 Ordered 的顺序规则 顺序执行
全局过滤器有两个主要 接口 :GlobalFilter, Ordered (Ordered 定义全局过滤器的执行顺序的,数字越大,越后执行)
主要结构:
@Component public class MyLogGlobalFilter implements GlobalFilter { private Logger logger = LoggerFactory.getLogger(MyLogGlobalFilter.class); @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 前置过滤器逻辑 logger.info("执行全局过滤器-logger"); long start = System.currentTimeMillis(); // 执行后续逻辑 Mono<Void> result = chain.filter(exchange); // 后置过滤器逻辑 long end = System.currentTimeMillis(); logger.info("执行结束,本次执行时长:{} 毫秒", end - start); return result; } }
如:以下简单示例:
@Component public class GlobalLogFilter implements GlobalFilter, Ordered { /** * 实现自定义过滤器的逻辑 * * @param exchange 请求的上下文对象 * @param chain 通道 * @return */ @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { System.out.println("进入全局过滤器"); ServerHttpRequest request = exchange.getRequest(); String username = request.getQueryParams().getFirst("username"); if (null == username) { System.out.println("请求参数中没有 username,不允许访问"); exchange.getResponse().setStatusCode(HttpStatus.NOT_ACCEPTABLE); return exchange.getResponse().setComplete(); } // 传递给下一个过滤链 return chain.filter(exchange); } /** * 加载过滤器的顺序,数字越小,优先级越高 * 最小数:int HIGHEST_PRECEDENCE = -2147483648; * 最大数:int LOWEST_PRECEDENCE = 2147483647; * * @return */ @Override public int getOrder() { return -1000; } }
自定义 FilterFactory
可以定义针对于 Router 的 Filter。
注意:
1、类名必须叫做XxxGatewayFilterFactory.注入到Spring容器后使用时的名称就叫做Xxx。
2、类必须继承 AbstractGatewayFilterFactory,让父类帮实现配置参数的处理 ( 不限麻烦的可以直接实现 GatewayFilterFactory )
3、所有需要传递进来的参数都配置到当前类的内部类Config中
@Component // 自定义路由过滤器,查看请求路径地址 public class RequestPathGatewayFilterFactory extends AbstractGatewayFilterFactory<RequestPathGatewayFilterFactory.MyConfig> { public RequestPathGatewayFilterFactory() { super(MyConfig.class); } /** * 这个简化配置的方案,当前方法返回简化配置参数明明列表 * 如:RequestPath=nameValue,pathValue * * @return */ @Override public List<String> shortcutFieldOrder() { return Arrays.asList("name", "path"); } /** * 执行过滤的逻辑 * * @param config * @return */ @Override public GatewayFilter apply(MyConfig config) { // 匿名内部类方式实现 return (ServerWebExchange exchange, GatewayFilterChain chain) -> { // 前置逻辑器逻辑 String path = exchange.getRequest().getPath().toString(); System.out.println("路由过滤器,本次请求地址为:" + path + ",配置的参数是:" + config.getName() + ",配置的 path=" + config.getPath()); // 同样可以对后置处理的响应进行处理 ServerHttpResponse response = exchange.getResponse(); // 执行下一个逻辑 return chain.filter(exchange); //后置过滤器逻辑 }; } @Getter // 当前过滤器是要使用的配置内容 public static class MyConfig { private String name; private String path; public MyConfig setName(String name) { this.name = name; return this; } public MyConfig setPath(String path) { this.path = path; return this; } } }
使用时配置:( 重写了 shortcutFieldOrder() 方法,可以进行简化配置使用 )
filters: RequestPath=testnameValue,testPathValue
>>>>>>>>>>>>> 下一篇 : https://www.cnblogs.com/chxlay/p/15150599.html <<<<<<<<<<<<<<<<<<<<<<
本文来自博客园,作者:Vermeer,转载请注明原文链接:https://www.cnblogs.com/chxlay/p/15150562.html