Spring全家桶之SpringCloud——高级阶段(中)

SpringCloud高级阶段中

  • 第四章 如何设计微服务
    • 一、微服务常用的六种设计模式
    • 二、 微服务设计模式实战
      • 需求分析
      • 数据库设计
      • product服务
      • 根据接product服务,写出用户,订单,交易服务
      • 创建消费者服务,实现消费者代理对其他服务的调用
      • 服务调用服务(Trade去调用Order进行查询和更新)
  • 第五章 服务网关Zuul
    • 一、 什么是网关服务
    • 二、 编写网关服务入门案例
      • 路由规则总结
    • 三、 自定义网关过滤器
      • 采用网关过滤器实现权限验证
      • 采用网关过滤器对系统异常同一处理
    • 四、 网关容错
    • 五、 在高并发情况下,网关实现限流达到自我保护
    • 六、zuul超时调优图解
  • 第六章 分布式配置中心
    • 一、 为什么需要使用配置中心
    • 二、编写配置中心入门案例
      • 创建配置中心server端
        • 配置中心配置文件的命名与访问规则
      • 创建配置中心Client端
        • bootstrap与application的区别
    • 三、在 git 端修改配置后,在不重启服务中如何让客户端生效
      • cmd命令刷新git上的配置文件: curl -X POST http://localhost:服务的端口号/actuator/refresh
    • 四、 安全与加密
      • 使用对称加密算法 ,实现敏感数据加密
        • 1.创建配置中心服务端
        • 2.使用HTTPClient向数据加密的服务中心配置发送命令,对数据进行加密
        • 3.配置中心客户端(E-Book-Product-Provider)
        • 4.需要将数据库的相关配置/下面代码上传至配置中心(码云/git)
        • 5.通过配置中心服务端访问码云上的配置文件,查看是否显示解密后的数据
        • 6.出现上图后 ,启动被提供加密服务(E-Book-Product-Provider) ,访问相关的方法,查看联网的配置是否可用
      • 使用非对称加密算法 ,实现敏感数据加密
        • 1.配置中心服务端
        • 2.使用对称加密使用到的HTTPClient工具类向生成秘钥的项目发送请求
        • 3.创使用非对称加密的项目( config-E-Book-Product-Provider-RSA )
        • 4.在码云上创建 config-E-Book-Product-Provider-RSA.yml文件 ,修改其内容
        • 5.通过生成秘钥的服务中心访问创建好的配置文件
        • 6.访问被加密的项目,发现可以正常运行
      • 配置中心的用户安全认证
        • 配置中心服务端
        • 配置中心客户端

SpringCloud高级阶段上 传送门
第一章 负载均衡Ribbon
第二章 声明式调用Feign
第三章 服务容错保护Hystrix

SpringCloud高级阶段中(当前所在位置)
第四章 如何设计微服务
第五章 服务网关Zuul
第六章 分布式配置中心

SpringCloud高级阶段下 传送门
第七章 消息总线Bus
第八章 消息驱动Stream
第九章 分布式服务跟踪Sleuth

第四章 如何设计微服务

一、微服务常用的六种设计模式

Spring全家桶之SpringCloud——高级阶段(中)_第1张图片

Spring全家桶之SpringCloud——高级阶段(中)_第2张图片

Spring全家桶之SpringCloud——高级阶段(中)_第3张图片

Spring全家桶之SpringCloud——高级阶段(中)_第4张图片

Spring全家桶之SpringCloud——高级阶段(中)_第5张图片

Spring全家桶之SpringCloud——高级阶段(中)_第6张图片

二、 微服务设计模式实战

需求分析

如下图所示:
模拟电商项目中的订单模块, 因此需要添加模拟登陆 ,浏览商品 ,支付功能 ,订单功能等.
使用的最核心的设计模式为代理设计模式 ,通过Consumer对用户进行代理来进行相关的操作
Spring全家桶之SpringCloud——高级阶段(中)_第7张图片

数据库设计

  1. User 表

用户表,存放用户的相关属性,手动添加相关数据

CREATE TABLE `user` (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  `password` varchar(50) NOT NULL COMMENT '密码',
  `email` varchar(50) NOT NULL COMMENT 'email',
  `deleted` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT ' 删除标志,默认 0 不删除,1 删除',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='用户表';

  1. Product 表

产品表,存放产品的相关属性 , 手动添加相关数据

CREATE TABLE `product` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `name` varchar(100) DEFAULT NULL COMMENT '产品名称',
  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '产品状态:0 待 审,1 上架,2 下架,3 停售,4 测试',
  `price` int(10) NOT NULL COMMENT '产品价格 单位分',
  `detail` text COMMENT '产品详情',
  `deleted` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT ' 删除标志,默认 0 不删除,1 删除',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更 新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='产品信息';

  1. Orders 表

订单表,存放订单的相关信息 , 手动添加相关数据

CREATE TABLE `orders` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `product_id` int(10) NOT NULL DEFAULT '0' COMMENT '产品 ID',
  `price` int(10) DEFAULT '0' COMMENT '价格',
  `user_id` int(10) DEFAULT '0' COMMENT '用户账号 ID',
  `trade_id` int(10) DEFAULT '0' COMMENT '交易号 ID',
  `trade_status` tinyint(1) DEFAULT '0' COMMENT '支付状态 0=未支付 \r\n\r\n \r\n \r\n1=已支付',
  `deleted` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT ' 删除标志,默认 0 不删除,1 删除',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更 新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

4 Trade 表

交易表,存放交易的相关信息 , 手动添加相关数据

CREATE TABLE `trade` (
  `id` int(10) NOT NULL AUTO_INCREMENT COMMENT 'IID',
  `order_id` int(10) NOT NULL COMMENT '订单 ID',
  `user_id` int(10) NOT NULL COMMENT '用户 ID',
  `price` int(10) NOT NULL COMMENT '支付价',
  `pay_status` tinyint(4) NOT NULL COMMENT '1 未付款 2 付款中 3 付款失败 4 付款完成',
  `pay_type` tinyint(4) NOT NULL COMMENT '支付类型:1-支付宝支付, 2-网银在线,3-银联,4-微信支付',
  `gateway_pay_num` varchar(30) DEFAULT NULL COMMENT '网关支 付流水号',
  `gateway_pay_time` datetime DEFAULT NULL COMMENT '网关支付 时间',
  `gateway_pay_price` int(10) NOT NULL DEFAULT '0' COMMENT '网关 实际支付金额',
  `deleted` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT ' 删除标志,默认 0 不删除,1 删除',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更 新时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='交易';

product服务

Spring全家桶之SpringCloud——高级阶段(中)_第8张图片
1.官网快速构建产品服务的接口项目,添加相关坐标

	<parent>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring-boot-starter-parentartifactId>
		<version>2.1.7.RELEASEversion>
	parent>

	<properties>
		<java.version>1.8java.version>
		<spring-cloud.version>Greenwich.SR2spring-cloud.version>
		<maven-jar-plugin.version>2.6maven-jar-plugin.version>
	properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
		dependency>
	dependencies>

2.创建产品服务的提供者项目,添加相关坐标
勿忘添加服务接口项目的坐标

<parent>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring-boot-starter-parentartifactId>
		<version>2.1.7.RELEASEversion>
	parent>
	
	<properties>
		<java.version>1.8java.version>
		<spring-cloud.version>Greenwich.SR2spring-cloud.version>
		<maven-jar-plugin.version>2.6maven-jar-plugin.version>
	properties>

	<dependencies>
		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
		dependency>
		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-thymeleafartifactId>
		dependency>
		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-starterartifactId>
		dependency>
		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
		dependency>

		
		<dependency>
			<groupId>org.mybatis.spring.bootgroupId>
			<artifactId>mybatis-spring-boot-starterartifactId>
			<version>1.1.1version>
		dependency>
		
		<dependency>
			<groupId>mysqlgroupId>
			<artifactId>mysql-connector-javaartifactId>
		dependency>
		
		<dependency>
			<groupId>com.alibabagroupId>
			<artifactId>druidartifactId>
			<version>1.0.9version>
		dependency>
		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-devtoolsartifactId>
			
			<optional>trueoptional>
		dependency>



		
		<dependency>
			<groupId>ah.szxy.springcloudgroupId>
			<artifactId>E-Book-Trade-ServiceartifactId>
			<version>0.0.1-SNAPSHOTversion>
		dependency>
	dependencies>

3.修改全局配置文件application.yml的参数

项目名,
jdbc数据库连接参数,
该项目的端口号,
mybatis参数配置中实体类所在包
mapper.xml配置文件所在地址
Eureka注册中心地址,可以不配置,但需要将参数注释

spring:
  application:
    name: E-Book-Product-Provider
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/book-product?useUnicode=true&characterEncoding=gbk&useJDBCCompliantTimezoneShift=true&serverTimezone=UTC
    username: root
    password: root
    type: com.alibaba.druid.pool.DruidDataSource

server:
  port: 8001
  compression:   #springboot的gzip配置
    enabled: true   #是否启用压缩  
    mime-types:    #配置压缩支持的 MIME TYPE
    - application/json,application/ xml,text/html,text/xml,text/plain
    
mybatis:
  type-aliases-package: ah.szxy.product.pojo
  mapper-locations:
  - classpath:ah/szxy/product/mapper/*.xml 

eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/

4.使用Mybatis逆向工程生成实体类,mapper接口与mapper.xml文件
点击查看MyBatis Generator( 逆向工程以及源码分析 )

5.将逆向工程生成的实体类放入服务接口项目中,并编写业务层访问代码
Spring全家桶之SpringCloud——高级阶段(中)_第9张图片

/**
 * 产品服务接口
 * @author chy
 *
 */
@RequestMapping("/product")
public interface ProductService {
	
	@RequestMapping(value="/find",method=RequestMethod.GET)
	public List<Product> findAll();
}

6.将逆向工程生成的Mapper接口与Mapper映射配置文件放入服务提供者项目下

Spring全家桶之SpringCloud——高级阶段(中)_第10张图片

7.业务层接口实现类,作用是调用Mapper接口,进而实现对数据库的查询操作

/**
 * 这里通过对mapper的操作实现对数据库的操作-查询所有
 * @author chy
 *
 */
@Service
public class ProductServiceImpl {
	
	@Autowired
	private ProductMapper mapper;
	
	public List<Product> findAll(){
		
		ProductExample example = new ProductExample();
		return this.mapper.selectByExampleWithBLOBs(example);//查询的条件中带有大字段
	}
}

8.Controller
注意:
1.需要实现服务接口项目中的相关项目接口
2.@RestController ,会在前端页面返回Json串

@RestController
public class ProductController implements ProductService{
	
	@Autowired
	private ProductServiceImpl productServiceImpl;
	
	@Override
	public List<Product> findAll() {

		return this.productServiceImpl.findAll();
	}
	
}

返回结果类似下图
在这里插入图片描述

根据接product服务,写出用户,订单,交易服务

创建消费者服务,实现消费者代理对其他服务的调用

1.创建项目,修改pom文件
因为继承服务接口项目中的接口,所以需要添加所有服务接口项目的坐标

	<parent>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring-boot-starter-parentartifactId>
		<version>2.1.7.RELEASEversion>
	parent>
<properties>
		<java.version>1.8java.version>
		<spring-cloud.version>Greenwich.SR2spring-cloud.version>
		<maven-jar-plugin.version>2.6maven-jar-plugin.version>
	properties>

	<dependencies>
		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
		dependency>

		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-starterartifactId>
		dependency>
		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
		dependency>
		
		
		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-starter-openfeignartifactId>
		dependency>
		
		 
		<dependency>
			<groupId>ah.szxy.springcloudgroupId>
			<artifactId>E-Book-User-ServiceartifactId>
			<version>0.0.1-SNAPSHOTversion>
		dependency>
		<dependency>
			<groupId>ah.szxy.springcloudgroupId>
			<artifactId>E-Book-Trade-ServiceartifactId>
			<version>0.0.1-SNAPSHOTversion>
		dependency>
		<dependency>
			<groupId>ah.szxy.springcloudgroupId>
			<artifactId>E-Book-Product-ServiceartifactId>
			<version>0.0.1-SNAPSHOTversion>
		dependency>
		<dependency>
			<groupId>ah.szxy.springcloudgroupId>
			<artifactId>E-Book-Order-ServiceartifactId>
			<version>0.0.1-SNAPSHOTversion>
		dependency>
		
		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-devtoolsartifactId>
			
			<optional>trueoptional>
		dependency>
		
	dependencies>

2.修改全局配置文件application.yml

spring:
  application:
    name: E-Book-Consumer
server:
  port: 8888


eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/

3.创建四个消费者服务接口,继承服务接口项目中的接口

/**
 * 调用订单服务
 * @FeignClient 声明式调用服务,需要指明提供者的名称
 * 继承服务接口项目的接口
 * 
 * @author chy
 *
 */
@FeignClient("E-Book-Order-Provider")   
public interface ConsumerOrderService extends OrderService{

}

/**
 * 调用产品服务
 * @FeignClient 声明式调用服务,需要指明提供者的名称
 * 继承服务接口项目的接口
 * 
 * @author chy
 *
 */
@FeignClient("E-Book-Product-Provider")
public interface ConsumerProductService extends ProductService{

}

/**
 * 调用交易服务
 * @FeignClient 声明式调用服务,需要指明提供者的名称
 * 继承服务接口项目的接口
 * 
 * @author chy
 *
 */
@FeignClient("E-Book-Trade-Provider")
public interface ConsumerTradeService extends TradeService {

}
/**
 * 调用用户服务
 * @FeignClient 声明式调用服务,需要指明提供者的名称
 * 继承服务接口项目的接口
 * 
 * @author chy
 *
 */
@FeignClient("E-Book-User-Provider")
public interface ConsumerUserService extends UserService {

}

4.将所有的业务逻辑提升到Controller ,实现相关的业务逻辑

/**
 * 创建订单
 * @author chy
 *
 */
@RestController
public class ConsumerController {
	
	@Autowired
	private ConsumerOrderService orderService;
	@Autowired
	private ConsumerProductService productService;
	@Autowired
	private ConsumerUserService userService;
	@Autowired
	private ConsumerTradeService tradeService;
	
	/**
	* 模拟内容: 登录 查看产品 下订单
	* 1. 测试登录 账号 admin admin
	* 2. 查看所有产品列表
	* 3. 选第一款产品,下订单
	* 4. 实现订单交易支付
	* 5. 查看所有的订单信息
	*/
	@RequestMapping(value="/create",method=RequestMethod.GET)
	public List<Orders> createOrder() {
		System.out.println("++++++++++创建订单是测试是否登录++++++++");
		//创建订单是测试是否登录
		Integer userid = this.login();
		System.out.println(userid);
		System.out.println("++++++++++++++++++");
		
		System.out.println("++++++++++登陆成功后,查看所有商品+++++++++");
		//登陆成功后,查看所有商品
		List<Product> list = this.productService.findAll();
		for(Product product:list) {
			System.out.println(product.getName());
		}
		System.out.println("+++++++++++++++++++");
		
		System.out.println("+++++++++下单++++++++++");
		//选择第一款商品下单
		Product product = list.get(0);
		Integer orderid=1004;
		//创建订单
		Orders order = new Orders();
		order.setId(orderid);
		order.setUserId(userid);
		order.setProductId(product.getId());
		order.setPrice(product.getPrice());
		order.setDeleted((byte) 0);//0不删除,1删除
		//调用Order服务完成持久化订单
		Integer result = this.orderService.addOrder(order);
		System.out.println("交易订单结果"+result);
		System.out.println("++++++++++++++++++++++++");
		System.out.println("+++++++++++创建交易订单+++++++++++++");
		
		Trade trade = new Trade();
		trade.setOrderId(orderid);
		trade.setUserId(userid);
		trade.setPrice(order.getPrice());
		trade.setPayStatus((byte) 4);//'1 未付款 2 付款中 3 付款失败 4 付款完成',
		trade.setPayType((byte) 4);//'支付类型:1-支付宝支付, 2-网银在线,3-银联,4-微信支付',
		trade.setGatewayPayNum(new Date().getTime()+"");
		trade.setGatewayPayPrice(order.getPrice());
		trade.setGatewayPayTime(new Date());
		trade.setDeleted((byte) 0);
		this.tradeService.addTrade(trade);
		
		//查询所有订单并返回
		List<Orders> orderlist = this.orderService.findAll();
		return orderlist;
	}
	
	/**
	 * 用户登陆
	 * @return
	 */
	private Integer login() {
		String userName="admin";
		String password="admin";
		User user = this.userService.userLogin(userName, password);
		if (user !=null && user.getUserName().length() >=0) {
			System.err.println("登陆成功");
			return user.getId();
		}
		System.out.println("登陆失败");
		return null;
	}
	
	
}

5.启动类

因为使用声明式调用,需要添加@EnableFeignClients

@SpringBootApplication
@EnableDiscoveryClient
@EnableFeignClients
public class StartClass {
	public static void main(String[] args) {
		SpringApplication.run(StartClass.class, args);
	}
}

测试结果
Spring全家桶之SpringCloud——高级阶段(中)_第11张图片

服务调用服务(Trade去调用Order进行查询和更新)

1.修改Trade的pom文件
添加Order接口项目的坐标
添加Feign的坐标


		<dependency>
			<groupId>ah.szxy.springcloudgroupId>
			<artifactId>E-Book-Order-ServiceartifactId>
			<version>0.0.1-SNAPSHOTversion>
		dependency>
		
		
		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-starter-openfeignartifactId>
		dependency>

2.添加提供者的代理消费接口

@FeignClient("E-Book-Order-Provider")  //接口不允许多类继承,而接口可以多继承接口
public interface ProviderOrderService extends OrderService{

}

3.添加消费者添加的方法,在这里调用Order的服务,查询并且修改Order
需要在Order接口项目中添加接口,提供者项目中创建实现类以及Controller方法(查询,更新)

	@Override
	public void addTrade(@RequestBody Trade trade) {
		//添加交易信息
		this.tradeServiceImpl.addTrade(trade);
		
		//根据id查询订单
		Orders order = orderService.findOrderById(trade.getOrderId());
		//order.setId(trade.getId());
		order.setTradeId(trade.getId());
		//更新订单(修改了订单id)
		this.orderService.updateOrder(order);
		
	}

查询和更新接口,其他省略

//根据订单id查询订单
	@RequestMapping(value="/findById",method=RequestMethod.GET)
	public Orders findOrderById(@RequestParam("orderid")Integer orderid);
	
	//更新订单
	@RequestMapping(value="update",method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE)
	public void updateOrder(@RequestBody Orders order);

3.启动类,需要额外添加@EnableFeignClients ,表示将要调用其他服务

@SpringBootApplication
@EnableEurekaClient
@MapperScan("ah.szxy.trade.mapper")//只能添加Mapper所在的包,而不是具体的类
@EnableFeignClients
public class TradeProviderApp {
	public static void main(String[] args) {
		SpringApplication.run(TradeProviderApp.class, args);
	}
}

功能思路

  1. 用户登录,调用user-provider实现登录。
  2. 查询商品:调用product-provider浏览商品
  3. 下订单:接受到请求后创建订单对象,填入基本信息,同时创建trade对象,设置关联关系。
    保存值数据库,在返回订单列表
  4. 支付:接受到请求后根据用户查找到未支付的订单order,在根据订单中的tradeid获取trade对象,修改trade和order信息。更新数据库,上述步骤在trade-provider中实现,创建一个接口继承orderserviceapi,使用feign调用。
    注:需要在各个provider中添加方法。
    接受参数是一定要是用 使用@RequsetParam注解,且一定要加参数。

第五章 服务网关Zuul

一、 什么是网关服务

什么是API网关
API网关是一个反向路由:屏蔽内部细节,为调用者提供统一入口,接收所有调用者请求,通过路由机制转发到服务实例。
API网关是一组“过滤器”集合:可以实现一系列与核心业务无关的横切面功能,如安全认证、限流熔断、日志监控。
Spring全家桶之SpringCloud——高级阶段(中)_第12张图片

二、 编写网关服务入门案例

1.创建项目,修改pom文件

<parent>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring-boot-starter-parentartifactId>
		<version>2.1.7.RELEASEversion>
	parent>

	<properties>
		<java.version>1.8java.version>
		<spring-cloud.version>Greenwich.SR2spring-cloud.version>
		<maven-jar-plugin.version>2.6maven-jar-plugin.version>
	properties>
	<dependencies>
		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-devtoolsartifactId>
			
			<optional>trueoptional>
		dependency>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
		dependency>
		
		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
		dependency>
		
		<dependency>
		  <groupId>org.springframework.cloudgroupId>
		  <artifactId>spring-cloud-starter-netflix-zuulartifactId>
		dependency>
	dependencies>
	
	<dependencyManagement>
	<dependencies>
			<dependency>
				<groupId>org.springframework.cloudgroupId>
				<artifactId>spring-cloud-dependenciesartifactId>
				<version>${spring-cloud.version}version>
				<type>pomtype>
				<scope>importscope>
			dependency>
		dependencies>
	dependencyManagement>

2.修改全局配置文件

spring:
  application:
    name: Zuul-Gateway
    
server:
  port: 9999

eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/

# URL 匹配关键字,如果包含path就跳转到指定的 URL 中
zuul:   #配置路由规则
  routes:
    E-Book-Product-Provider:   #此处为网关代理的服务名称
      path: /E-Book-Product-Provider/**
      url: http://localhost:8001/

3.启动类
添加@EnableZuulProxy注解

@SpringCloudApplication
@EnableZuulProxy
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

访问路径

http:// 网关服务地址 :网关服务端口 /访问的服务名称 /访问服务的接口地址

Spring全家桶之SpringCloud——高级阶段(中)_第13张图片
注:path中符号的含义

符号 含义
/? 匹配一个字符
/* 匹配任意字符,但只能匹配单层路径
/ ** 匹配任意字符,可以匹配多层路径

zuul.routs.name.path中的name可以变更,通常使用服务名。

路由规则总结

1.通过url:
http://localhost:9999/suibian/product/find

	zuul:
	  routes:
	     E-Book-Product-Provider:
	      path: /suibian/**
	      url: http://localhost:8001/

2.通过服务名, service-id为服务名
http://localhost:9999/suibian/product/find

	zuul:
	  routes:
	    E-Book-Product-Provider:
	      path: /suibian/**
	      service-id: E-Book-Product-Provider

3.通过服务名(简化)
http://localhost:9999/suibian/product/find

zuul:
  routes:
    E-Book-Product-Provider:
      path: /suibian/**

不指定service-id,但要求zuul.routs.name.path中的name为服务名。

4.路由排除法

	zuul:
	    ignored-services:  #排除知道服务。也可以排除所有服务/*,可以同routes添加不排除的服务
	    - /*               # E-Book-Product-Provider
	    ignored-patterns:  #排除指定路径 使用符号统配
	    - /*/findAll

5.添加前缀 , 访问时服务路径前必须添加前缀
http://localhost:9999/sui/bian/product/find

zuul:
  prefix: /sui
  routes:
     E-Book-Product-Provider:  #必须是服务名
             path: /bian/** 

三、 自定义网关过滤器

1.复制上方案例,添加日志配置文件logback.xml


 <configuration>
  
    <property name="LOG_HOME" value="${catalina.base}/logs/" />  
       
    <appender name="Stdout" class="ch.qos.logback.core.ConsoleAppender">
         
        <layout class="ch.qos.logback.classic.PatternLayout">   
              
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n   
            pattern>   
        layout>   
    appender>   
       
    <appender name="RollingFile"  class="ch.qos.logback.core.rolling.RollingFileAppender">   
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            
            <FileNamePattern>${LOG_HOME}/server.%d{yyyy-MM-dd}.logFileNamePattern>   
            <MaxHistory>30MaxHistory>
        rollingPolicy>   
        <layout class="ch.qos.logback.classic.PatternLayout">  
             
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n   
            pattern>   
       layout> 
        
       <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
         <MaxFileSize>10MBMaxFileSize>
       triggeringPolicy>
    appender>     

    
    <root level="info">   
        <appender-ref ref="Stdout" />   
        <appender-ref ref="RollingFile" />   
    root> 



  


configuration>

2.修改全局配置文件

spring:
  application:
    name: Zuul-Gateway-Filter
    
server:
  port: 9999

eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/

# URL 匹配关键字,如果包含path就跳转到指定的 URL中
zuul:   #配置路由规则
  routes:
    E-Book-Product-Provider:
      path: /E-Book-Product-Provider/**
      url: http://localhost:8001/

3.创建过滤器
注意所导的包

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

@Component
public class MyFilter extends ZuulFilter{
	
	private Logger log=LoggerFactory.getLogger(MyFilter.class);

	/**
	 * 过滤逻辑
	 */
	@Override
	public Object run() throws ZuulException {
		
		RequestContext rc=RequestContext.getCurrentContext();
		HttpServletRequest req = rc.getRequest();
		log.info("Filter:method:{}+url:{}",req.getMethod(),req.getRequestURL().toString() );
		return null;
	}

	/**
	 * 是否开启过滤
	 */
	@Override
	public boolean shouldFilter() {
		// TODO Auto-generated method stub
		return true;
	}

	/**
	 * 拦截优先级   数字越小越高
	 */
	@Override
	public int filterOrder() {
		// TODO Auto-generated method stub
		return 0;
	}
	

	/**
	 * 拦截器类型
	 * PRE过滤器:是在请求路由到具体服务之前执行的,可以做安全验证,如身份验证,参数验证。
	*ROUTING过滤器:它用于将请求 路由到具体的微服务实例。默认使用Http Client进行网络请求。
	*POST过滤器:在请求已被路由到微服务后执行的。可用作收集统计信息、指标,以及将响应传输到客户端。
	*ERROR过滤器:在其他过滤器发生错误时执行。
    *只能小写
	 */
	@Override
	public String filterType() {
		// TODO Auto-generated method stub
		return "pre";
	}
}

运行启动器, 测试结果
在这里插入图片描述

过滤器类型(需要小写)
Spring全家桶之SpringCloud——高级阶段(中)_第14张图片

Zuul请求的声明周期(结合上图来看)

Spring全家桶之SpringCloud——高级阶段(中)_第15张图片

采用网关过滤器实现权限验证

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;

import io.micrometer.core.instrument.util.StringUtils;

/**
 * 简单的登录权限校验
 * @author Administrator
 *
 */
@Component
public class TokenFilter extends ZuulFilter{
	
	private static final Logger log=LoggerFactory.getLogger(TokenFilter.class);

	/**
	 * 过滤逻辑
	 */
	@Override
	public Object run() throws ZuulException {
		
		RequestContext rc=RequestContext.getCurrentContext();
		HttpServletRequest req = rc.getRequest();
		String token = req.getParameter("token");
		if(StringUtils.isEmpty(token)) {
			//未登录
			log.warn("未登录!!!!");
			rc.setSendZuulResponse(false);//设置不向下传递,拦截不通过
			rc.setResponseStatusCode(401);
			rc.setResponseBody("未登录!!请先登录");
			rc.getResponse().setContentType("text/html;charset=utf-8");
			
		}else {
			log.info("已登录,通过过滤器!!!");
			
		}
		return null;
	}

	/**
	 * 是否开启过滤
	 */
	@Override
	public boolean shouldFilter() {
		return true;
	}

	/**
	 * 拦截优先级   数字越小越高
	 */
	@Override
	public int filterOrder() {
		return 0;
	}
	

	/**
	 * 拦截器类型
	 * PRE过滤器:是在请求路由到具体服务之前执行的,可以做安全验证,如身份验证,参数验证。
	*ROUTING过滤器:它用于将请求 路由到具体的微服务实例。默认使用Http Client进行网络请求。
	*POST过滤器:在请求已被路由到微服务后执行的。可用作收集统计信息、指标,以及将响应传输到客户端。
	*ERROR过滤器:在其他过滤器发生错误时执行。
	 */
	@Override
	public String filterType() {
		//只能是小写
		return "pre";
	}
}

采用网关过滤器对系统异常同一处理

  1. 创建异常过滤器
    在过滤器逻辑中自定义了一个异常RuntimeException(“运行异常”)
@Component
public class ErrorMyFilter extends ZuulFilter{
	
	private Logger log=LoggerFactory.getLogger(ErrorMyFilter.class);

	/**
	 * 过滤逻辑
	 */
	@Override
	public Object run() throws ZuulException {
		
		RequestContext rc=RequestContext.getCurrentContext();
		HttpServletRequest req = rc.getRequest();
			//http://localhost:9999/E-Book-Product-Provider/product/find?token=suibian
			log.info("------网关过滤器拦截异常------");
			throw new RuntimeException("运行异常");
			
	}
	/**
	 * 是否开启过滤
	 */
	@Override
	public boolean shouldFilter() {
		// TODO Auto-generated method stub
		return true;
	}

	/**
	 * 拦截优先级   数字越小越高
	 */
	@Override
	public int filterOrder() {
		// TODO Auto-generated method stub
		return 0;
	}
	

	/**
	 * 拦截器类型
	 * PRE过滤器:是在请求路由到具体服务之前执行的,可以做安全验证,如身份验证,参数验证。
	*ROUTING过滤器:它用于将请求 路由到具体的微服务实例。默认使用Http Client进行网络请求。
	*POST过滤器:在请求已被路由到微服务后执行的。可用作收集统计信息、指标,以及将响应传输到客户端。
	*ERROR过滤器:在其他过滤器发生错误时执行。
    *只能小写
	 */
	@Override
	public String filterType() {
		// TODO Auto-generated method stub
		return "error";
	}
}

2.创建异常处理的controller

@RestController
public class ExceptionHandler implements ErrorController {

	@Override
	public String getErrorPath() {
		return "/error";
	}
	
	@RequestMapping("/error")
	public String handler() {
		return "出错了!!!!";
	}

}

四、 网关容错

一. zuul 和 hystrix 无缝结合
在 zuul 的 jar 包中包含了 hystrix 的 jar 包。所以我们不需要在项目中添加 Hystrix 的坐标 (SpringBoot2.0以上版本需要在配置文件中启用hystrix.stream)

management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream 
  1. 启动并访问一个服务,然后使用网关访问这个服务

  2. 访问网关服务的数据监控流

    http://localhost:9999/actuator/hystrix.stream

  3. 启动 dashboard 服务通过可视化界面查看监控数据
    Spring全家桶之SpringCloud——高级阶段(中)_第16张图片

二. 在网关中实现对服务降级处理

  1. 创建项目
  2. 导入依赖(zuul)
  3. 修改配置文件(项目名、端口、注册中心)
spring:
  application:
    name: Zuul-Gateway-FallBack
    
server:
  port: 9020

eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/

zuul:   #配置路由规则
  routes:
    E-Book-Product-Provider:
      path: /E-Book-Product-Provider/**
      url: http://localhost:8001/
  1. 添加fallback类
    实现ZuulFallbackProvider接口**(2.0版本后实现FallbackProvider接口)**
/**
 * 实现FallbackProvider接口,实现服务降级
 * 
 * 1.添加@Component注解
 * 2.getRoute方法返回监控的服务名称
 * 3.FallbackProvider
 * 
 * @author Administrator
 *
 */
@Component
public class ProductProviderFallback implements FallbackProvider {

	/**
	 * 对指定的服务提供降级处理
	 */
	@Override
	public String getRoute() {
		return "E-Book-Product-Provider";
	}

	/**
	 * 设置降级后返回的响应
	 */
	@Override
	public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
		return new ClientHttpResponse() {
			
			/**
			 * 响应头
			 */
			@Override
			public HttpHeaders getHeaders() {
				HttpHeaders hander=new HttpHeaders();
				hander.setContentType(MediaType.APPLICATION_JSON_UTF8);
				return hander;
			}
			/**
			 * 响应体
			 */
			@Override
			public InputStream getBody() throws IOException {
				String content="请求服务不可达!请联系管理员!";
				return new ByteArrayInputStream(content.getBytes());
			}
			/**
			 * 状态码:String类型
			 */
			@Override
			public String getStatusText() throws IOException {
				// TODO Auto-generated method stub
				return getStatusCode().getReasonPhrase();
			}
			/**
			 * 状态码:HttpStatus类型
			 */
			@Override
			public HttpStatus getStatusCode() throws IOException {
				return HttpStatus.OK;
			}
			/**
			 * 状态码:int类型
			 */
			@Override
			public int getRawStatusCode() throws IOException {
				// TODO Auto-generated method stub
				return getStatusCode().value();
			}
			
			/**
			 * 关闭
			 */
			@Override
			public void close() {
				
			}
		};
	}
}

启动类

@SpringCloudApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

测试结果
启动一个服务,然后通过网关服务进行访问 ,最后关闭服务, 刷新网关服务页面,查看页面输出结果

Spring全家桶之SpringCloud——高级阶段(中)_第17张图片

五、 在高并发情况下,网关实现限流达到自我保护

  1. 创建项目 ,导入依赖
    注意额外添加了限流的jar包redis的坐标
	
	<properties>
		<java.version>1.8java.version>
		<spring-cloud.version>Greenwich.SR2spring-cloud.version>
		<maven-jar-plugin.version>2.6maven-jar-plugin.version>
	properties>
	<dependencies>
		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-devtoolsartifactId>
			
			<optional>trueoptional>
		dependency>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
		dependency>
		
		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
		dependency>
		
		<dependency>
		  <groupId>org.springframework.cloudgroupId>
		  <artifactId>spring-cloud-starter-netflix-zuulartifactId>
		dependency>
		
		
		
		<dependency>
		    <groupId>com.marcosbarbero.cloudgroupId>
		    <artifactId>spring-cloud-zuul-ratelimitartifactId>
		    <version>2.2.3.RELEASEversion>
		dependency>
		
		<dependency>
		    <groupId>org.springframework.bootgroupId>
		    <artifactId>spring-boot-starter-data-redisartifactId>
		dependency>
	dependencies>

2.修改全局配置值文件

spring:
  application:
    name: Zuul-getway-ratelimit
  redis:
  #redis单机配置
    host: 47.98.169.238
    port: 6379
#redis连接池配置
    jedis:
      pool:
        max-idle: 10
        min-idle: 5
        max-active: 100
        max-wait: 3000
server:
  port: 8888
  
eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/

#配置路由规则
zuul:
  routes:
    E-Book-Product-Provider:
      path: /suibian/**

  ratelimit:
    enabled: true   #开启限流
    #全 局 限 流
    default-policy-list:       #全局配置  
    - limit: 10    #访问次数
      quota: 30     #访问总时间
      refresh-interval: 60      #时间间隔
    # 即在时间间隔内 访问的次数 总时间小于 访问总时间 就会被限制
      type:
      - origin    #对ip进行限制
    repository: redis    #数据存储方式,默认为内存存储
    #指定服务限流(局部限流)
#    policy-list:
#      E-Book-Product-Provider:  #被限流的服务名
#      - limit: 10
#        quota: 30
#        refresh-interval: 60
#        type:
#        - url
#      repository: redis    #数据存储方式,默认为内存存储

#开启监控端点   http://ip:port/actuator/hystrix.stream    需要actuatorjar包
#management:
#  endpoints:
#    web:
#      exposure:
#        include: hystrix.stream 
        

补充 :超时参数介绍
Spring全家桶之SpringCloud——高级阶段(中)_第18张图片

3.测试
在60s内访问10次,且十次访问在30s内,被限流,返回429错误

Spring全家桶之SpringCloud——高级阶段(中)_第19张图片

4.可以通过异常处理类处理限流异常(429),返回指定的页面,创建友好的交互

六、zuul超时调优图解

背景介绍
hystrix的超时时间为1s,而ribbon为5s,假设请求在1s内没有处理完,就会timeout。
我们将hystrix的超时时间调高,避免timeout。
但ribbon的超时时间应该小于hystrix,在集群环境下,给充足的时间让ribbon调用集群中其他服务。

Spring全家桶之SpringCloud——高级阶段(中)_第20张图片

情景模拟
被hystrix监控的服务在查询数据库时,由于数据量大而请求响应时间大于1s,导致返回超时问题

异常错误模拟
令被监控的服务休眠两秒 ,出现如下错误Spring全家桶之SpringCloud——高级阶段(中)_第21张图片

解决方案
1.创建网关项目 ,修改pom


	<properties>
		<java.version>1.8java.version>
		<spring-cloud.version>Greenwich.SR2spring-cloud.version>
		<maven-jar-plugin.version>2.6maven-jar-plugin.version>
	properties>
	<dependencies>
			
			<optional>trueoptional>
		dependency>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
		dependency>
		
		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
		dependency>
		
		<dependency>
		  <groupId>org.springframework.cloudgroupId>
		  <artifactId>spring-cloud-starter-netflix-zuulartifactId>
		dependency>
	dependencies>

2.修改全局配置文件

设置Ribbo和hystrix的超时时限

spring:
  application:
    name: Zuul-Gateway-Timeout
    
server:
  port: 9999

eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/

#http://localhost:9999/suibian/product/find  
zuul:
  routes:
    E-Book-Product-Provider:
      path: /suibian/**

#hystrix的超时时限  
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 8000 
#ribbon的超时时限  
ribbon:
  ReadTimeout: 5000
  ConnectTimeout: 5000
             
management:
  endpoints:
    web:
      exposure:
        include: hystrix.stream 

3.启动类

@SpringCloudApplication
@EnableDiscoveryClient
@EnableZuulProxy
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

测试结果
访问刚才出现超时的页面,发现Zuul超时问题得以解决

第六章 分布式配置中心

一、 为什么需要使用配置中心

  1. 服务配置的现状
    Spring全家桶之SpringCloud——高级阶段(中)_第22张图片

  2. 常用的配置管理解决方案的缺点

Spring全家桶之SpringCloud——高级阶段(中)_第23张图片

  1. 为什么要使用SpringCloud Config配置中心
    Spring全家桶之SpringCloud——高级阶段(中)_第24张图片

  2. SpringCloud Config配置中心解决了什么问题
    Spring全家桶之SpringCloud——高级阶段(中)_第25张图片

二、编写配置中心入门案例

前提
使用码云作为git仓库。先注册码云账号,创建一个仓库即可,
下面会用到仓库的全网访问的url

Spring全家桶之SpringCloud——高级阶段(中)_第26张图片

创建配置中心server端

1.创建SpringCloud项目 ,修改pom文件
最重要的就是配置中心server 的坐标

<parent>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring-boot-starter-parentartifactId>
		<version>2.1.7.RELEASEversion>
	parent>

	<properties>
		<java.version>1.8java.version>
		<spring-cloud.version>Greenwich.SR2spring-cloud.version>
		<maven-jar-plugin.version>2.6maven-jar-plugin.version>
	properties>
	<dependencies>
		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-devtoolsartifactId>
			
			<optional>trueoptional>
		dependency>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
		dependency>
		
		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
		dependency>
		
		<dependency>
		  <groupId>org.springframework.cloudgroupId>
		  <artifactId>spring-cloud-starter-netflix-zuulartifactId>
		dependency>
		
		
		<dependency>
	      <groupId>org.springframework.cloudgroupId>
	      <artifactId>spring-cloud-config-serverartifactId>
	    dependency>
	dependencies>
	
	<dependencyManagement>
	<dependencies>
			<dependency>
				<groupId>org.springframework.cloudgroupId>
				<artifactId>spring-cloud-dependenciesartifactId>
				<version>${spring-cloud.version}version>
				<type>pomtype>
				<scope>importscope>
			dependency>
		dependencies>
	dependencyManagement>

2.修改全局配置文件 application.yml
注意在使用时, 应用名(spring.application.name)不能与Eureka注册中心的其他服务的应用名相同 ,否则会访问不到码云上的配置文件

spring:
  application:
    name: config-server-Git  
  cloud:
    config:
      server:
        git:    #Git 配置 
          uri: https://gitee.com/TimePause/SpringCloudConfig   #码云仓库url
          username:       #码云账号
          password:       #码云密码
        
    
    
server:
  port: 9090

eureka:
  client:
    serviceUrl:
      defaultZone:    #Eureka注册中心地址

3.创建4个临时配置文件 ,然后上传到码云仓库中 ,再把项目中的这些临时配置文件移除
Spring全家桶之SpringCloud——高级阶段(中)_第27张图片

4 .编写启动类并启动
主要添加了 @EnableConfigServer注解

@SpringBootApplication
@EnableEurekaClient
@EnableConfigServer
public class Application {
	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

测试结果
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

配置中心配置文件的命名与访问规则

Spring全家桶之SpringCloud——高级阶段(中)_第28张图片

注意 :
application为即将对其配置的服务的服务名
主干访问正常访问 ,分支访问需要加上分支的名称

创建配置中心Client端

1.复制上个项目 ,修改pom文件
将原来配置中心的server的坐标换成client的坐标


		<dependency>
		  <groupId>org.springframework.cloudgroupId>
		  <artifactId>spring-cloud-starter-configartifactId>
		dependency>

2.修改启动类
去掉了config-server所使用的注解 @EnableConfigServer

@SpringBootApplication
@EnableEurekaClient
public class ConfigClientApplication {
	public static void main(String[] args) {
		SpringApplication.run(ConfigClientApplication.class, args);
	}
}

3.修改全局配置文件 bootstrap.yml
因为配置了配置中心,配置文件从配置中心读取,不能再使用applocation.properties/yml,配置项目名,端口号注册中心等 .
必须在本地配置,所以这里使用优先级比application.properties/yml高的bootstrap.properties/yml文件。

spring:
  application:
    name: config-client
  cloud:
    config:
      discovery:
        service-id: config-server-Git    #config-server的服务名
        enabled: true    #开关
      profile: dev    #使用什么环境 test/dev/prod/default
      label: master    #git标签
        

server:
  port: 9091   #服务启动端口

eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/

bootstrap与application的区别

Spring全家桶之SpringCloud——高级阶段(中)_第29张图片

4.编写一个controller ,去访问码云中的配置文件config-client-dev.properties
获取哪个配置文件根据 bootstrap.yml配置
通过@value注解+el表达式获取相关配置文件的具体的值

@Controller
public class showMsgController {
	
	@Value("${E-Book}")
	private String msg;
	
	@RequestMapping("showMsg")
	@ResponseBody
	public String showMsg() {
		
		return msg;
	}
}

测试结果
码云中Spring全家桶之SpringCloud——高级阶段(中)_第30张图片

浏览器中,注册中心截图省略
Spring全家桶之SpringCloud——高级阶段(中)_第31张图片

三、在 git 端修改配置后,在不重启服务中如何让客户端生效

Spring全家桶之SpringCloud——高级阶段(中)_第32张图片
当我们修改git端配置文件是需要重新启动项目才能重新加载配置文件。当然这样在实际生产中是不好。
在config-server中,每一次client请求时都会去git端同步版本,所以不需要从重启server端,只需要重启client端。
我们通过actuator中的/refresh完成client的重启操作。

1.修改配置中心Client端pom文件 (被同步数据的一端)

添加actuator的坐标

	<dependencies>
		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-devtoolsartifactId>
			
			<optional>trueoptional>
		dependency>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
		dependency>
		
		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
		dependency>
		
		<dependency>
		  <groupId>org.springframework.cloudgroupId>
		  <artifactId>spring-cloud-starter-netflix-zuulartifactId>
		dependency>
		
		<dependency>
		  <groupId>org.springframework.cloudgroupId>
		  <artifactId>spring-cloud-starter-configartifactId>
		dependency>
		
		
		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-actuatorartifactId>
		dependency>
	dependencies>

2.修改其全局配置文件 bootbootstrap.yml

spring:
  application:
    name: config-client
  cloud:
    config:
      discovery:
        service-id: config-server-Git    #config-server的服务名
        enabled: true    #开关
      profile: dev    #使用什么环境 test/dev/prod/default
      label: master    #git标签
        

server:
  port: 9091

eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/

management:
# 2.0之前需要关闭防护
  #security:
   # enable: false
  endpoints:
    web:
      exposure:
        include: refresh

3.启动类

@SpringBootApplication
@EnableEurekaClient
public class ConfigClientApplication {
	public static void main(String[] args) {
		SpringApplication.run(ConfigClientApplication.class, args);
	}
}

4.控制层
在springioc容器中,bean为单例模式/原型模式,
其值配注入后不会改变,刷新后也不会变化,需要@RefreshScope注解刷新属性

/**
 *在springioc容器中,bean为单例模式,其值配注入后不会改变,刷新后也不会变化,需要@RefreshScope注解刷新属性
 * @author chy
 *
 */
@Controller
@RefreshScope
public class showMsgController {
	
	@Value("${E-Book}")
	private String msg;
	
	@RequestMapping("showMsg")
	@ResponseBody
	public String showMsg() {
		
		return msg;
	}
}

5.启动server、启动client,修改git端数据使其数据改变,
例如修改上面代码中msg引用的值
Spring全家桶之SpringCloud——高级阶段(中)_第33张图片

cmd命令刷新git上的配置文件: curl -X POST http://localhost:服务的端口号/actuator/refresh

6.进入Windows命令行 , 使用 curl -X POST http://localhost:服务的端口号/actuator/refresh 刷新client
在刷新之前,可以先清除配置中心客户端的控制台 ,待输出如下数据说明刷新/重启数据完毕

在这里插入图片描述
Spring全家桶之SpringCloud——高级阶段(中)_第34张图片
7. 注意

  1. /refresh请求必须post方式,可以通过java程序发送post请求(HTTPClient工具类),也可以通过命令行curl发送。
  2. 对于@value注入的属性不能通过刷新重新加载,需要在该类上添加@RefreshScope注解。
  3. 2.0版本以前需要设置management.security.enabled=false ,2.0版本以后需要在配置中放开refresh

测试结果
Spring全家桶之SpringCloud——高级阶段(中)_第35张图片

四、 安全与加密

对于一些配置文件中的内容不宜明文显示,需要进行加密处理

  1. 对称加密介绍
    对称加密是最快速、最简单的一种加密方式,加密(encryption)与解密(decryption)用的是同样的密钥(secret key)。

  2. 检查加密环境 http://127.0.0.1:配置中心服务端端口号/encrypt/status

    检查结果:
    出现下列结果需要为加密服务安装密钥。

      {"description":"No key was installed for encryption service","status":"NO_KEY"}2.0版本以前)
      {"description":"The encryption algorithm is not strong enough","status":"INVALID"}2.0版本以后)
    
  3. 设置加密环境
    步骤
    1.设置秘钥 KEY
    (必须在bootstrap.properties/yml文件中

    encrypt:
      key: chy  #配置加密环境的秘钥
    

    2.未配置 JCE
    http://www.oracle.com/technetwork/java/javase/downloads/jce8-download-2133166.html
    下载解压后,把 jar 文件上传到需要安装 jce 机器上 JDK 或 JRE 的 security 目录下,覆盖源文件 即可。
    JDK:将两个 jar 文件放到%JDK_HOME%\jre\lib\security 下
    JRE:将两个 jar 文件放到%JRE_HOME%\lib\security 下

    3.spring cloud bug
    Dalston.SR4、Dalston.SR3、Dalston.SR2 版本不能对配置文件加密,若需要调整到 Dalston.SR1
    https://github.com/spring-cloud/spring-cloud-config/issues/767

    如果使用官网生成的2.17版本的SpringBoot项目,则无需修改第3步,pom文件如下

    
    	<properties>
    		<java.version>1.8java.version>
    		<spring-cloud.version>Greenwich.SR2spring-cloud.version>
    		<maven-jar-plugin.version>2.6maven-jar-plugin.version>
    	properties>
    
    <dependencyManagement>
    <dependencies>
    		<dependency>
    			<groupId>org.springframework.cloudgroupId>
    			<artifactId>spring-cloud-dependenciesartifactId>
    			<version>${spring-cloud.version}version>
    			<type>pomtype>
    			<scope>importscope>
    		dependency>
    	dependencies>
    dependencyManagement>
    
  4. 设置后检查设置结果
    在这里插入图片描述

  5. 加密演示
    加密(post 请求):http://ip:port/encrypt
    解密(post 请求):http://ip:port/decrypt
    通过Postman工具发送post请求

使用对称加密算法 ,实现敏感数据加密

1.创建配置中心服务端

主要添加的坐标


		<dependency>
	      <groupId>org.springframework.cloudgroupId>
	      <artifactId>spring-cloud-config-serverartifactId>
	    dependency>

配置文件 bootstrap.yml

spring:
  application:
    name: config-server-encryption-sym 
  cloud:
    config:
      server:
        git:    #Git 配置 
          uri: https://gitee.com/TimePause/SpringCloudConfig    #码云/git仓库地址
          username: 账号
          password: 密码
          skip-ssl-validation: true #解决Cannot clone or checkout repository 的问题
          
server:
  port: 9999

eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/

encrypt:
  key: chy  #配置加密环境的秘钥

2.使用HTTPClient向数据加密的服务中心配置发送命令,对数据进行加密

环境搭建

  1. 创建SpringCloud项目,修改pom文件

    <parent>
    		<groupId>org.springframework.bootgroupId>
    		<artifactId>spring-boot-starter-parentartifactId>
    		<version>2.1.7.RELEASEversion>
    	parent>
    
    
    	<properties>
    		<java.version>1.8java.version>
    		<spring-cloud.version>Greenwich.SR2spring-cloud.version>
    		<maven-jar-plugin.version>2.6maven-jar-plugin.version>
    	properties>
    	<dependencies>
    		<dependency>
    			<groupId>org.springframework.bootgroupId>
    			<artifactId>spring-boot-starter-webartifactId>
    		dependency>
    		<dependency>
    			<groupId>org.apache.httpcomponentsgroupId>
    			<artifactId>httpclientartifactId>
    		dependency>
    		
    		<dependency>
    			<groupId>commons-logginggroupId>
    			<artifactId>commons-loggingartifactId>
    			<version>1.2version>
    		dependency>
    	dependencies>
    
    	<dependencyManagement>
    		<dependencies>
    			<dependency>
    				<groupId>org.springframework.cloudgroupId>
    				<artifactId>spring-cloud-dependenciesartifactId>
    				<version>${spring-cloud.version}version>
    				<type>pomtype>
    				<scope>importscope>
    			dependency>
    		dependencies>
    	dependencyManagement>
    
  2. 创建HTTPClient工具类,向其中发送需要加密的信息

    数据加密的服务中心配置发送请求
    a. 例如发送一个需要加密字符串 “root”
    返回一个加密的字符串 “baa42d01c077be2d26c7511d97845cf341427e7e9aefb726e941df7866816128”
    b. 然后重新发送解密字符串 “baa42d01c077be2d26c7511d97845cf341427e7e9aefb726e941df7866816128”
    验证是否返回root

    import java.io.IOException;
    import java.net.URI;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.http.NameValuePair;
    import org.apache.http.client.entity.UrlEncodedFormEntity;
    import org.apache.http.client.methods.CloseableHttpResponse;
    import org.apache.http.client.methods.HttpGet;
    import org.apache.http.client.methods.HttpPost;
    import org.apache.http.client.utils.URIBuilder;
    import org.apache.http.entity.ContentType;
    import org.apache.http.entity.StringEntity;
    import org.apache.http.impl.client.CloseableHttpClient;
    import org.apache.http.impl.client.HttpClients;
    import org.apache.http.message.BasicNameValuePair;
    import org.apache.http.util.EntityUtils;
    
    public class HttpClientUtil {
    
    	public static String doGet(String url, Map<String, String> param) {
    
    		// 创建Httpclient对象
    		CloseableHttpClient httpclient = HttpClients.createDefault();
    
    		String resultString = "";
    		CloseableHttpResponse response = null;
    		try {
    			// 创建uri
    			URIBuilder builder = new URIBuilder(url);
    			if (param != null) {
    				for (String key : param.keySet()) {
    					builder.addParameter(key, param.get(key));
    				}
    			}
    			URI uri = builder.build();
    
    			// 创建http GET请求
    			HttpGet httpGet = new HttpGet(uri);
    
    			// 执行请求
    			response = httpclient.execute(httpGet);
    			// 判断返回状态是否为200
    			if (response.getStatusLine().getStatusCode() == 200) {
    				resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
    			}
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				if (response != null) {
    					response.close();
    				}
    				httpclient.close();
    			} catch (IOException e) {
    				e.printStackTrace();
    			}
    		}
    		return resultString;
    	}
    
    	public static String doGet(String url) {
    		return doGet(url, null);
    	}
    
    	public static String doPost(String url, Map<String, String> param) {
    		// 创建Httpclient对象
    		CloseableHttpClient httpClient = HttpClients.createDefault();
    		CloseableHttpResponse response = null;
    		String resultString = "";
    		try {
    			// 创建Http Post请求
    			HttpPost httpPost = new HttpPost(url);
    			// 创建参数列表
    			if (param != null) {
    				List<NameValuePair> paramList = new ArrayList<>();
    				for (String key : param.keySet()) {
    					paramList.add(new BasicNameValuePair(key, param.get(key)));
    				}
    				// 模拟表单
    				UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList,"utf-8");
    				httpPost.setEntity(entity);
    			}
    			// 执行http请求
    			response = httpClient.execute(httpPost);
    			resultString = EntityUtils.toString(response.getEntity(), "utf-8");
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				response.close();
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    
    		return resultString;
    	}
    
    	public static String doPost(String url) {
    		return doPost(url, null);
    	}
    	
    	public static String doPostJson(String url, String json) {
    		// 创建Httpclient对象
    		CloseableHttpClient httpClient = HttpClients.createDefault();
    		CloseableHttpResponse response = null;
    		String resultString = "";
    		try {
    			// 创建Http Post请求
    			HttpPost httpPost = new HttpPost(url);
    			// 创建请求内容
    			StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
    			httpPost.setEntity(entity);
    			// 执行http请求
    			response = httpClient.execute(httpPost);
    			resultString = EntityUtils.toString(response.getEntity(), "utf-8");
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			try {
    				response.close();
    			} catch (IOException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    		}
    
    		return resultString;
    	}
    	
    	public static void main(String[] args) {
    		//刷新服务请求
    		//String url ="http://localhost:9091/actuator/refresh";
    		//加密请求
    		//String url ="http://localhost:9999/encrypt";//baa42d01c077be2d26c7511d97845cf341427e7e9aefb726e941df7866816128
    		//解密请求
    		String url ="http://localhost:9999/decrypt";
    		
    		//该url必须要使用dopost方式来发送
    		//加密
    		//String doPostJson = HttpClientUtil.doPostJson(url, "root");
    	    //解密
    		String doPostJson = HttpClientUtil.doPostJson(url, "baa42d01c077be2d26c7511d97845cf341427e7e9aefb726e941df7866816128");
    	    System.out.println(doPostJson);
    	}
    }
    		
    

3.配置中心客户端(E-Book-Product-Provider)

主需要额外添加的坐标


		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-starter-configartifactId>
		dependency>

bootstrap.yml
保留的参数 应用名,端口号,不重启服务刷新配置文件的配置 , 注册中心配置

spring:
  application:
    name: config-E-Book-Product-Provider
  #配置中心服务端的连接信息  
  cloud:
    config:
      discovery:
        service-id: config-server-encryption-sym    #configserver的服务名
        enabled: true    #开关
      label: master    #git标签
server:
  port: 8001
management:
  endpoints:
    web:
      exposure:
        include: refresh
eureka:
  instance:
    prefer-ip-address: true
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/

注意:
配置refresh属性后并且添加actuator的坐标,以后在码云中更改配置文件后在服务中生效
只需要在命令行输入 curl -X POST http://localhost:8001这个服务端口号/actuator/refresh
例如: curl -X POST http://localhost:8001/actuator/refresh

4.需要将数据库的相关配置/下面代码上传至配置中心(码云/git)

在比较长的字符串的前后最好加上单引号,不然可能会报错,
这里推荐url,加密后的用户名和密码的前后需要加上单引号
注册中心的文件不能放到配置中心/码云上 ,这是我们区分是否将配置文件上传的一个依据

spring:
  datasource:
    driverClassName: com.mysql.cj.jdbc.Driver
    url:  'jdbc:mysql://localhost:3306/book-product?useUnicode=true&characterEncoding=gbk&useJDBCCompliantTimezoneShift=true&serverTimezone=UTC'
    username: '{cipher}baa42d01c077be2d26c7511d97845cf341427e7e9aefb726e941df7866816128'
    password: '{cipher}baa42d01c077be2d26c7511d97845cf341427e7e9aefb726e941df7866816128'
    type: com.alibaba.druid.pool.DruidDataSource

  
server:
  compression:   #springboot的gzip配置
    enabled: true   #是否启用压缩  
    mime-types:    #配置压缩支持的 MIME TYPE
    - application/json,application/ xml,text/html,text/xml,text/plain
    
mybatis:
  type-aliases-package: ah.szxy.product.pojo
  mapper-locations:
  - classpath:ah/szxy/product/mapper/*.xml 

Spring全家桶之SpringCloud——高级阶段(中)_第36张图片

5.通过配置中心服务端访问码云上的配置文件,查看是否显示解密后的数据

在这里插入图片描述

6.出现上图后 ,启动被提供加密服务(E-Book-Product-Provider) ,访问相关的方法,查看联网的配置是否可用

在这里插入图片描述

注意 :
a.将需要加密的数据进行通过config-server加密(每次加密结果不一样,但都能解密出相同的结果)
b.在密码前需要加上{cipher},这样config-server才能解密出明文密码。

使用非对称加密算法 ,实现敏感数据加密

非对称加密介绍
Spring全家桶之SpringCloud——高级阶段(中)_第37张图片

Java-keytool 使用说明

  1. Keytool 介绍
    Keytool 是一个 Java 数据证书的管理工具 。 它的作用是帮助配置服务实现64位非对称秘钥的生成
    Keytool 将密钥(key)和证书(certificates)存在一个称为 keystore 的文件中。
    keystore 文件,包含两种数据:密钥实体(Key entity)-密钥(secret key)或者是私钥和配对公钥(采用非对称加密)可信任的证书实体(trusted certificate entries)-只包含公钥.
    位于JAVA_HOME/jdk/bin/keytool.exe

  2. 使用keytool创建证书
    使用有管理员权限的命令行,在keytool.exe目录 shift+鼠标右键 打开power shell(或使用cmd跳转到该目录)
    后执行 keytool -genkeypair -alias "test1" -keyalg "RSA" -keystore "test.keystore"
    keytool -genkey -alias andro eyalg RSA -validity 30000 -keystore

    Spring全家桶之SpringCloud——高级阶段(中)_第38张图片

    Spring全家桶之SpringCloud——高级阶段(中)_第39张图片

    生成的test.keystire文件位于JAVA_HOME/jdk/bin/。

    Spring全家桶之SpringCloud——高级阶段(中)_第40张图片

使用非对称加密算法实现配置文件加密与解密
前提 : 需要有keytool创建的证书

1.配置中心服务端

pom文件如下


<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0modelVersion>
	<parent>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring-boot-starter-parentartifactId>
		<version>2.1.7.RELEASEversion>
		<relativePath /> 
	parent>
	<groupId>ah.szxy.springcloudgroupId>
	<version>0.0.1-SNAPSHOTversion>
	<description>Demo project for Spring Bootdescription>

	<properties>
		<java.version>1.8java.version>
		<spring-cloud.version>Greenwich.SR2spring-cloud.version>
		<maven-jar-plugin.version>2.6maven-jar-plugin.version>
	properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
		dependency>
		
		<dependency>
	      <groupId>org.springframework.cloudgroupId>
	      <artifactId>spring-cloud-config-serverartifactId>
	    dependency>
		
		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
		dependency>
	dependencies>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloudgroupId>
				<artifactId>spring-cloud-dependenciesartifactId>
				<version>${spring-cloud.version}version>
				<type>pomtype>
				<scope>importscope>
			dependency>
		dependencies>
	dependencyManagement>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.bootgroupId>
				<artifactId>spring-boot-maven-pluginartifactId>
			plugin>
		plugins>
	build>

	<name>Config-Server-Encryptionname>
	<artifactId>Config-Server-EncryptionartifactId>
project>

修改配置文件 bootstrap.yml

spring:
  application:
    name: config-server-rsa-sym
  cloud:
    config:
      server:
        git:    #Git 配置 
          uri: https://gitee.com/TimePause/SpringCloudConfig
          username: 码云账号
          password: 码云密码
          skip-ssl-validation: true #解决Cannot clone or checkout repository 的问题
          
server:
  port: 9999

eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/
      
#使用非对称加密
#keytool -genkeypair -alias "config-info" -keyalg "RSA" -keystore "encrypt-info.keystore"
encrypt:
  key-store:
  # keystore 文件的路径 
    location: classpath:encrypt-info.keystore
    # alias 指定密钥对的别名,该别名是公开的; 
    alias: config-info
    # storepass 密钥仓库 
    password: caohaiyang
    # keypass 用来保护所生成密钥对中的私钥 
    secret: caohaiyang   

将2.2生成好的加密文件放到src目录下

Spring全家桶之SpringCloud——高级阶段(中)_第41张图片
创建启动类,然后启动

@SpringBootApplication
@EnableConfigServer
@EnableEurekaClient
public class Application {

	public static void main(String[] args) {
		SpringApplication.run(Application.class, args);
	}
}

2.使用对称加密使用到的HTTPClient工具类向生成秘钥的项目发送请求

对相关数据进行加密(如数据库的用户名和密码)
得到的是一个64位的字符串

3.创使用非对称加密的项目( config-E-Book-Product-Provider-RSA )

复制对称加密使用的项目,修改其全局配置文件 bootstrap

spring:
  application:
    name: config-E-Book-Product-Provider-RSA
  #配置中心服务端的连接信息  
  cloud:
    config:
      discovery:
        service-id: config-server-rsa-sym    #configs-erver的服务名
        enabled: true    #开关
      label: master    #git标签
server:
  port: 8011
management:
  endpoints:
    web:
      exposure:
        include: refresh
eureka:
  instance:
    prefer-ip-address: true
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/

4.在码云上创建 config-E-Book-Product-Provider-RSA.yml文件 ,修改其内容

文件名称是依据 bootstrap中服务的应用名而起的

Spring全家桶之SpringCloud——高级阶段(中)_第42张图片

5.通过生成秘钥的服务中心访问创建好的配置文件

这里可以看到密码已经被解密
在这里插入图片描述
注意:本次模拟主要是对数据库的用户名和密码进行的加密

6.访问被加密的项目,发现可以正常运行

在这里插入图片描述

配置中心的用户安全认证

以非对称加密为例 ,对称加密安全认证同上

配置中心服务端

添加security坐标

		
		<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-securityartifactId>
		dependency>	
<dependency>
			<groupId>org.springframework.bootgroupId>
			<artifactId>spring-boot-starter-webartifactId>
		dependency>
		
		<dependency>
	      <groupId>org.springframework.cloudgroupId>
	      <artifactId>spring-cloud-config-serverartifactId>
	    dependency>
		
		<dependency>
			<groupId>org.springframework.cloudgroupId>
			<artifactId>spring-cloud-starter-netflix-eureka-clientartifactId>
		dependency>	

修改全局配置文件

spring:
  application:
    name: config-server-rsa-sym-security
  cloud:
    config:
      server:
        git:    #Git 配置 
          uri: https://gitee.com/TimePause/SpringCloudConfig
          username: 码云账号
          password: 码云密码
          skip-ssl-validation: true #解决Cannot clone or checkout repository 的问题
  # 安全认证
  #开启基于 http basic 的安全认证
  security:
    user:  
      name: root
      password: root    
          
          
server:
  port: 9999

eureka:
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/
      
#使用非对称加密
#keytool -genkeypair -alias "config-info" -keyalg "RSA" -keystore "encrypt-info.keystore"
encrypt:
  key-store:
  # keystore 文件的路径 
    location: classpath:encrypt-info.keystore
    # alias 指定密钥对的别名,该别名是公开的; 
    alias: config-info
    # storepass 密钥仓库 
    password: caohaiyang
    # keypass 用来保护所生成密钥对中的私钥 
    secret: caohaiyang      

再次通过[配置中心服务端访问码云上的配置文件时,需要输入配置文件设置的用户名和密码才能访问
Spring全家桶之SpringCloud——高级阶段(中)_第43张图片

配置中心客户端

pom文件无需修改,但是如果直接访问,会出现如下错误:在这里插入图片描述
解决方式:
在全局配置文件中添加安全认证的用户名密码
Spring全家桶之SpringCloud——高级阶段(中)_第44张图片

spring:
  application:
    name: config-E-Book-Product-Provider-RSA
  #配置中心服务端的连接信息  
  cloud:
    config:
      discovery:
        service-id: config-server-rsa-sym-security    #configs-erver的服务名
        enabled: true    #开关
      label: master    #git标签
      username: root
      password: root
      
server:
  port: 8011
  
management:
  endpoints:
    web:
      exposure:
        include: refresh
eureka:
  instance:
    prefer-ip-address: true
  client:
    serviceUrl:
      defaultZone: http://admin:admin@eureka1:8761/eureka/,http://admin:admin@eureka2:8761/eureka/

测试结果
在这里插入图片描述

你可能感兴趣的:(JAVA小窝(笔记),Spring技术)