springCloud组件基本设置以及案例
SSM
dao层/service层/controller spring容器贯穿始终,所有的Bean,配置文件直接面向spring容器
业务层接口+实现类
传统ssm中: 业务层接口在Controller层@Autowired注入生成代理类对象
dubbo分布式中: 业务层接口注册到zookeeper 在Controller中@Reference注入 生成RPC代理类对象
dao层接口+mapper.xml(接口映射文件)
传统ssm中: dao层接口在业务层@Autowired注入生成代理类对象.
注意: 要求dao接口与映射文件mapper.xml同路径同名且反斜杠
springBoot中: dao层接口在业务层@Autowired注入, dao接口需要添加注解@Mapper / 启动类添加注解 @MapperScan("xx.xxx")接口包扫描
注意: 只要求接口与映射文件mapper.xml同名, 在yml中已经指定了路径
springBoot管理SSM
SpringBoot与MyBatis
步骤;
1 依赖启动器
MyBatis-spring-boot-starter
2 application.yml参数配置
JDBC连接池参数:
Mybatis参数:
# 数据库链接信息
spring
3 逆向工程生成3大件
4 dao接口类添加@Mapper 或者 启动类添加@MapperScan("cn.it.mapper") 接口包扫描
业务层@Autowired注入接口代理对象
5 编写mapper.xml接口映射文件,与接口同名 (因为在yml中有指定了路径,所以不需要像SSM一样与接口同路 径并且反斜杠)
SpringBoot与SpringMVC
步骤:
1 依赖启动器
spring-boot-starter-web
2 编写@Controller
SpringBoot与日志控制
日志输出原理:
debug级别: 输出debug / info / warn /error日志信息
info级别: 输出info / warn / error日志信息
warn级别: 输出warn / error日志信息
error级别: 输出error日志信息
步骤
1 添加lombok插件和依赖
2 application.yml配置
# 配置日志
logging
3 添加日志注解@Slf4j自动生成log对象
SpringBoot与拦截器
spring2.0 : 自定义拦截器 + xml配置文件
springBoot : 自定义拦截器 + 配置类
步骤:
1 自定义拦截器 实现接口HandlerInterceptor重写3大方法
public class loginInterceptot implements HandlerInterceptor {
//前置拦截 进入Controller前 返回值 : true放行 / false拦截
2 编写配置类实现WebMvcConfigurer接口 (记得添加@Configuration配置类注解)
springBoot管理分布式
springBoot管理微服务
微服务 = springBoot + 微服务组件
RestTemplate
spring-web自带了一个模板工具类RestTemplate实现原始的HTTP远程调用
步骤:
1 在启动类创建RestTemplate添加到spring容器
2 在测试类中@Autowired注入RestTemplate对象
3 <T> RestTemplate . getForObject("url", <T>.class)
<T> RestTemplate . postForObject("url", null, <T>.class)
用法:
1 RestTemplate+DiscoveryClient可以调用微服务Feign接口 (DiscoveryClient可以获取host/post)
详细 见: DiscoveryClient--API
2 RestTemplate直接调用Controller
案例: 1 简单的RestTemplate调用
2 springBoot下服务提供 ,服务消费
SpringBootAndRestTemplate
Feign
Feign封装了HTTP客户端(RestTemplate)到spring容器, 直接注入接口完成springCloud的服务远程调用
内部集成了Ribbon负载均衡(同一个服务ID,多个实例进行轮询)还进行了增强.(默认开启)
内部集成了Hystrix熔断 (默认关闭状态)
步骤:
1 添加组件依赖
spring-cloud-starter-openfeign
2 在启动类开启Feign客户端@EnableFeignClients
3 编写微服务接口 模拟出应用名: service-name微服务调用 http://service-name/user/6
4 在微服务调用处@Autowired注入接口服务, 自动生成接口代理类对象.
Feign对负载均衡进行了增强 --- 重试机制 (轮询到一个失效服务时会自动重试其他服务)
Feign默认关闭Hystrix熔断,(因为重试机制 不知道何时才能获取到服务)开启后提供降级策略. 降级方法一般在GetWay中处理
Eureka
非集群注册中心
步骤:
1 导入Eureka组件 spring-cloud-starter-netflix-eureka-server
2 配置注册中心application.yml
server:
port: 8761 # 应用端口号(默认8761)
spring:
application:
name: Eureka-Registry # 应用名称
eureka:
client:
# 点开源码 service-url是一个map集合,键值对代码在源码中有提示
service-url:
# 如果eureka高可用(集群),配置对方服务地址 如果不是集群则配置自己的地址
defaultZone: http://localhost:8761/eureka
fetch-registry: false #是否拉取其他注册服务(默认true)
register-with-eureka: true #是否将当前应用注册到Eureka(默认true)
3 启动类开启Eureka组件@EnableEurekaServer
案例: SpringCloudAndEureka
客户端(服务提供者)
步骤;
1 导入Eureka组件 spring-cloud-starter-netflix-eureka-client
2 启动类开启Eurka客户端 @EnableDiscoveryClient
3 配置application.yml
server:
port: 8001
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/springboot-db
username: root
password: root
application:
name: provider-8001 #应用名称
mybatis:
mapper-locations: mapper/UserMapper.xml #指定接口映射文件地址
type-aliases-package: cn.it.midea.dao.pojo.User #实体类别名包扫描
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka # 指定Eureka注册中心地址
案例: SpringCloudAndEureka 使用的RestTemplate方法调用微服务
客户端(服务消费者)
步骤:
1 添加组件 spring-cloud-starter-netflix-eureka-client
2 启动类开启Eureka客户端 @EnableDiscoveryClient
3 配置application.yml
server:
port: 8080
spring:
application:
name: consumer-8080 #应用名称
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka #指定Eureka注册中心地址
案例: SpringCloudAndEureka 使用的RestTemplate方法调用微服务
集群
注册中心集群:
核心: 集群ID相同且互相注册 (ID: spring.application.name)
步骤:
1 添加Eureka组件 spring-cloud-starter-netfilx-eureka-server
2 启动类开启Eureka @EnableEurekaServer
3 application.yml配置
server:
port: 8761 # 应用端口号(默认8761)
spring:
application:
name: Eureka-Registry # 集群中应用名称相同
eureka:
client:
service-url:
# url地址互相注册
defaultZone: http://localhost:8762/eureka,http://localhost:8763/eureka
fetch-registry: true #是否拉取其他注册服务(默认true,可以忽略不写)
register-with-eureka: true #是否将当前应用注册到Eureka(默认true,可以忽略不写)
案例: SpringCloudAndEurekaColony 通过Http客户端RestTemplate远程调用,没有经过Eureka
服务提供者集群
核心: 集群服务ID相同,并注册到注册中心集群的多个url中
步骤
1 添加组件 spring-cloud-starter-netflix-client
2 启动类开启客户端@EnabeDiscovertClient
3 application.yml
server:
port: 8002
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/springboot-db
username: root
password: root
application:
name: provider #多个提供者应用名称一致
mybatis:
mapper-locations: mapper/UserMapper.xml #指定接口映射文件地址
type-aliases-package: cn.it.midea.dao.pojo.User #实体类别名包扫描
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka,
http://localhost:8762/eureka,http://localhost:8763/eureka # 注册到集群中心的多个地址
案例: SpringCloudAndEurekaColony 通过Http客户端RestTemplate远程调用,没有经过Eureka
DiscoveryClient--API
来源 : org.springframework.cloud.client.discovery.DiscoveryClient
注解@EnableDiscoveryClient友情提供
作用: 协助RestTemplate 动态获取微服务URL
Controller--(RestTemplate+DiscoveryClient)-->微服务--(RestTemplate+DiscoveryClient)-->其他微服务
// 获取服务ID的所有实例的集合 实例可以有多个(相同的服务ID)以实现负载均衡
// serviceId就是yml中的spring.application.name: serviceId (注意方法中参数小写)
List<ServiceInstance> instances = discoveryClient.getInstances("provider-8001");
//从集合中获取第一个服务实例
ServiceInstance serviceInstance = instances.get(0);
//通过实例获取该实例的url的host port:
String host = serviceInstance.getHost();
int port = serviceInstance.getPort();
//再拼接上提供者的路径得到url
String url="http://"+ host +":"+ port +"provider/user/"+id;
return restTemplater.getForObject(url,User.class);
案例: SpringCloudAndEureka 使用的RestTemplate方法调用微服务
Eureka高级
以下案例出现在 SpringCloudAndEurekaColony项目中
服务端高级
服务下线
给注册中心发送Rest请求,通知服务下线
失效剔除
既没有定时续约发送心跳,也没有发送下线请求, 但是服务失效. 服务端会默认90秒后失效剔除
每隔60秒扫描一次, 超过90秒没有续约的失效服务剔除
eureka:
server:
eviction-interval-timer-in-ms: 900000 # 多久剔除,单位ms
自我保护
既没有定时续约发送心跳,也没有发送下线请求, 但是服务失效. 但是和失效剔除不同的是Eureka会统计服 务实例最近5main失效的比例是否在85%以内. 这段时间不会剔除任何服务,等待服务重新上线. 防止大 面积续约失败
eureka:
server:
enable-self-preservation: true # 开启自我保护(默认)
客户端高级(提供者)
指定服务提供者地址IP
Eureka会判断服务是否注册(eureka.client.register-with-eureka: true默认), 接着提供者会向 EurekaServer发送Rest信息(包含服务元数据信息), Eureka会将服务提供者信息保存进双层map集合
Map<String, Map<String, Object>>
外层map : String-->服务ID (spring.application.name)
内层map : String-->服务实例ID ( localhost : 服务ID : post) localhost:user-service:9001
Object-->服务实例集群 (再嵌套集群中其他实例)
修改内层map中的localhost改用IP代替, 方便指名服务所在服务器地址
eureka:
instance:
ip-address: 127.0.0.1
prefer-ip-address: true # 使ip地址生效
控制台效果 : url = http://127.0.0.1:8001provider/user/2
服务续约
服务提供者定时向服务注册中心发送心跳, 默认30秒发送一次心跳. 服务失效默认90秒.
eureka:
instance:
lease-renewal-interval-in-seconds: 30 # 服务续约(心跳)间隔时间
lease-expiration-duration-in-seconds: 90 # 服务失效时间(默认超过90秒的注册中心会失效剔除)
客户端高级(消费者)
定时拉取服务列表
服务消费者启动时判断 fetch-registry 是否为true. 如果是则会将注册中心服务列表缓存到消费者 (即 使关闭注册中心依然能获取服务的原因), 并且默认每隔30秒重新拉取一次
eureka:
client:
fetch-registry: true # 是否拉取服务列表 默认true
registry-fetch-interval-seconds: 30 # 服务消费者每隔30秒从注册中心拉取一次服务列表 默认30秒
Ribbon
步骤:
1 服务消费者添加Ribbon组件 Ribbon集成在了Eureka组件中
2 RestTemplate配置类添加注解@LoadBalanced
3 application.yml