1. 微服务应用场景
创建父工程spring-cloud,依赖如下
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<gson.version>2.8.0</gson.version>
<jackson.version>2.9.5</jackson.version>
<swagger.version>2.9.2</swagger.version>
<mybatis.plus.boot.version>3.1.0</mybatis.plus.boot.version>
<hutool.version>5.3.4</hutool.version>
<druid.version>1.1.10</druid.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.8.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR6</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
1.1 创建服务提供者
springcloud-provider
添加依赖
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis.plus.boot.version}</version>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!--mybatis逆向生成-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.0</version>
<scope>test</scope>
</dependency>
配置application.yml
server:
port: 8081
spring:
application:
name: provider
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.100.101:3306/springcloud?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
username: root
password: 123456
mybatis-plus:
mapper-locations: classpath:mapper/*.xml # mapper映射文件的路径
type-aliases-package: com.iweb.model
global-config:
db-config:
id-type: id_worker # 分布式全局唯一id
configuration:
map-underscore-to-camel-case: false # 驼峰是否转下划线
cache-enabled: true # 全局缓存开关
lazy-loading-enabled: true # 延迟加载
multiple-result-sets-enabled: true # 开启延时加载,否则按需加载 属性
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印sql语句
通过mybatis-plus直接生成
public class MyBatisGenerate {
@Test
public void generate() {
//
String url = "jdbc:mysql://192.168.100.101:3306/springcloud?useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull";
// 基本包
String parentPackage = "com.iweb";
String baseDir = System.getProperty("user.dir");
String driverClassName = "com.mysql.cj.jdbc.Driver";
String username = "root";
String password = "123456";
// 表 前缀
String[] tablePrefix = new String[]{"tb_"};
String[] tableNames = new String[]{"tb_user"};
/*数据源*/
DataSourceConfig dsc = new DataSourceConfig();
dsc.setDbType(DbType.MYSQL);
dsc.setUrl(url);
dsc.setDriverName(driverClassName);
dsc.setUsername(username);
dsc.setPassword(password);
/*全局配置*/
GlobalConfig gc = new GlobalConfig();
gc.setOutputDir(baseDir + "/src/main/java");
gc.setFileOverride(true);
gc.setActiveRecord(true);
gc.setEnableCache(false);// XML 二级缓存
gc.setBaseResultMap(true);// XML ResultMap
gc.setBaseColumnList(true);// XML columList
gc.setAuthor("jack");
gc.setMapperName("%sMapper");
gc.setXmlName("%sMapper");
gc.setServiceName("%sService");
gc.setServiceImplName("%sServiceImpl");
gc.setControllerName("%sController");
/*生成策略*/
StrategyConfig strategy = new StrategyConfig();
strategy.setEntityLombokModel(true);
strategy.setEntityTableFieldAnnotationEnable(true);
strategy.setTablePrefix(tablePrefix);// 此处可以修改为您的表前缀
strategy.setNaming(NamingStrategy.underline_to_camel);// 表名生成策略
strategy.setInclude(tableNames); // 需要生成的表
/*生成文件包配置*/
PackageConfig pc = new PackageConfig();
pc.setParent(parentPackage);
pc.setController("controller");
pc.setService("service");
pc.setServiceImpl("service.impl");
pc.setEntity("model");
pc.setMapper("mapper");
AutoGenerator mpg = new AutoGenerator();
/*xml文件配置*/
InjectionConfig cfg = new InjectionConfig() {
@Override
public void initMap() {
// nothing
}
};
//xml生成路径
List<FileOutConfig> focList = new ArrayList<>();
focList.add(new FileOutConfig("/templates/mapper.xml.vm") {
@Override
public String outputFile(TableInfo tableInfo) {
return baseDir + "/src/main/resources/" + "/mapper/" + tableInfo.getEntityName() + "Mapper.xml";
}
});
cfg.setFileOutConfigList(focList);
mpg.setCfg(cfg);
// 关闭默认 xml 生成,调整生成 至 根目录
TemplateConfig tc = new TemplateConfig();
tc.setXml(null);
mpg.setDataSource(dsc); //数据源配置
mpg.setGlobalConfig(gc); //全局配置
mpg.setStrategy(strategy); //生成策略配置
mpg.setPackageInfo(pc); //包配置
mpg.setCfg(cfg); //xml配置
mpg.setTemplate(tc); //
// 执行生成
mpg.execute();
}
}
完成Controller
@RequestMapping("/user")
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping
public List<User> findAll() {
return userService.list();
}
@GetMapping("{id}")
public User findById(@PathVariable Long id) {
return userService.getById(id);
}
}
1.2 创建服务消费者
springcloud-consumer
添加依赖
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-annotation</artifactId>
<version>3.1.0</version>
<scope>compile</scope>
</dependency>
配置application.yml
server:
port: 8082
spring:
application:
name: consumer
完成 ConsumerController
@RequestMapping("/consumer")
@RestController
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@GetMapping
private List<User> findAll() {
String url = "http://localhost:8081/user";
return restTemplate.getForObject(url, List.class);
}
}
通过消费者向提供者请求数据:http://127.0.0.1:8082/consumer
2. 注册中心 Spring Cloud Eureka
2.1 创建注册中心
springcloud-eureka
2.2 注册提供者到注册中心
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
修改application.yml配置文件
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8761/eureka
将微服务注册到注册中心
@EnableDiscoveryClient // 注册到注册中心
@SpringBootApplication
@MapperScan(value = "com.iweb.mapper")
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class);
}
}
在Eureka监控页面可以看到服务注册成功信息
2.3 注册消费者到注册中心
添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
修改application.yml配置文件
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:8761/eureka
将微服务注册到注册中心
@EnableDiscoveryClient // 注册到注册中心
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
2.4 通过注册中心访问提供者
@RequestMapping("/consumer")
@RestController
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping
private List<User> findAll() {
// String url = "http://localhost:8081/user";
// return restTemplate.getForObject(url, List.class);
List<ServiceInstance> instances = discoveryClient.getInstances("provider");
ServiceInstance info = instances.get(0);
String host = info.getHost();
int port = info.getPort();
String url = String.format("http://%s:%s/user", host, port);
return restTemplate.getForObject(url, List.class);
}
}
2.5 Eureka详解
3. 负载均衡 Spring Cloud Ribbon
3.1 启动2个提供者
port=8080和port=8081
3.2 开启消费者负载均衡
@Bean
@LoadBalanced // 开启负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
3.3 通过服务名称调用
@GetMapping
private List<User> findAll() {
// String url = "http://localhost:8081/user";
// List<ServiceInstance> instances = discoveryClient.getInstances("provider");
// ServiceInstance info = instances.get(0);
// String host = info.getHost();
// int port = info.getPort();
// String url = String.format("http://%s:%s/user", host, port);
// 通过服务名称调用
String url = String.format("http://provider/user");
return restTemplate.getForObject(url, List.class);
}
3.4 配置负载策略
# 修改服务地址轮询策略,默认是轮询,配置之后变随机
# RandomRule 随机
# RoundRobinRule 轮询策略
provider:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
4. 熔断器 Spring Cloud Hystrix
4.1 什么是熔断器
Hystrix,英文意思是豪猪,全身是刺,刺是一种保护机制。Hystrix也是Netflix公司的一款组件。
Hystrix的作用是什么?
Hystrix是Netflix开源的一个延迟和容错库,用于隔离访问远程服务、第三方库、防止出现级联失败也就是雪崩效应。
4.2 雪崩效应
- 微服务中,一个请求可能需要多个微服务接口才能实现,会形成复杂的调用链路。
- 如果某服务出现异常,请求阻塞,用户得不到响应,容器中线程不会释放,于是越来越多用户请求堆积,越来越多线程阻塞。
- 单服务器支持线程和并发数有限,请求如果一直阻塞,会导致服务器资源耗尽,从而导致所有其他服务都不可用,从而形成雪崩效应;
Hystrix解决雪崩问题的手段,主要是服务降级**(兜底)**,线程隔离;
4.3 熔断器简单实现
在springcloud-consumer中添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
配置熔断器注解
// @SpringCloudApplication =等同于@SpringBootApplication+@EnableDiscoveryClient+@EnableCircuitBreaker
//@EnableCircuitBreaker // 开启熔断
//@EnableDiscoveryClient // 注册到注册中心
//@SpringBootApplication
@SpringCloudApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class);
}
@Bean
@LoadBalanced // 开启负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
编写服务降级处理方法:使用@HystrixCommand定义fallback方法。
@GetMapping("{id}")
@HystrixCommand(fallbackMethod = "findByIdFallback")
public User findById(@PathVariable Long id) {
if (id == 1) {
throw new RuntimeException("too busy!!!");
}
// 通过服务名称调用
String url = String.format("http://provider/user/%d", id);
return restTemplate.getForObject(url, User.class);
}
// 返回值和 findById 方法需要相同
public User findByIdFallback(Long id) {
return new User();
}
测试请求:localhost:8082/consumer/1 抛出异常后熔断器生效
4.4 熔断器的配置策略
# 配置熔断策略:
hystrix:
command:
default:
circuitBreaker:
# 原理分析中解释配置含义
# 强制打开熔断器 默认false关闭的。测试配置是否生效
forceOpen: false
# 触发熔断错误比例阈值,默认值50%
errorThresholdPercentage: 50
# 熔断后休眠时长,默认值5秒
sleepWindowInMilliseconds: 5000
# 熔断触发最小请求次数,默认值是20
requestVolumeThreshold: 10
execution:
isolation:
thread:
# 熔断超时设置,默认为1秒
timeoutInMilliseconds: 2000
修改springcloud-provider中UserController的findById方法
@GetMapping("{id}")
public User findById(@PathVariable Long id) {
try {
Thread.sleep(3000); // 熔断器配置 2 秒
} catch (InterruptedException e) {
e.printStackTrace();
}
return userService.getById(id);
}
测试:localhost:8082/consumer/2 实际请求 3 秒 熔断器生效
4.5 熔断器的原理
熔断器状态机有3个状态:
- 关闭状态,所有请求正常访问
- 打开状态,所有请求都会被降级。
- Hystrix会对请求情况计数,当一定时间失败请求百分比达到阈值,则触发熔断,断路器完全关闭
- 默认失败比例的阈值是50%,请求次数最低不少于20次
- 半开状态
- 打开状态不是永久的,打开一会后会进入休眠时间(默认5秒)。休眠时间过后会进入半开状态。
- 半开状态:熔断器会判断下一次请求的返回状况,如果成功,熔断器切回关闭状态。如果失败,熔断器切回打开状态。
熔断器的核心解决方案:线程隔离和服务降级。
- 线程隔离。
- 服务降级(兜底方法)。
线程隔离和服务降级之后,用户请求故障时,线程不会被阻塞,更不会无休止等待或者看到系统奔溃,至少可以看到执行结果(熔断机制)。
什么时候熔断
- 访问超时
- 服务不可用(死了)
- 服务抛出异常(虽然有异常但还活着)
- 其他请求导致服务异常到达阈值,所有服务都会被降级
4.6 配置全局熔断器
在控制器添加注解 @DefaultProperties(defaultFallback = “defaultFallback”)
在目标方法上添加注解 @HystrixCommand //不指定 fallbackMethod 即可
5. 远程调用 Spring Cloud Feign
前面学习中,使用RestTemplate大大简化了远程调用的代码
String url = String.format("http://provider/user/%d", id);
return restTemplate.getForObject(url, User.class);
而我们只用spring cloud 的Feign 功能可以更加优雅的来实现。
5.1 Feign的简介
Feign 的英文表意为“假装,伪装,变形”, 是一个http请求调用的轻量级框架,是以Java接口注解的方式调用Http请求,而不用像Java中通过封装HTTP请求报文的方式直接调用。Feign通过处理注解,将请求模板化,当实际调用的时候,传入参数,根据参数再应用到请求上,进而转化成真正的请求,这种请求相对而言比较直观。
Feign被广泛应用在Spring Cloud 的解决方案中,是学习基于Spring Cloud 微服务架构不可或缺的重要组件。
5.1 入门案例
5.2.1 添加依赖
在springcloud-consumer中添加依赖
<!--配置feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
5.2.2 编写Feign客户端
/**
* 作者: jack
* 时间: 2020-07-07 19:15
* 描述: UserClient
*/
@FeignClient("provider")
public interface UserClient {
@GetMapping("/user/{id}") // 这里的url要写完整的
public User findById(@PathVariable Long id);
}
5.2.3 使用Feign客户端
开启Feign功能
@SpringCloudApplication
@EnableFeignClients
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class);
}
@Bean
@LoadBalanced // 开启负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
在ConsumerController中改造
@RequestMapping("/consumer")
@RestController
public class ConsumerController {
@Autowired
private RestTemplate restTemplate;
// 注入Feign客户端
@Autowired
private UserClient userClient;
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping
private List<User> findAll() {
String url = String.format("http://provider/user");
return restTemplate.getForObject(url, List.class);
}
@GetMapping("{id}")
@HystrixCommand(fallbackMethod = "findByIdFallback")
public User findById(@PathVariable Long id) {
// 通过服务名称调用
// String url = String.format("http://provider/user/%d", id);
// return restTemplate.getForObject(url, User.class);
// 使用Feign客户端的方式调用
return userClient.findById(id);
}
public User findByIdFallback(Long id) {
return new User();
}
}
修改提供者的方法
@GetMapping("{id}")
public User findById(@PathVariable Long id) {
// try {
// Thread.sleep(2000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
return userService.getById(id);
}
测试请求 http://localhost:8082/consumer/1
5.2 Feign客户端支持负载均衡
Feign中已经自动集成Ribbon负载均衡,因此不需要自定义RestTemplate进行负载均衡的配置
5.3 Feign客户端熔断器使用
5.3.1 在application.yml中开启feign熔断器支持
# feign熔断器支持开启
feign:
hystrix:
enabled: true
5.3.2 编写FallBack处理类,实现FeignClient客户端
@Component
public class UserClientFallback implements UserClient {
@Override
public User findById(Long id) {
User user = new User();
user.setName("用户不存在");
return user;
}
}
5.3.3 在@FeignClient注解中,指定FallBack处理类
PS:这里要关闭之前的熔断器
@FeignClient(value = "provider", fallback = UserClientFallback.class)
public interface UserClient {
@GetMapping("/user/{id}") // 这里的url要写完整的
public User findById(@PathVariable Long id);
}
修改UserController用来测试
@GetMapping("{id}")
public User findById(@PathVariable Long id) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return userService.getById(id);
}
测试:http://localhost:8082/consumer/1
5.4 请求压缩和响应压缩
开启以下配置即可
feign:
hystrix:
enabled: true
compression:
request:
enabled: true
# 压缩的文件类型
mime-types: text/html,application/xml,application/json
# 压缩文件的其实大小
min-request-size: 1024
response:
enabled: true
6. 网关 Spring Cloud Gateway
Spring Cloud Gateway 是Spring Cloud团队的一个全新项目,基于Spring 5.0、SpringBoot2.0、Project Reactor 等技术开发的网关。 旨在为微服务架构提供一种简单有效统一的REST 请求路由管理方式。
Spring Cloud Gateway 作为SpringCloud生态系统中的网关,目标是替代Netflflix Zuul。Gateway不仅提供统一路由方式,并且基于Filter链的方式提供网关的基本功能。例如:安全,监控/指标,和限流。
本身也是一个微服务,需要注册到Eureka
**网关的核心功能:**过滤(权限)、路由
核心概念:
- 路由(route)
- 断言Predicate函数:路由转发规则
- 过滤器(Filter)
spring cloud
Gateway
不支持spring boot web
包 所以这边要把父工程的 spring boot web删除在需要的子工程添加,前面忘记了就懒得修改笔记了。注意以下
6.1 入门案例
创建子模块springcloud-gateway并添加依赖
<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>
编写启动类并注册为eureka客户端
/**
* 作者: jack
* 时间: 2020-07-07 20:02
* 描述: GatewayApplication
*/
@EnableDiscoveryClient
@SpringBootApplication
public class GatewayApplication {
public static void main(String[] args) {
SpringApplication.run(GatewayApplication.class);
}
}
配置application.yml
server:
port: 8083
spring:
application:
name: gateway
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]': # 匹配所有请求
allowedOrigins: "*" #跨域处理 允许所有的域
allowedMethods: # 支持的方法
- GET
- POST
- PUT
- DELETE
routes:
- id: provider-router # 唯一标识
uri: lb://provider # 路由地址,动态路由
predicates: # 断言
- Path=/user/** # 请求url 多个使用逗号
eureka:
client:
service-url:
defauleZone: http://127.0.0.1:8761/eureka
启动网关测试:http://localhost:8083/user/1 可以通过网关的端口进行访问,说明网关配置成功
6.2 路由前缀
在gateway中可以通过配置路由的过滤器PrefifixPath 实现映射路径中的前缀添加。可以起到隐藏接口地址的作用,避免接口地址暴露。
predicates:
- Path=/**
filters:
- PrefixPath=/user
测试访问地址:http://localhost:8083/1
在gateway中通过配置路由过滤器StripPrefifix,实现映射路径中地址的去除。通过StripPrefifix=1来指定路由要去掉的前缀个数。如:路径/api/user/1将会被路由到/user/1。
predicates:
- Path=/api/**
filters:
- StripPrefix=1
测试访问地址:http://localhost:8083/api/user/1
6.4 过滤器
过滤器作为网关的其中一个重要功能,就是实现请求的鉴权。前面的 路由前缀 章节中的功能也是使用过滤器实现的。
Gateway自带过滤器有几十个,常见自带过滤器有:
过滤器名称 | 说明 |
---|---|
AddRequestHeader | 对匹配上的请求加上Header |
AddRequestParameters | 对匹配上的请求路由 |
AddResponseHeader | 对从网关返回的响应添加Header |
StripPrefifix | 对匹配上的请求路径去除前缀 |
PrefifixPath | 对匹配上的请求路径添加前缀 |
配置全局过滤器
spring:
application:
name: gateway
cloud:
gateway:
default-filters:
- AddResponseHeader=ilove,web
请求后可以看到响应头添加了 ilove=web
6.4.1自定义全局过滤器
模拟一个登录的校验。基本逻辑:如果请求中有token参数,则认为请求有效,放行
@Component
public class TokenFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
System.out.println("TokenFilter is filter");
// TO DO
return chain.filter(exchange);
}
//设置过滤器执行顺序,值越小,优先级越高
@Override
public int getOrder() {
return 0;
}
}
6.4.2 自定义局部过滤器
自定义GatewayFilter有两种实现方式,一种是直接实现GatewayFilter接口,另一种是继承AbstractGatewayFilterFactory类 ,任意选一种即可
package com.iweb.filter;
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.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 作者: jack
* 时间: 2020-07-07 21:24
* 描述: AuthorizeGatewayFilter
* Authorize(自定义) GatewayFilterFactory(固定写法)
*/
@Component
public class AuthorizeGatewayFilterFactory extends AbstractGatewayFilterFactory<AuthorizeGatewayFilterFactory.Config> {
/**
* Prefix key.
*/
public static final String AUTHOR_NAME = "name"; // 接收配置的参数 这里可以不写
public AuthorizeGatewayFilterFactory() {
super(Config.class);
}
@Override
public List<String> shortcutFieldOrder() {
return Arrays.asList(AUTHOR_NAME);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
System.out.println("AuthorizeGatewayFilterFactory is filter");
System.out.println(config.name);
return chain.filter(exchange);
};
}
public static class Config {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
}
在application.yml中配置
spring:
application:
name: gateway
cloud:
gateway:
default-filters:
- AddResponseHeader=ilove,web
globalcors:
cors-configurations:
'[/**]': # 匹配所有请求
allowedOrigins: "*" #跨域处理 允许所有的域
allowedMethods: # 支持的方法
- GET
- POST
- PUT
- DELETE
routes:
- id: provider-router # 唯一标识
uri: lb://provider # 路由地址,动态路由
predicates:
- Path=/api/**
filters:
- StripPrefix=1
- Authorize=iweb
控制台输出
AuthorizeGatewayFilterFactory is filter
iweb