gateway 动态网关路由
介绍:API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它 与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。它可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与 管理、静态响应处理。API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。
·
介绍:API网关是一个服务器,是系统的唯一入口。从面向对象设计的角度看,它与外观模式类似。API网关封装了系统内部架构,为每个客户端提供一个定制的API。它可能还具有其它职责,如身份验证、监控、负载均衡、缓存、请求分片与 管理、静态响应处理。API网关方式的核心要点是,所有的客户端和消费端都通过统一的网关接入微服务,在网关层处理所有的非业务功能。通常,网关也是提供REST/HTTP的访问API。服务端通过API-GW注册和管理服务。
具体实现流程图:
第一步:pom新增需要包
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
第二步:application.yml文件配置
server:
port: 9090
eureka:
client:
service-url:
defaultZone: http://admin:admin@127.0.0.1:8761/eureka/
instance:
prefer-ip-address: true
spring:
application:
name: microservice-gateway
redis:
host: 192.168.0.116
port: 6379
profiles:
active: dev
management:
endpoint:
refresh:
enabled: true
endpoints:
web:
exposure:
include: refresh,health,info
第三步:加载网关配置
网关配置类
import com.example.constant.GatewayEnum;
import com.example.pojo.vo.RouteVo;
import com.example.tools.RedisTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactory;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* @Author: 胡成
* @Version: 0.0.1V
* @Date: 2018/11/19
* @Description: 网关路由初始化
**/
@Slf4j
@Configuration
public class GatewayConfig {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Bean
@RefreshScope
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
StripPrefixGatewayFilterFactory.Config config = new StripPrefixGatewayFilterFactory.Config();
config.setParts(1);
RouteLocatorBuilder.Builder routeLocator = builder.routes();
List<RouteVo> lists = RedisTools.hget(stringRedisTemplate, GatewayEnum.ROUTE_LIST.getKey(),RouteVo.class);
log.info("加载网关路由配置 --> {}",lists);
lists.forEach(routeVo -> routeLocator.route(routeVo.getId(),
r -> r.path(routeVo.getPath()).and().weight(routeVo.getGroup(),
routeVo.getWeight()).filters(f -> f.stripPrefix(1)).uri(routeVo.getUri())));
return routeLocator.build();
}
}
路由参数
import lombok.Data;
import java.io.Serializable;
/**
* @Author: 胡成
* @Version: 0.0.1V
* @Date: 2018/11/20
* @Description: 网关路由bean
**/
@Data
public class RouteVo implements Serializable {
private static final long serialVersionUID = 1L;
/**唯一*/
private String id;
/**转发识别 eg:/path/** */
private String path;
/**分组,如果需要双机负载均衡,就把两个路由group填写一致*/
private String group;
/**权重,配合分组使用,如果分组填写了,就可以调节权重0-100*/
private Integer weight;
/**转发目标的地址*/
private String uri;
}
网关路由枚举
import lombok.Getter;
import lombok.Setter;
/**
* @Author: 胡成
* @Version: 0.0.1V
* @Date: 2018/11/20
* @Description: 网关路由枚举类
**/
public enum GatewayEnum {
/**
* 路由枚举
*/
ROUTE_LIST("route:list");
@Setter
@Getter
private String key;
GatewayEnum(String key) {
this.key = key;
}
public static GatewayEnum get(String key) {
for (GatewayEnum c : GatewayEnum.values()) {
if (c.key == key) {
return c;
}
}
return null;
}
}
第四步:修改新增路由方法
@PostMapping("saveGateway")
public String saveGateway(RouteVo routeVo) throws UnsupportedEncodingException {
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
routeVo.setId(uuid);
RedisTools.hset(stringRedisTemplate, GatewayEnum.ROUTE_LIST.getKey(), uuid, JSON.toJSONString(routeVo));
//刷新路由配置bean
restTemplate.getForObject(http://网关服务:9090/actuator/refresh , String.class);
return "success";
}
@PostMapping("updateGateway")
public String updateGateway(RouteVo routeVo) throws UnsupportedEncodingException {
//判断key是否存在
if (!RedisTools.existsHash(stringRedisTemplate, GatewayEnum.ROUTE_LIST.getKey(), routeVo.getId())) {
log.info("网关路由key不存在直接返回");
return "fail";
}
RedisTools.hset(stringRedisTemplate, GatewayEnum.ROUTE_LIST.getKey(), routeVo.getId(), JSON.toJSONString(routeVo));
//刷新路由配置bean
restTemplate.getForObject(http://网关服务:9090/actuator/refresh , String.class);
return "success";
}
第五步:修改路由或者新增路由只需要刷新customRouteLocator bean就行,请求http://网关服务:9090/actuator/refresh,新增或修改路由,操作redis数据,然后刷新路由
项目下载
更多推荐
已为社区贡献2条内容
所有评论(0)