时间:2024-7-11 作者:老大夫 分类: SpringCloud
三大部分:路由(有没有的问题)、断言(可不可以访问的问题)、过滤(访问前后进行的操作)
由于存在geteway映射写死的问题
解决办法:
改写成 lb://service (服务名称)lb是loadbalence负载均衡的意思
两种配置方法:简介配置、全面配置
#id:我们自定义的路由 ID,保持唯一
##uri:目标服务地址
##predicates:路由条件,Predicate接受一个输入参数返回一个布尔值。
## 该属性包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非)
public void test01(){
ZonedDateTime zbj = ZonedDateTime.now(); // 默认时区
System.out.println(zbj);
}
得到 2024-07-11T14:54:11.992550800+08:00[Asia/Shanghai]
After:超过时间戳后的时间才能访问
Before:在时间戳之前才能访问
Between:时间戳1,时间戳2 在时间戳之间才能访问
gateway:
routes:
- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
- After=2024-07-11T15:00:11.992550800+08:00[Asia/Shanghai]
,前面是cookie名称,后面是正则表达式
- Cookie=username,zzyy
- Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式
Host在请求头中 =后面是正则表达式
- Host=**.atguigu.com
=后是参数名,后是正则表达式
- Query=username, \d+ # 要有参数名username并且值还要是整数才能路由
限制外部访问的ip地址限制
- RemoteAddr=192.168.124.1/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。
- Method:Post
要求:
要么继承AbstractRoutePredicateFactory抽象类
要么实现RoutePredicateFactory接口
开头任意取名,但是必须以RoutePredicateFactory后缀结尾
package com.atguigu.cloud.mygateway;
import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory;
public class MyRoutePredicateFactory extends RoutePredicateFactory {
}
package com.atguigu.cloud.mygateway;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory;
import org.springframework.web.server.ServerWebExchange;
import java.util.function.Predicate;
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<AbstractRoutePredicateFactory.Config> {
@Override
public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {
return null;
}
}
package com.atguigu.cloud.mygateway;
import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;
import lombok.Setter;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;
import java.util.function.Predicate;
/**
* 需求:会员按照金银铜铁分类,控制不同等级是否可以访问
*/
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {
//这个Config就是断言规则
@Validated
public static class Config{
@Setter
@Getter
@NotEmpty
private String userType;//会员的金银铜铁等级
}
@Override
public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {
return null;
}
}
package com.atguigu.cloud.mygateway;
import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;
import lombok.Setter;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;
import java.util.function.Predicate;
/**
* 需求:会员按照金银铜铁分类,控制不同等级是否可以访问
*/
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {
public MyRoutePredicateFactory(){
super(MyRoutePredicateFactory.Config.class);
}
//这个Config就是断言规则
@Validated
public static class Config{
@Setter
@Getter
@NotEmpty
private String userType;//会员的金银铜铁等级
}
@Override
public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {
return null;
}
}
package com.atguigu.cloud.mygateway;
import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;
import lombok.Setter;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;
import java.util.function.Predicate;
/**
* 需求:会员按照金银铜铁分类,控制不同等级是否可以访问
*/
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {
public MyRoutePredicateFactory(){
super(MyRoutePredicateFactory.Config.class);
}
//这个Config就是断言规则
@Validated
public static class Config{
@Setter
@Getter
@NotEmpty
private String userType;//会员的金银铜铁等级
}
@Override
public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {
return new Predicate<ServerWebExchange>() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
//检查request里的参数,usertype是否为指定的值,符合就通过
//localhost:9527/pay/gateway/get/1?usertype=diamond
String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");
if (userType==null || userType.isEmpty()){
return false;
}
//如果参数存在就和config参数进行比较
if(userType.equalsIgnoreCase(config.getUserType())){
return true;
}
return false;
}
};
}
}
- My=diamond
使用快捷设置方法,发现报错:Failed to bind properties under '' to com.atguigu.cloud.mygateway.MyRoutePredicateFactory$Config
绑定报错
- name: My
args:
userType: diamond
使用全参数配置,发现恢复正常
原因:自定义断言类中没有重写快捷设置方法 shortcutFieldOrder
package com.atguigu.cloud.mygateway;
import jakarta.validation.constraints.NotEmpty;
import lombok.Getter;
import lombok.Setter;
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.server.ServerWebExchange;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
/**
* 需求:会员按照金银铜铁分类,控制不同等级是否可以访问
*/
@Component
public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<MyRoutePredicateFactory.Config> {
public MyRoutePredicateFactory(){
super(MyRoutePredicateFactory.Config.class);
}
//这个Config就是断言规则
@Validated
public static class Config{
@Setter
@Getter
@NotEmpty
private String userType;//会员的金银铜铁等级
}
@Override
public Predicate<ServerWebExchange> apply(MyRoutePredicateFactory.Config config) {
return new Predicate<ServerWebExchange>() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
//检查request里的参数,usertype是否为指定的值,符合就通过
//localhost:9527/pay/gateway/get/1?usertype=diamond
String userType = serverWebExchange.getRequest().getQueryParams().getFirst("userType");
if (userType==null || userType.isEmpty()){
return false;
}
//如果参数存在就和config参数进行比较
if(userType.equalsIgnoreCase(config.getUserType())){
return true;
}
return false;
}
};
}
@Override
public List<String> shortcutFieldOrder() {
return Collections.singletonList("userType");
}
}
添加请求头内容
@GetMapping(value = "/pay/gateway/filter")
public ResultData<String> getGatewayFilter(HttpServletRequest request)
{
String result = "";
Enumeration<String> headers = request.getHeaderNames();
while(headers.hasMoreElements())
{
String headName = headers.nextElement();
String headValue = request.getHeader(headName);
System.out.println("请求头名: " + headName +"\t\t\t"+"请求头值: " + headValue);
if(headName.equalsIgnoreCase("X-Request-atguigu1")
|| headName.equalsIgnoreCase("X-Request-atguigu2")) {
result = result+headName + "\t " + headValue +" ";
}
}
return ResultData.success("getGatewayFilter 过滤器 test: "+result+" \t "+ DateUtil.now());
}
- id: pay_routh3 #pay_routh3
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/pay/gateway/filter/** # 断言,路径相匹配的进行路由
filters:
- AddRequestHeader=X-Request-atguigu1,atguiguValue1 # 请求头kv,若一头含有多参则重写一行设置
- AddRequestHeader=X-Request-atguigu2,atguiguValue2
移除指定的请求头
server:
port: 9527
spring:
application:
name: cloud-gateway #以微服务注册进consul或nacos服务列表内
cloud:
consul: #配置consul地址
host: localhost
port: 8500
discovery:
prefer-ip-address: true
service-name: ${spring.application.name}
gateway:
routes:
- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
- After=2023-12-30T23:02:39.079979400+08:00[Asia/Shanghai]
#- Cookie=username,zzyy
# - Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式
#- Host=**.atguigu.com
#- Query=username, \d+ # 要有参数名username并且值还要是整数才能路由
#- RemoteAddr=192.168.124.1/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。
- My=gold
# - name: My
# args:
# userType: diamond
- id: pay_routh2 #pay_routh2 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service
predicates:
- Path=/pay/gateway/info/** # 断言,路径相匹配的进行路由
- id: pay_routh3 #pay_routh3
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/pay/gateway/filter/** # 断言,路径相匹配的进行路由
filters:
- AddRequestHeader=X-Request-atguigu1,atguiguValue1 # 请求头kv,若一头含有多参则重写一行设置
- AddRequestHeader=X-Request-atguigu2,atguiguValue2
- RemoveRequestHeader=sec-fetch-site # 删除请求头sec-fetch-site
设置请求头内容
- SetRequestHeader=sec-fetch-mode, Blue-updatebyzzyy # 将请求头sec-fetch-mode对应的值修改为Blue-updatebyzzyy
添加请求参数
删除请求参数
package com.atguigu.cloud.controller;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.atguigu.cloud.entities.Pay;
import com.atguigu.cloud.resp.ResultData;
import com.atguigu.cloud.service.PayService;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import java.util.Enumeration;
import java.util.concurrent.TimeUnit;
/**
* @auther zzyy
* @create 2023-11-20 13:09
*/
@RestController
public class PayGateWayController
{
@Resource
PayService payService;
@GetMapping(value = "/pay/gateway/get/{id}")
public ResultData<Pay> getById(@PathVariable("id") Integer id)
{
Pay pay = payService.getById(id);
return ResultData.success(pay);
}
@GetMapping(value = "/pay/gateway/info")
public ResultData<String> getGatewayInfo()
{
return ResultData.success("gateway info test:"+ IdUtil.simpleUUID());
}
@GetMapping(value = "/pay/gateway/filter")
public ResultData<String> getGatewayFilter(HttpServletRequest request)
{
String result = "";
Enumeration<String> headers = request.getHeaderNames();
while(headers.hasMoreElements())
{
String headName = headers.nextElement();
String headValue = request.getHeader(headName);
System.out.println("请求头名: " + headName +"\t\t\t"+"请求头值: " + headValue);
if(headName.equalsIgnoreCase("X-Request-atguigu1")
|| headName.equalsIgnoreCase("X-Request-atguigu2")) {
result = result+headName + "\t " + headValue +" ";
}
}
System.out.println("=============================================");
String customerId = request.getParameter("customerId");
System.out.println("request Parameter customerId: "+customerId);
String customerName = request.getParameter("customerName");
System.out.println("request Parameter customerName: "+customerName);
System.out.println("=============================================");
return ResultData.success("getGatewayFilter 过滤器 test: "+result+" \t "+ DateUtil.now());
}
}
- AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
- RemoveRequestParameter=customerName # 删除url请求参数customerName,你传递过来也是null
- AddResponseHeader=X-Response-atguigu, BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
- SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
- RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除
在路径前加上 /pay
访问的时候不用在地址栏输入/pay了,实际访问的是带/pay的地址
- PrefixPath=/pay # http://localhost:9527/pay/gateway/filter
设置路径
占位符{}内用什么字母都可以,
server:
port: 9527
spring:
application:
name: cloud-gateway #以微服务注册进consul或nacos服务列表内
cloud:
consul: #配置consul地址
host: localhost
port: 8500
discovery:
prefer-ip-address: true
service-name: ${spring.application.name}
gateway:
routes:
- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
#- After=2023-11-20T17:38:13.586918800+08:00[Asia/Shanghai]
- Before=2023-12-29T17:58:13.586918800+08:00[Asia/Shanghai]
#- Between=2023-11-21T17:38:13.586918800+08:00[Asia/Shanghai],2023-11-22T17:38:13.586918800+08:00[Asia/Shanghai]
#- Cookie=username,zzyy
#- Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式
#- Host=**.atguigu.com
#- Query=username, \d+ # 要有参数名username并且值还要是整数才能路由
#- RemoteAddr=192.168.1.196/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24。
- id: pay_routh2 #pay_routh2 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/pay/gateway/info/** # 断言,路径相匹配的进行路由
- id: pay_routh3 #pay_routh3
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
#- Path=/pay/gateway/filter/** # 真实地址
#- Path=/gateway/filter/** # 断言,为配合PrefixPath测试过滤,暂时注释掉/pay
- Path=/XYZ/abc/{segment} # 断言,为配合SetPath测试,{segment}的内容最后被SetPath取代
filters:
- AddRequestHeader=X-Request-atguigu1,atguiguValue1 #请求头kv,若一头含有多参则重写一行设置
#- AddRequestHeader=X-Request-atguigu2,atguiguValue2
#- RemoveRequestHeader=sec-fetch-site # 删除请求头sec-fetch-site
#- SetRequestHeader=sec-fetch-mode, Blue-updatebyzzyy # 将请求头sec-fetch-mode对应的值修改为Blue-updatebyzzyy
#- AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
#- RemoveRequestParameter=customerName # 删除url请求参数customerName,你传递过来也是null
#- AddResponseHeader=X-Response-atguigu, BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
#- SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
#- RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除
#- PrefixPath=/pay # http://localhost:9527/pay/gateway/filter
- SetPath=/pay/gateway/{segment} # {segment}表示占位符,你写abc也行但要上下一致
/XYZ/abc/{segment},{segment}就是个占位符,等价于SetPath后面指定的{segment}内容
浏览器访问地址: http://localhost:9527/XYZ/abc/filter
实际微服务地址:http://localhost:9527/pay/gateway/filter
server:
port: 9527
spring:
application:
name: cloud-gateway #以微服务注册进consul或nacos服务列表内
cloud:
consul: #配置consul地址
host: localhost
port: 8500
discovery:
prefer-ip-address: true
service-name: ${spring.application.name}
gateway:
routes:
- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
#- After=2023-11-20T17:38:13.586918800+08:00[Asia/Shanghai]
- Before=2023-12-29T17:58:13.586918800+08:00[Asia/Shanghai]
#- Between=2023-11-21T17:38:13.586918800+08:00[Asia/Shanghai],2023-11-22T17:38:13.586918800+08:00[Asia/Shanghai]
#- Cookie=username,zzyy
#- Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式
#- Host=**.atguigu.com
#- Query=username, \d+ # 要有参数名username并且值还要是整数才能路由
#- RemoteAddr=192.168.1.196/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24。
- id: pay_routh2 #pay_routh2 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
#uri: http://localhost:8001 #匹配后提供服务的路由地址
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/pay/gateway/info/** # 断言,路径相匹配的进行路由
- id: pay_routh3 #pay_routh3
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/pay/gateway/filter/** # 真实地址
#- Path=/gateway/filter/** # 断言,为配合PrefixPath测试过滤,暂时注释掉/pay
#- Path=/XYZ/abc/{segment} # 断言,为配合SetPath测试,{segment}的内容最后被SetPath取代
filters:
- AddRequestHeader=X-Request-atguigu1,atguiguValue1 #请求头kv,若一头含有多参则重写一行设置
#- AddRequestHeader=X-Request-atguigu2,atguiguValue2
#- RemoveRequestHeader=sec-fetch-site # 删除请求头sec-fetch-site
#- SetRequestHeader=sec-fetch-mode, Blue-updatebyzzyy # 将请求头sec-fetch-mode对应的值修改为Blue-updatebyzzyy
#- AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
#- RemoveRequestParameter=customerName # 删除url请求参数customerName,你传递过来也是null
#- AddResponseHeader=X-Response-atguigu, BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
#- SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
#- RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除
#- PrefixPath=/pay # http://localhost:9527/pay/gateway/filter
- RedirectTo=302, http://www.atguigu.com/ # 访问http://localhost:9527/pay/gateway/filter跳转到http://www.atguigu.com/
Default Filters会应用到所有路由上,不推荐
package com.atguigu.cloud.mygateway;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Map;
/**
* @auther zzyy
* @create 2023-11-22 17:41
*/
@Component //不要忘记
@Slf4j
public class MyGlobalFilter implements GlobalFilter, Ordered
{
public static final String BEGIN_VISIT_TIME="begin_visit_time";//开始调用方法的时间
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain)
{
//1.先记录下访问接口的开始时间
exchange.getAttributes().put(BEGIN_VISIT_TIME,System.currentTimeMillis());
//返回统计的各个结果给后台
return chain.filter(exchange).then(Mono.fromRunnable(()->{
Long beginVisitTime = (Long) exchange.getAttribute(BEGIN_VISIT_TIME);
if (beginVisitTime!=null){
log.info("访问接口主机:"+exchange.getRequest().getURI().getHost());
log.info("访问接口URL:"+exchange.getRequest().getURI().getPath());
log.info("访问接口URL后面的参数:"+exchange.getRequest().getURI().getRawQuery());
log.info("访问接口主机:"+exchange.getRequest().getURI().getHost());
log.info("访问接口时长:"+(System.currentTimeMillis()-beginVisitTime)+"毫秒");
log.info("===============分割线======================");
System.out.println();
}
}));
}
/**
* 数字越小优先级越高
* @return
*/
@Override
public int getOrder()
{
return 0;
}
}
yml里路由断言设置好了哪些链接路由归GateWay管(之前的设置不用动)
然后运行就可以了
package com.atguigu.cloud.mygateway;
import lombok.Getter;
import lombok.Setter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.stereotype.Component;
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config>
{
public static class Config {
@Setter
@Getter
private String status;
}
}
package com.atguigu.cloud.mygateway;
import lombok.Getter;
import lombok.Setter;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
/**
* @auther zzyy
* @create 2023-04-29 17:37
*/
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config>
{
@Override
public GatewayFilter apply(MyGatewayFilterFactory.Config config)
{
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
System.out.println("进入自定义网关过滤器MyGatewayFilterFactory,status===="+config.getStatus());
if(request.getQueryParams().containsKey("atguigu")) {
return chain.filter(exchange);
}else {
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
return exchange.getResponse().setComplete();
}
}
};
}
public static class Config {
@Setter @Getter
private String status;
}
}
package com.atguigu.cloud.mygateway;
import lombok.Getter;
import lombok.Setter;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config>
{
@Override
public GatewayFilter apply(MyGatewayFilterFactory.Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
System.out.println("进入了自定义网关过滤器MyGatewayFilterFactory,status:"+config.getStatus());
if(request.getQueryParams().containsKey("atguigu")){
return chain.filter(exchange);
}else {
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
return exchange.getResponse().setComplete();
}
}
};
}
public static class Config {
@Setter
@Getter
private String status;//设定一个状态值,它等于多少才可以访问
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("status");
}
}
package com.atguigu.cloud.mygateway;
import lombok.Getter;
import lombok.Setter;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
@Component
public class MyGatewayFilterFactory extends AbstractGatewayFilterFactory<MyGatewayFilterFactory.Config>
{
public MyGatewayFilterFactory() {
super(MyGatewayFilterFactory.Config.class);
}
@Override
public GatewayFilter apply(MyGatewayFilterFactory.Config config) {
return new GatewayFilter() {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
System.out.println("进入了自定义网关过滤器MyGatewayFilterFactory,status:"+config.getStatus());
if(request.getQueryParams().containsKey("atguigu")){
return chain.filter(exchange);
}else {
exchange.getResponse().setStatusCode(HttpStatus.BAD_REQUEST);
return exchange.getResponse().setComplete();
}
}
};
}
public static class Config {
@Setter
@Getter
private String status;//设定一个状态值,它等于多少才可以访问
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList("status");
}
}
server:
port: 9527
spring:
application:
name: cloud-gateway #以微服务注册进consul或nacos服务列表内
cloud:
consul: #配置consul地址
host: localhost
port: 8500
discovery:
prefer-ip-address: true
service-name: ${spring.application.name}
gateway:
routes:
- id: pay_routh1 #pay_routh1 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/pay/gateway/get/** # 断言,路径相匹配的进行路由
# - After=2024-07-11T15:00:11.992550800+08:00[Asia/Shanghai]
# - Cookie=username,zzyy
# - Header=X-Request-Id, \d+ # 请求头要有X-Request-Id属性并且值为整数的正则表达式
# - Host=**.atguigu.com
# - Query=username, \d+ # 要有参数名username并且值还要是整数才能路由
# - name: My
# args:
# userType: diamond
# - My=diamond
# - RemoteAddr=10.0.0.1/24 # 外部访问我的IP限制,最大跨度不超过32,目前是1~24它们是 CIDR 表示法。
- id: pay_routh2 #pay_routh2 #路由的ID(类似mysql主键ID),没有固定规则但要求唯一,建议配合服务名
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/pay/gateway/info/** # 断言,路径相匹配的进行路由
- id: pay_routh3 #pay_routh3
uri: lb://cloud-payment-service #匹配后提供服务的路由地址
predicates:
- Path=/pay/gateway/filter/** # 断言,路径相匹配的进行路由,默认正确地址
# - Path=/gateway/filter/** # 断言,路径相匹配的进行路由,默认正确地址
# - Path=/XYZ/abc/{segment} # 断言,为配合SetPath测试,{segment}的内容最后被SetPath取代
filters:
- My=atguigu
# - AddRequestHeader=X-Request-atguigu1,atguiguValue1 # 请求头kv,若一头含有多参则重写一行设置
# - AddRequestHeader=X-Request-atguigu2,atguiguValue2
# - RemoveRequestHeader=sec-fetch-site # 删除请求头sec-fetch-site
# - SetRequestHeader=sec-fetch-mode, Blue-updatebyzzyy # 将请求头sec-fetch-mode对应的值修改为Blue-updatebyzzyy
# - AddRequestParameter=customerId,9527001 # 新增请求参数Parameter:k ,v
# - RemoveRequestParameter=customerName # 删除url请求参数customerName,你传递过来也是null
# - AddResponseHeader=X-Response-atguigu, BlueResponse # 新增请求参数X-Response-atguigu并设值为BlueResponse
# - SetResponseHeader=Date,2099-11-11 # 设置回应头Date值为2099-11-11
# - RemoveResponseHeader=Content-Type # 将默认自带Content-Type回应属性删除
# - PrefixPath=/pay # http://localhost:9527/pay/gateway/filter
# - SetPath=/pay/gateway/{segment} # {segment}表示占位符,你写abc也行但要上下一致
# - RedirectTo=302, http://www.atguigu.com/ # 访问http://localhost:9527/pay/gateway/filter跳转到http://www.atguigu.com/
推荐阅读: