1,课程回顾
2,本章重点

zuul(zuul1,zuul2)
gateway
3,具体内容
3.1 zuul
3.1.1 zuul简介
https://www.springcloud.cc/
https://github.com/Netflix/zuul/wiki
https://www.springcloud.cc/spring-cloud-greenwich.html#_router_and_filter_zuul
Zuul 是从设备和网站到 Netflix 流媒体应用程序后端的所有请求的前门。作为边缘服务应用程序,Zuul 旨在支持动态路由、监控、弹性和安全性。路由是微服务架构不可或缺的一部分。例如,/可能被映射到您的web应用程序,/api/users被映射到用户服务,/api/shop被映射到商店服务。 Zuul是Netflix的基于JVM的路由器和服务器端负载平衡器。
3.1.1 zuul 的主要作用(为什么使用)
Netflix API 流量的数量和多样性有时会导致生产问题在没有警告的情况下迅速出现。我们需要一个允许我们快速改变行为以应对这些情况的系统。
Zuul 使用一系列不同类型的过滤器,使我们能够快速灵活地将功能应用到我们的边缘服务。这些过滤器帮助我们执行以下功能:
身份验证和安全性 - 确定每个资源的身份验证要求并拒绝不满足要求的请求。
洞察力和监控 - 在边缘跟踪有意义的数据和统计数据,以便为我们提供准确的生产视图。
动态路由 - 根据需要将请求动态路由到不同的后端集群。
压力测试 - 逐渐增加集群的流量以衡量性能。
减载 - 为每种类型的请求分配容量并丢弃超出限制的请求。
静态响应处理 - 直接在边缘构建一些响应,而不是将它们转发到内部集群
3.1.2 实现过程(参考项目 zuul)
1)引入jar:

<!--zuul jar-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<!--nacos客户端jar-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

2) 启动类:
@SpringBootApplication
@EnableZuulProxy //开启zuul的代理功能
3)配置application.yml

server:#端口号配置port: 14151
spring:cloud:nacos:discovery:#注册地址server-addr: localhost:8848application:#注册服务名称name: zuulService
zuul:host:#总并发连接配置  默认值为200max-total-connections: 300#每个路由并发连接配置  默认值为20max-per-route-connections: 30#连接超时时长  默认为2000毫秒connect-timeout-millis:  5000#路由配置routes:#自定义路由名称order:#服务的唯一识别  一定要和想访问的服务注册到注册中心的名称一致serviceId: orderService#请求该服务的路径配置  **不确定,可以根据地址栏请求,动态路由path: /os/**goods:#服务的唯一识别  一定要和想访问的服务注册到注册中心的名称一致serviceId: goodsService#请求该服务的路径配置  **不确定,可以根据地址栏请求,动态路由path: /gs/**sns:#服务的唯一识别  一定要和想访问的服务注册到注册中心的名称一致serviceId: snsService#请求该服务的路径配置  **不确定,可以根据地址栏请求,动态路由

4)路由测试:
http://localhost:14151/ss/comment/selectOne/1?a=1&b=22&c=333nnd33
http://localhost:14151/gs/product/selectAll?current=1&size=2
5)过滤器实现:
jar(增加):

<!--springboot web包  过滤器需要-->
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>

filter方法详解:
/**

  • 过滤类型 定义当前过滤器在什么起用
  • @return
    */
@Override
public String filterType() {//pre  在执行业务之前执行//route  在执行业务方法时执行//error  在执行业务时出现异常执行//post  在正常执行业务后或者出现异常后 执行return "pre";
}

/**

  • 多个过滤器同时执行时,通过该方法确定先后顺序 返回值越小,执行优先级越高
  • @return
    /
    @Override
    public int filterOrder() {
    return 3;
    }
    /
    *
  • 是否让该过滤器生效 返回false不生效
  • @return
    /
    @Override
    public boolean shouldFilter() {
    return true;
    }
    /
    *
  • 开发过滤功能
  • @return
  • @throws ZuulException
    */
    @Override
    public Object run() throws ZuulException {
    }
    上下文对象:
com.netflix.zuul.context.RequestContext
编写IP过滤过滤器:
package com.aaa.zuul.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.apache.http.HttpStatus;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*** @ fileName:IllegalIPFilter* @ description:* @ author:zhz* @ createTime:2022/2/21 20:37* @ version:1.0.0*/
@Component
public class IllegalIPFilter extends ZuulFilter {@Value("${illegal_ip}")private String illegalIp;@Overridepublic String filterType() {return "pre";}@Overridepublic int filterOrder() {return 0;}@Overridepublic boolean shouldFilter() {return true;}@Overridepublic Object run() throws ZuulException {//具体过滤器业务代码System.out.println("进入了IP过滤器。。。。。");//获取zuul中提供的请求上下文对象RequestContext requestContext = RequestContext.getCurrentContext();//获取requestHttpServletRequest request =requestContext.getRequest();//获取response对象HttpServletResponse response = requestContext.getResponse();//获取请求用户的IP地址String remoteAddr = request.getRemoteAddr();System.out.println("请求IP为:"+remoteAddr);System.out.println(illegalIp+"............");//判断IP地址是否合法   192.168.1.120//illegalIp=192.168.1.120,192.168.1.110,192.168.1.134,192.168.1.143if(illegalIp.contains(remoteAddr)){//添加响应方法response.setCharacterEncoding("gbk");try {//阻止程序继续运行requestContext.setSendZuulResponse(false);//response.sendError(HttpStatus.SC_FORBIDDEN,"禁止访问!");response.getWriter().println("IP非法,禁止访问!!!");} catch (IOException e) {e.printStackTrace();}}return null;}
}编写脏字过滤器:
package com.aaa.zs.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
/*** @ fileName:IllegalCharFilter* @ description:* @ author:zhz* @ createTime:2022/2/22 9:43* @ version:1.0.0*/
@Component
public class IllegalCharFilter extends ZuulFilter {@Value("${illegal_char}")private String illegalChar;@Overridepublic String filterType() {return "pre";}@Overridepublic int filterOrder() {return 4;}@Overridepublic boolean shouldFilter() {return true;}@Overridepublic Object run() throws ZuulException {System.out.println("非法字符过滤器。。。。。。。。。。。。");//实例化zuul封装请求上下文对象RequestContext currentContext = RequestContext.getCurrentContext();//通过上下问对象获取request,responseHttpServletRequest request = currentContext.getRequest();HttpServletResponse response = currentContext.getResponse();//获取请求的所有参数 //?a=1&b=2&c=3&aa=11   parameterNames [a,b,c,aa]Enumeration<String> parameterNames = request.getParameterNames();//根据逗号分割 非法字符串 [tmd,nnd,nm,yyds]String[] illegalCharAarray = illegalChar.split(",");//循环遍历所有参数名称while(parameterNames.hasMoreElements()){//第1次获取a  第2次获取b  ...String parameterName = parameterNames.nextElement();//根据名称获取参数值 第1次获取1  第2次获取2  ...String parameterValue = request.getParameter(parameterName);for (String illegalChar : illegalCharAarray) {if(parameterValue.contains(illegalChar)){//直接阻止程序运行currentContext.setSendZuulResponse(false);//回显错误response.setCharacterEncoding("GBK");try {response.getWriter().println("请求中含有非法参数,禁止访问");} catch (IOException e) {e.printStackTrace();}}}}return null;}
}

编写单点登录过滤器(单点登录用到)
跨域过滤(参考3.4 方法2)

package com.aaa.zs.filter;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/*** @fileName:CrossDomainFilter* @description:后台跨域过滤器* @author:zz* @createTime:2020/11/6 16:20* @version:1.0.0*/
@Component
public class CrossDomainFilter extends ZuulFilter {@Overridepublic String filterType() {return "pre";}@Overridepublic int filterOrder() {return 0;}@Overridepublic boolean shouldFilter() {return true;}@Overridepublic Object run() throws ZuulException {// 获取request对象RequestContext ctx = RequestContext.getCurrentContext();HttpServletRequest request = ctx.getRequest();HttpServletResponse response = ctx.getResponse();// 这些是对请求头的匹配,网上有很多解释response.setHeader("Access-Control-Allow-Origin",request.getHeader("origin"));response.setHeader("Access-Control-Allow-Credentials","true");response.setHeader("Access-Control-Allow-Methods","GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH");response.setHeader("Access-Control-Allow-Headers","authorization, content-type");response.setHeader("Access-Control-Expose-Headers","X-forwared-port, X-forwarded-host");response.setHeader("Vary","Origin,Access-Control-Request-Method,Access-Control-Request-Headers");// 跨域请求一共会进行两次请求 先发送options 是否可以请求// 调试可发现一共拦截两次 第一次请求为options,第二次为正常的请求 eg:get请求//  equalsIgnoreCase 忽略大小写if ("OPTIONS".equalsIgnoreCase(request.getMethod())){ctx.setSendZuulResponse(false); //验证请求不进行路由ctx.setResponseStatusCode(HttpStatus.OK.value());//返回验证成功的状态码ctx.set("isSuccess", true);return null;}// 第二次请求(非验证,eg:get请求不会进到上面的if) 会走到这里往下进行// 不需要token认证ctx.setSendZuulResponse(true); //对请求进行路由ctx.setResponseStatusCode(HttpStatus.OK.value());ctx.set("isSuccess", true);return null;}public static void main(String[] args) {System.out.println("a".equals("A"));System.out.println("a".equalsIgnoreCase("A"));}
}

测试过滤器的优先级,测试过滤器的启用和禁用等功能

3.2 gateway
https://spring.io/projects/spring-cloud-gateway#overview
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/
3.3.1 概念
该项目提供了一个用于在Spring WebFlux之上构建API网关的库。Spring Cloud Gateway旨在提供一种简单而有效的方法来路由到API,并为它们提供跨领域的关注点,例如:安全性,监视/指标和弹性。
主要功能: 路由功能route 断言功能predicate 过滤功能filter

webFlux官网文档:
https://docs.spring.io/spring-framework/docs/current/reference/html/web-reactive.html
3.3.2 特点
建立在Spring Framework 5,Project Reactor和Spring Boot 2.0之上
能够匹配任何请求属性上的路由。
谓词和过滤器特定于路由。
断路器集成。
Spring Cloud DiscoveryClient集成
易于编写的谓词和过滤器
请求速率限制(https://www.cnblogs.com/forezp/p/10140316.html)
路径改写
3.3.3 zuul和gateway对比(面试题)
相同点:
1、底层都是servlet
2、两者均是web网关,处理的是http请求
不同点:
1,getway的性能会远高于zuul1
getway和zuul 在zuul没有进行参数调优的时候,getway的性能会远高于zuul。在空负载的时候,SpringCloud Gateway比zuul 1 性能高50%左右,在模拟处理50ms业务后,,SpringCloud Gateway比zuul 1 性能高9倍左右。

zuul优化参数参考如下:

在实际生产使用中,zuul 1虽然使用的是同步io,但是可以通过参数优化提高性能理论上可以达到极限性能,而springcloud gateway使用的是异步io,不需优化既可以达到接近极限的性能。
Zuul 1.x,是一个基于阻塞io的API Gateway。Zuul已经发布了Zuul 2.x,基于Netty,也是非阻塞的,支持长连接,但Spring Cloud暂时还没有整合计划。
SpringCloud GetWay 是基于webFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty(异步非阻塞)。
2、是否支持异步
zuul1 仅支持同步
gateway支持异步。理论上gateway则更适合于提高系统吞吐量(但不一定能有更好的性能),最终性能还需要通过严密的压测来决定

3.3.4 工作原理

  客户端向Spring Cloud Gateway发出请求。如果网关处理程序映射确定请求与路由匹配,则将其发送到网关Web处理程序。该处理程序通过特定于请求的过滤器链运行请求。筛选器由虚线分隔的原因是,筛选器可以在发送代理请求之前和之后运行逻辑。所有“前置”过滤器逻辑均被执行。然后发出代理请求。发出代理请求后,将运行“后”过滤器逻辑。

3.3.5 具体使用
1)创建项目,引入jar包

<!--gateway jar包-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos 服务发现 客户端包-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--fastjson 包 -->
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId>
</dependency>

2) 创建配置
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-host-route-predicate-factory

server:port: 14152  #当前服务端口号
spring:application:name: gatewayService  #当前服务名称cloud:gateway:routes: #表示多个路由- id: order_route  # 每个网关的唯一标识,不可以重复name: order-service #名称,可以省略配置#uri: http://localhost:14121 #匹配后提供服务的路由地址uri: lb://orderService  #匹配后提供服务的路由地址,必须和注册中心注册名称一致 lb 支持负载均衡  注册服务是多个predicates: # 断言,满足条件,就执行- Path=/order/**- id: goods_route  # 每个网关的唯一标识,不可以重复uri: lb://goodsService  #配置被访问服务的名称,必须和注册中心注册名称一致predicates: # 断言,满足条件,就执行- Path=/product/**,/productType/**  #多个路径可以用,隔开- Method=POST,GET,PUT,DELETE  #请求方式是 POST,GET,PUT或者DELETE- Query=id,\d+  #要有参数id并且要求id为整数- Before=2023-02-22T11:25:40.666+08:00[Asia/Shanghai] #匹配这个时间之前的请求  UTC时间,也就是国际统一时间  +8:00 东八区- After=2021-02-21T12:15:30.666+08:00[Asia/Shanghai]  #匹配这个时间之后的请求- Between=2021-02-21T12:15:30.666+08:00[Asia/Shanghai],2023-02-21T12:15:30.666+08:00[Asia/Shanghai]- id: sns_route  # 每个网关的唯一标识,不可以重复name: sns-service #名称,可以省略配置#uri: http://localhost:14121 #匹配后提供服务的路由地址uri: lb://snsService  #匹配后提供服务的路由地址,必须和注册中心注册名称一致predicates: # 断言,满足条件,就执行- Path=/comment/**nacos:discovery:server-addr: localhost:8848/  #注册中心地址  gateway必须注册,才能发现其他服务
#自定义非法IP
illegal_ip: 192.168.41.174,192.168.1.110,192.168.1.134,192.168.1.143

3) 创建启动类

package com.aaa.gws;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/*** @ fileName:GatewayApp* @ description:* @ author:zhz* @ createTime:2022/2/22 11:14* @ version:1.0.0*/
@SpringBootApplication
@EnableDiscoveryClient
public class GatewayApp {public static void main(String[] args) {SpringApplication.run(GatewayApp.class,args);}
}

4) 启动项目,路由测试
先启动order服务,再启动gateway
http://localhost:14152/productType/selectOne/1?id=1
http://localhost:18888/order/selectOne?id=1
5)过滤器配置:
添加配置(application.yml):
#配置非法IP
illegal_ip: 192.168.1.120,192.168.1.110,192.168.1.134,192.168.1.143

#配置非法字符 BAT=baidu alibaba tencent
illegal_char: sb,nnd,tmd
#白名单配置
white_list: /order/selectOne,userLogin,/order/selectAll,memberLogin

非法字符滤器:
使用gateway过滤功能,过滤所有请求,获取所有请求中所有参数,如果请求参数中含有系统配置非法字符,直接不让提示错误。

package com.aaa.gs.filter;
import com.aaa.common.util.ResultStatus;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/*** @ fileName:IllegalIPFilter* @ description: 非法字符过滤器* @ author:zhz* @ createTime:2022/6/27 15:58* @ version:1.0.0*/
@Component
public class IllegalCharacterFilter implements GlobalFilter, Ordered {//基本属性依赖注入配置的值@Value("${illegal_char}")private String illegalChar;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {System.out.println("经过了非法字符过滤器。。。。。。。。。。。。。。。。。。");//获取request对象ServerHttpRequest request = exchange.getRequest();//获取response对象ServerHttpResponse response = exchange.getResponse();//获取所有请求参数的值,判断是否含有非法字符//http://192.168.28.173:14966/order/queryById?id=3&a=1&b=2&c=3&c=4tmd4//获取请求的所有参数及值  id=3&a=1&b=2&c=3&c=4tmd4  checkbox =  ["体育","读书"]MultiValueMap<String, String> queryParamsMap = request.getQueryParams();// MultiValueMap是Map的子类  遍历queryParamsMap [{key=id value=[3]},{key=a value=[1]}....]Set<Map.Entry<String, List<String>>> queryParamsMapEntries = queryParamsMap.entrySet();//获取非法字符并分割为数组 [tmd,nnd,fuck,falungong,guomindang]String[] illegalCharArray = illegalChar.split(",");//定义标识符,判断是否含有非法字符boolean isContainsIllegalChar = false;//循环遍历for (Map.Entry<String, List<String>> queryParamsMapEntry : queryParamsMapEntries) {String key = queryParamsMapEntry.getKey();//第一次 id  第二次  a ....System.out.println("key:"+key);//第一次 3  第二次  1 .... 第四次 4tmd4//  "tmd,nnd,fuck,falungong,guomindang".contains(4tmd4)  判断不对String value = queryParamsMapEntry.getValue().get(0);System.out.println("value:"+value);//循环遍历非法数组for (String illegalChar : illegalCharArray) {//第1次 tmd 第2次 nnd .......//判断是否含有if(value.contains(illegalChar)){//定义返回map对象Map map = new HashMap();map.put("code", ResultStatus.ILLEGAL_CHAR_ERROR.getReturnCode());map.put("msg", ResultStatus.ILLEGAL_CHAR_ERROR.getReturnMsg());byte[] bytesMap = null;try {//把map转换为字节数组bytesMap = JSON.toJSONString(map).getBytes("GBK");} catch (UnsupportedEncodingException e) {e.printStackTrace();}//spring 提供数据缓冲类  使用response.bufferFactory()中提供的wrap方法,把字节数组转换为DataBufferDataBuffer dataBuffer = response.bufferFactory().wrap(bytesMap);//writeWith 向响应对象中写入影响数据  需要的是Publisher接口的实现类   Mono就是该接口的实现类return response.writeWith(Mono.just(dataBuffer));/*isContainsIllegalChar = true;break;*/}}}//判断标识符/* if(isContainsIllegalChar){//定义返回map对象Map map = new HashMap();map.put("code", ResultStatus.ILLEGAL_CHAR_ERROR.getReturnCode());map.put("msg", ResultStatus.ILLEGAL_CHAR_ERROR.getReturnMsg());byte[] bytesMap = null;try {//把map转换为字节数组bytesMap = JSON.toJSONString(map).getBytes("GBK");} catch (UnsupportedEncodingException e) {e.printStackTrace();}//spring 提供数据缓冲类  使用response.bufferFactory()中提供的wrap方法,把字节数组转换为DataBufferDataBuffer dataBuffer = response.bufferFactory().wrap(bytesMap);//writeWith 向响应对象中写入影响数据  需要的是Publisher接口的实现类   Mono就是该接口的实现类return response.writeWith(Mono.just(dataBuffer));}*///如果不是,让程序继续运行return chain.filter(exchange);}@Overridepublic int getOrder() {return 5;}
}

非法IP过滤:
拦截所有客户请求,获取请求IP地址,判断地址是否在非法IP列表中,如果在,直接拦截,提示错误,不在放行。


```java
package com.aaa.gs.filter;
import com.aaa.common.util.ResultStatus;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
/*** @ fileName:IllegalIPFilter* @ description: 非法IP过滤器* @ author:zhz* @ createTime:2022/6/27 15:58* @ version:1.0.0*/
@Component
public class IllegalIPFilter implements GlobalFilter, Ordered {//基本属性依赖注入配置的值@Value("${illegal_ip}")private String illegalIp;@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {System.out.println("经过了非法IP过滤器。。。。。。。。。。。。。。。。。。");//获取request对象ServerHttpRequest request = exchange.getRequest();//获取response对象ServerHttpResponse response = exchange.getResponse();//IP过滤功能 如果是非法IP,直接拦截,提示错误//获取客户请求的IP地址InetSocketAddress remoteAddress = request.getRemoteAddress();//String hostName = remoteAddress.getHostName();InetAddress address = remoteAddress.getAddress();//System.out.println("主机名称----------------:"+hostName);String hostAddress = address.getHostAddress();System.out.println("IP地址----------------:"+hostAddress);//判断获取到IP是否是192.168.28.70,192.168.28.133//if(hostAddress.equals("192.168.28.173")||hostAddress.equals("192.168.28.70")||hostAddress.equals("192.168.28.133")||hostAddress.equals("192.168.28.47")){// illegalIp=192.168.28.173,192.168.28.70,192.168.28.133,192.168.28.47,192.168.28.238// "192.168.28.173,192.168.28.70,192.168.28.133,192.168.28.47,192.168.28.238".contains("192.168.28.173") 为trueif(illegalIp.contains(hostAddress)){//定义返回map对象Map map = new HashMap();map.put("code", ResultStatus.ILLEGAL_IP_ERROR.getReturnCode());map.put("msg", ResultStatus.ILLEGAL_IP_ERROR.getReturnMsg());byte[] bytesMap = null;try {//把map转换为字节数组bytesMap = JSON.toJSONString(map).getBytes("GBK");} catch (UnsupportedEncodingException e) {e.printStackTrace();}//spring 提供数据缓冲类  使用response.bufferFactory()中提供的wrap方法,把字节数组转换为DataBufferDataBuffer dataBuffer = response.bufferFactory().wrap(bytesMap);//writeWith 向响应对象中写入影响数据  需要的是Publisher接口的实现类   Mono就是该接口的实现类return response.writeWith(Mono.just(dataBuffer));}//如果不是,让程序继续运行return chain.filter(exchange);}/*** 设置当前过滤器的优先级   返回数字越小,优先级越高   存在多个filter时使用* @return*/@Overridepublic int getOrder() {return 0;}
}

单点登录过滤器:```java
package com.aaa.gws.filter;
import com.aaa.gws.service.RemoteUserLogin;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.server.RequestPath;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/*** @ fileName:IllegalIpFilter* @ description:* @ author:zhz* @ createTime:2022/2/22 11:32* @ version:1.0.0*/
@Component
public class SSOLoginFilter implements GlobalFilter, Ordered {@Resourceprivate RemoteUserLogin remoteUserLogin;@Value("${white_list}")private  String whileList;/* @Value("${illegal_ip}")private String  illegalIp;*/@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {System.out.println("单点登录过滤。。。。。。。。。。");//gateway封装的request请求对象ServerHttpRequest request = exchange.getRequest();//gateway封装的response响应对象ServerHttpResponse response = exchange.getResponse();RequestPath path = request.getPath();///order/selectOne    /  jq/chaxunsuoyouSystem.out.println(path+"..............................");String[] whiteListArray = whileList.split(",");// System.out.println(whiteListArray+".......................");for (String permsPath : whiteListArray) {//  System.out.println(permsPath+"................ssss.............."+path.toString());if(path.toString().contains(permsPath)){// System.out.println(permsPath+"................ssss..............");//放行return  chain.filter(exchange);}}//获取请求所有参数集合 ?a=1&b=2&accessToken=admin1795936b-2ddc-4b24-b286-10ed018c61d88MultiValueMap<String, String> queryParams = request.getQueryParams();//定义accessTokenValue// boolean isHasToken =false;String accessTokenValue = "";if (queryParams != null) {Set<Map.Entry<String, List<String>>> entries = queryParams.entrySet();for (Map.Entry<String, List<String>> entry : entries) {System.out.println("参数的key:" + entry.getKey() + ",value:" + entry.getValue());if (entry.getKey().equals("accessToken")) {// isHasToken =true;accessTokenValue = entry.getValue().get(0);}}}//获取IP地址InetSocketAddress remoteAddress = request.getRemoteAddress();InetAddress address = remoteAddress.getAddress();String hostAddress = address.getHostAddress(); //获取客户端Ip//System.out.println("请求的IP为:" + hostAddress);//System.out.println("accessTokenValue========="+accessTokenValue);//如果没有带token获取校验错误,都需要返回错误信息if (accessTokenValue.equals("") || !remoteUserLogin.checkToken(accessTokenValue)) {// 不合法则返回错误信息Map<String, Object> map = new HashMap<>();map.put("errorCode", 5003);map.put("errorMessage", "认证错误");try {byte[] datas = JSON.toJSONString(map).getBytes("utf-8");DataBuffer buffer = response.bufferFactory().wrap(datas);//添加响应头response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");//写入自定义错误信息,并返回return response.writeWith(Mono.just(buffer));} catch (UnsupportedEncodingException e) {e.printStackTrace();}}//程序继续运行return chain.filter(exchange);}/*** 排序方法  返回值越小  优先级越高* @return*/@Overridepublic int getOrder() {return 0;}
}

3.3.6 gateway跨域配置

spring:cloud:gateway:globalcors: # 全局的跨域处理add-to-simple-url-handler-mapping: true  # 解决options请求被拦截问题corsConfigurations:'[/**]':allowedOrigins: # 允许哪些网站的跨域请求- "*"  #所有网站#- "http://localhost:8090" #指定网站#- "http://www.leyou.com"allowedMethods: # 允许的跨域ajax的请求方式- "*"#- "GET"#- "POST"#- "DELETE"#- "PUT"#- "OPTIONS"allowedHeaders: "*" # 允许在请求中携带的头信息allowCredentials: true # 是否允许携带cookiemaxAge: 360000 # 这次跨域检测的有效期

4,知识点总结
5,本章面试题

springcloud5-服务网关zuul及gateway相关推荐

  1. 微服务网关Zuul和Gateway的区别

    spring-cloud-Gateway是spring-cloud的一个子项目.而zuul则是netflix公司的项目,只是spring将zuul集成在spring-cloud中使用而已. 因为zuu ...

  2. spring cloud gateway 网关_微服务网关Spring Cloud Gateway全搞定

    一.微服务网关Spring Cloud Gateway 1.1 导引 文中内容包含:微服务网关限流10万QPS.跨域.过滤器.令牌桶算法. 在构建微服务系统中,必不可少的技术就是网关了,从早期的Zuu ...

  3. ws配置 zuul_微服务网关 Spring Cloud Gateway

    1.  为什么是Spring Cloud Gateway 一句话,Spring Cloud已经放弃Netflix Zuul了.现在Spring Cloud中引用的还是Zuul 1.x版本,而这个版本是 ...

  4. 服务容错保护Hystrix服务网关Zuul

    1.服务容错保护Hystrix 1.1.背景 在微服务架构中consumer调用provider的时候,provider在响应的时候,有可能会慢,如果provider 10s响应,那么consumer ...

  5. SpringCloud 服务网关 Zuul 自定义路由和排除路由配置

    前言 首先需要说明的是该文是 [带你入门SpringCloud 之 服务网关 Zuul ]的拓展篇,如果还未阅读 [带你入门SpringCloud 之 服务网关 Zuul ]请先阅读完毕后在阅读该文. ...

  6. [菜鸟SpringCloud实战入门]第九章:服务网关Zuul体验

    前言 欢迎来到菜鸟SpringCloud实战入门系列(SpringCloudForNoob),该系列通过层层递进的实战视角,来一步步学习和理解SpringCloud. 本系列适合有一定Java以及Sp ...

  7. zuul网关_SpringCould之服务网关(zuul)介绍与配置

    ??记得点击上方蓝字"程序员小强"关注哦 一.前言介绍 1.什么是服务(API)网关? 服务网关也就是API网关,可以作为服务的统一入口. 可提供身份校验.动态路由.负载均衡.安全 ...

  8. 服务网关 Zuul基本使用

    API 网关是一个更为智能的应用服务器,它的定义类似面向对象设计模式中的Facade模式,它的存在就像是整个微服务架构系统的门面一样,所有的外部客户端访问都需要经过它来进行调度和过滤.它除了要实现请求 ...

  9. 微服务网关Zuul迁移到Spring Cloud Gateway

    https://juejin.im/post/5ba8daa56fb9a05cfe486ebf 背景 在之前的文章中,我们介绍过微服务网关Spring Cloud Netflix Zuul,前段时间有 ...

  10. (十)java springboot b2b2c shop 多用户商城系统源码:服务网关zuul初级篇

    为什么需要API Gateway 1.简化客户端调用复杂度 在微服务架构模式下后端服务的实例数一般是动态的,对于客户端而言很难发现动态改变的服务实例的访问地址信息.因此在基于微服务的项目中为了简化前端 ...

最新文章

  1. Java程序员必看!2021最新爱奇艺Java社招面试题目
  2. Windows Phone开发(35):使用Express Blend绘图 转:http://blog.csdn.net/tcjiaan/article/details/7493010...
  3. JSON-B非对称属性绑定
  4. 【牛客 - 185B】路径数量(离散数学,长度为k的路径数量,图)
  5. Remove Duplicates from Sorted Array II
  6. PLSQL Developer简单使用及常用快捷键
  7. markdown 提示文本_【文本编辑01】MarkdownPad安装及基本配置
  8. 贪吃蛇小游戏(C语言)
  9. 计算机英语教程第6版,计算机英语教程(第6版)
  10. VSCode必备安装插件
  11. java如何计算时间天数差,Java计算两个时间的天数差与月数差 LocalDateTime,如何计算日期差的天数...
  12. matlab画三维图如何更改颜色,MATLAB画三维图像
  13. 微擎we7微赞官方通用功能模块插件带XML文件分享
  14. 青岛小学 初中有计算机编程比赛,青岛市电脑制作活动 程序设计竞赛 一等奖...
  15. 7.node.js的Buffer(缓冲区)的合并(concat)、比较(compare)、拷贝(copy)和裁剪(slice)以及如何转化为JSON对象
  16. 会声会影2022旗舰终极版详细功能介绍
  17. ipv4如何访问ipv6的地址
  18. 求网络号,广播地址,第一个可用ip,最后一个可用ip。可用ip总数
  19. db2数据库建表的时候主键怎么建_DB2数据库建表报错
  20. PHP获取今天、昨天、明天的日期

热门文章

  1. S7 200 smart模拟量应用介绍
  2. 英语单词背诵系统(有单词背诵,错词背诵功能)
  3. CF487E Tourists (圆方树,LCT)
  4. 电子科技大学信通2018级学生上早自习缺勤率情况分析
  5. 图计算论文笔记--SPARC: Self-Paced Network Representation for Few-Shot Rare Category Characterization
  6. 硬盘和硬盘驱动器的区别
  7. 【Gym 100015B】Ball Painting(DP染色)
  8. linux 使用sock编程实例
  9. android 网络编程 笔记,【Android 应用开发】Android 网络编程 API笔记
  10. QT 析构的报错Cannot send events to objects owned by a different thread.