1.Spring模块
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.coco</groupId>
<artifactId>springcloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<modules>
<!-- 模块只管pojo-->
<module>springcloud-api</module>
<module>springcloud-provider-dept-8001</module>
<module>springcloud-consumer-dept-80</module>
<module>springcloud-eureka-7001</module>
<module>springcloud-zuui-9527</module>
<module>vue</module>
</modules>
<packaging>pom</packaging>
<properties>
<java.version>1.8</java.version>
<junit.version>4.12</junit.version>
<lombok.version>1.18.24</lombok.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>2021.0.4</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.7.3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.13-SNSAPSHOT</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
2.api模块-只负责pojo
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<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">
<parent>
<artifactId>springcloud</artifactId>
<groupId>com.coco</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-api</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- 父依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- 自己的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
</dependencies>
</project>
编写pojo类
package com.coco.springcloud.pojo;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Accessors(chain = true)
@Getter
@Setter
@ToString
@NoArgsConstructor
public class Dept implements Serializable {
private long deptno;
private String dname;
private String db_source;
}
3.服务提供者
application.yml
server:
port: 8001
mybatis:
type-aliases-package: com.coco.springcloud.pojo
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
spring:
application:
name: springcloud-provider-TiGongZhe
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/corainld?useUnicode=true&characterEncoding=utf-8
username: root
password: 123456
编写mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
</settings>
</configuration>
编写dao层
package com.coco.springcloud.dao;
import com.coco.springcloud.pojo.Dept;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
import java.util.List;
@Mapper
@Repository
public interface DeptDao {
public boolean addDept(Dept dept);
public Dept queryById(Long id);
public List<Dept> queryAll();
}
编写service层
package com.coco.springcloud.service;
import com.coco.springcloud.pojo.Dept;
import java.util.List;
public interface DeptService {
public boolean addDept(Dept dept);
public Dept queryById(Long id);
public List<Dept> queryAll();
}
package com.coco.springcloud.service;
import com.coco.springcloud.dao.DeptDao;
import com.coco.springcloud.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class DeptServiceImpl implements DeptService{
@Autowired
private DeptDao deptDao;
@Override
public boolean addDept(Dept dept) {
return deptDao.addDept(dept);
}
@Override
public Dept queryById(Long id) {
return deptDao.queryById(id);
}
@Override
public List<Dept> queryAll() {
return deptDao.queryAll();
}
}
编写mapper
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.coco.springcloud.dao.DeptDao">
<insert id="addDept" parameterType="Dept">
insert into dept (dname, db_source)
values (#{dname}, DATANASE());
</insert>
<select id="queryById" resultType="Dept" parameterType="Long">
select * from dept where deptno = #{deptno}
</select>
<select id="queryAll" resultType="Dept">
select * from dept
</select>
</mapper>
编写controller层
package com.coco.springcloud.controller;
import com.coco.springcloud.pojo.Dept;
import com.coco.springcloud.service.DeptService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@Autowired
private DiscoveryClient discoveryClient;
@PostMapping("/dept/add")
public boolean addDept(Dept dept) {
return deptService.addDept(dept);
}
@HystrixCommand(fallbackMethod = "hystrixGet")
@GetMapping("/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
Dept dept = deptService.queryById(id);
System.out.println(dept);
if (dept == null) {
throw new RuntimeException("id=>" + id + ", 不存在该用户");
}
return dept;
}
public Dept hystrixGet(@PathVariable("id") Long id) {
return new Dept().setDeptno(id).setDname("id=>" + id + ", 不存在该用户").setDb_source("no Databased");
}
@GetMapping("/dept/list")
public List<Dept> queryAll() {
return deptService.queryAll();
}
@GetMapping("dept/discovery")
public Object discovery() {
//获取微服务名单
List<String> services = discoveryClient.getServices();
System.out.println("服务清单:" + services);
List<ServiceInstance> instances = discoveryClient.getInstances("springcloud-provider提供者");
instances.forEach(x->{
System.out.println(x.getHost());
System.out.println(x.getPort());
System.out.println(x.getUri());
System.out.println(x.getServiceId());
});
return this.discoveryClient;
}
}
编写启动类,启动访问:http://localhost:8001/dept/list
package com.coco.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableHystrix
public class DeptProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001.class, args);
}
}
3.服务消费者-远程调用
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<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">
<parent>
<artifactId>springcloud</artifactId>
<groupId>com.coco</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-consumer-dept-80</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.coco</groupId>
<artifactId>springcloud-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-loadbalancer</artifactId>
<version>2.3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-ribbon</artifactId>
<version>2.2.10.RELEASE</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 80
注册一个restTemplate bean注入到controller层
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ConfigBean {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public IRule myrule() {
return new RandomRule();
}
}
编写controller层
package com.coco.springcloud.controller;
import com.coco.springcloud.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@RestController
public class DeptConsumerController {
//消费者不该有service
//RestTemplate供直接调用
//public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)
//通过configBean注入
@Autowired
private RestTemplate restTemplate;
// private static final String Rest_url_prefix = "http://localhost:8001";
private static final String Rest_url_prefix = "http://SPRINGCLOUD-PROVIDER-TIGONGZHE";
@GetMapping("/consumer/get/{id}")
public Dept get(@PathVariable("id") Long id) {
// Dept dept = deptService.queryById(id);
Dept dept = restTemplate.getForObject(Rest_url_prefix + "/dept/get/" + id, Dept.class);
System.out.println(dept);
return dept;
}
@GetMapping("/consumer/list")
public List<Dept> queryAll() {
return restTemplate.getForObject(Rest_url_prefix + "/dept/list", List.class);
}
@PostMapping("/consumer/add")
public boolean addDept(Dept dept) {
return restTemplate.postForObject(Rest_url_prefix + "/dept/add", dept, boolean.class);
}
}
编写启动类,启动访问:http://localhost/consumer/list
package com.coco.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
@SpringBootApplication
@EnableEurekaClient
@RibbonClient
public class DeptConsumer_80 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_80.class, args);
}
}
4.将远程注册中心从zookeeper变成Eureka,舍弃一致性,实现可用性
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<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">
<parent>
<artifactId>springcloud</artifactId>
<groupId>com.coco</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-eureka-7001</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 7001
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false #是否向eureka注册中心注册自己
fetch-registry: false #false表示自己为注册中心
service-url: #与注册中心交互
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
#http://127.0.0.1:7002/eureka/,http://127.0.0.1:7003/eureka/
#this.serviceUrl.put("defaultZone", "http://localhost:8761/eureka/");
编写启动类,启动访问:http://localhost:7001/
package com.coco.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer //表示为服务端的启动类,可以接受别人注册进来
public class Eureka_7001 {
public static void main(String[] args) {
SpringApplication.run(Eureka_7001.class, args);
}
}
服务提供者配置注册中心地址
pom中增加依赖
<!--服务提供者配置Eureka注册中心依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<!--Eureka界面上的status监控描述依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
application.yml中增加配置
#服务端配置Eureka注册中心地址
eureka:
client:
service-url:
defaultZone: http://localhost:7001/eureka/,http://localhost:7002/eureka/,http://localhost:7003/eureka/
instance:
instance-id: spri-pro-8001 #status描述信息
prefer-ip-address: true #隐藏ip
info:
app.name: 监控信息 #点击status进入
company.name: 996
management:
endpoints:
web:
exposure:
include: "*"
info:
env:
enabled: true
启动类中添加注解
@EnableEurekaClient //添加后服务启动时自动注册进Eureka中
@EnableDiscoveryClient//向controller中注册discovery获取配置信息
获取配置方法
//获取一些配置信息
@Autowired
private DiscoveryClient discoveryClient;
@GetMapping("dept/discovery")
public Object discovery() {
//获取微服务名单
List<String> services = discoveryClient.getServices();
System.out.println("服务清单:" + services);
List<ServiceInstance> instances = discoveryClient.getInstances("springcloud-provider-TiGongZhe");
instances.forEach(x->{
System.out.println(x.getHost());
System.out.println(x.getPort());
System.out.println(x.getUri());
System.out.println(x.getServiceId());
});
return this.discoveryClient;
}
添加集群,将defaultZone从单机改为集群
server:
port: 7001
eureka:
instance:
hostname: eureka7001.com
client:
register-with-eureka: false #是否向eureka注册中心注册自己
fetch-registry: false #false表示自己为注册中心
service-url: #与注册中心交互
defaultZone: http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
#单机:http://${eureka.instance.hostname}:${server.port}/eureka/
#默认:this.serviceUrl.put("defaultZone", "http://localhost:8761/eureka/");
服务提供者修改defaultZone
#服务端配置Eureka注册中心地址
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: status
prefer-ip-address: true #自我保护机制,不推荐关闭
服务消费者
添加Eureka依赖
<!--eureka配置-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
添加Eureka配置
server:
port: 80
eureka:
client:
register-with-eureka: false
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
启动类添加注解
@EnableEurekaClient
5.Ribbon-为服务客户端做一些简单的负载均衡:用某种规则为客户端平摊分配到多台服务器上,从而实现高可用
进程式负载均衡,将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选出一个合适的服务器
pom文件添加Ribbon依赖
<!--Ribbon配置-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-ribbon</artifactId>
<version>2.2.10.RELEASE</version>
<scope>compile</scope>
</dependency>
<!--负载均衡依赖-->
<dependency>
<groupId>com.netflix.ribbon</groupId>
<artifactId>ribbon-loadbalancer</artifactId>
<version>2.3.0</version>
<scope>compile</scope>
</dependency>
ConfigBean中添加Ribbon注解,并设置负载均衡规则
package com.coco.springcloud.config;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
@Configuration
public class ConfigBean {
@Bean
@LoadBalanced //开启负载均衡注解
public RestTemplate restTemplate() {
return new RestTemplate();
}
@Bean
public IRule myrule() {
return new RandomRule();
}
}
controller中将固定服务器地址修改为服务器名
package com.coco.springcloud.controller;
import com.coco.springcloud.pojo.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@RestController
public class DeptConsumerController {
//消费者不该有service
//RestTemplate供直接调用
//public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)
@Autowired
private RestTemplate restTemplate;
//无Ribbon通过固定地址请求
//private static final String Rest_url_prefix = "http://localhost:8001";
//有Ribbon通过服务名请求
private static final String Rest_url_prefix = "http://SPRINGCLOUD-PROVIDER-TIGONGZHE";
@GetMapping("/consumer/get/{id}")
public Dept get(@PathVariable("id") Long id) {
// Dept dept = deptService.queryById(id);
Dept dept = restTemplate.getForObject(Rest_url_prefix + "/dept/get/" + id, Dept.class);
System.out.println(dept);
return dept;
}
@GetMapping("/consumer/list")
public List<Dept> queryAll() {
return restTemplate.getForObject(Rest_url_prefix + "/dept/list", List.class);
}
@PostMapping("/consumer/add")
public boolean addDept(Dept dept) {
return restTemplate.postForObject(Rest_url_prefix + "/dept/add", dept, boolean.class);
}
}
启动并访问:http://localhost/consumer/list
自定义规则组件
package com.coco.springcloud.myrule;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class myRule {
@Bean
public IRule myrule() {
return new RandomRule();
}
}
启动类添加注解
@RibbonClient(name = "springcloud-provider-TiGongZhe",configuration = myRule.class)
6.Feign-通过创建接口并使用注解实现负载均衡
api中添加服务接口
package com.coco.springcloud.service;
import com.coco.springcloud.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
@Component
public interface DeptClientService {
@GetMapping("/dept/get/{id}")
Dept queryById(@PathVariable("id") Long id);
@GetMapping("/dept/list")
List<Dept> queryAll();
@PostMapping("/dept/add")
boolean addDept(Dept dept);
@GetMapping("/dept/json")
String js(String s);
}
服务客户端
pom文件添加Feign依赖
<!--Feign依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-feign</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
controller层添加注解实现接口
package com.coco.springcloud.controller;
import com.coco.springcloud.pojo.Dept;
import com.coco.springcloud.service.DeptClientService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import java.util.List;
@RestController
public class DeptConsumerController {
//不再通过restTemplate实现
@Autowired
private RestTemplate restTemplate;
//通过Feign实现
@Autowired
private DeptClientService deptClientService;
// private static final String Rest_url_prefix = "http://localhost:8001";
//加了ribbon后
// private static final String Rest_url_prefix = "http://SPRINGCLOUD-PROVIDER-TIGONGZHE";
@GetMapping("/consumer/get/{id}")
public Dept get(@PathVariable("id") Long id) {
// Dept dept = deptService.queryById(id);
// Dept dept = restTemplate.getForObject(Rest_url_prefix + "/dept/get/" + id, Dept.class);
return this.deptClientService.queryById(id);
}
@GetMapping("/consumer/list")
public List<Dept> queryAll() {
return this.deptClientService.queryAll();
}
@PostMapping("/consumer/add")
public boolean addDept(Dept dept) {
return this.deptClientService.addDept(dept);
}
@GetMapping("/consumer/js")
public String json(Dept dept) throws JsonProcessingException {
dept.setDeptno(1).setDname("111").setDb_source("cococo");
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(dept);
return str;
}
}
启动类添加注解
package com.coco.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.coco.springcloud"})
//@ComponentScan("com.coco.springcloud")
public class FeignDeptConsumer_feign {
public static void main(String[] args) {
SpringApplication.run(FeignDeptConsumer_feign.class, args);
}
}
7.Hystrix-服务熔断机制
服务客户端
pom文件添加hystrix依赖
<!--服务熔断依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
熔断备用方法
@HystrixCommand(fallbackMethod = "hystrixGet")
@GetMapping("/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
Dept dept = deptService.queryById(id);
System.out.println(dept);
if (dept == null) {
throw new RuntimeException("id=>" + id + ", 不存在该用户");
}
return dept;
}
//抛出异常后执行备选方案
public Dept hystrixGet(@PathVariable("id") Long id) {
return new Dept().setDeptno(id).setDname("id=>" + id + ", 不存在该用户").setDb_source("no Databased");
}
启动类添加hystrix注解
package com.coco.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
@SpringBootApplication
@EnableEurekaClient //添加后服务启动时自动注册进Eureka中
@EnableDiscoveryClient//向controller中注册discovery获取配置信息
@EnableHystrix//开启熔断
public class DeptProvider_8002 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8002.class, args);
}
}
服务降级
api中添加工厂类
package com.coco.springcloud.service;
import com.coco.springcloud.pojo.Dept;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
//服务降级,服务全部停止时批量处理熔断
@Component
public class DeptClientFallbackFactory implements FallbackFactory {
@Override
public DeptClientService create(Throwable cause) {
return new DeptClientService() {
@Override
public Dept queryById(Long id) {
return new Dept().setDeptno(id)
.setDname("没有对应信息,服务已经关闭")
.setDb_source("no database");
}
@Override
public List<Dept> queryAll() {
Dept dept = new Dept().setDname("all server down").setDb_source("null");
List a = new ArrayList();
a.add(dept);
return a;
}
@Override
public boolean addDept(Dept dept) {
return false;
}
@Override
public String js(String s) {
return null;
}
};
}
}
添加注解
package com.coco.springcloud.service;
import com.coco.springcloud.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER-TIGONGZHE", fallbackFactory = DeptClientFallbackFactory.class)
public interface DeptClientService {
@GetMapping("/dept/get/{id}")
Dept queryById(@PathVariable("id") Long id);
@GetMapping("/dept/list")
List<Dept> queryAll();
@PostMapping("/dept/add")
boolean addDept(Dept dept);
@GetMapping("/dept/json")
String js(String s);
}
8.HystrixDashboard-流监控
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<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">
<parent>
<artifactId>springcloud</artifactId>
<groupId>com.coco</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-consumer-dashboard</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.coco</groupId>
<artifactId>springcloud-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
<!--Eureka-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<!--Ribbon-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
<!--Hystrix-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
<!--Dashboard-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 9001
hystrix:
dashboard:
proxy-stream-allow-list: "*"
编写启动类,启动并访问:http://localhost:9001/hystrix
package com.coco.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@EnableHystrixDashboard
public class DeptConsumerDashboard_9001 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumerDashboard_9001.class, args);
}
}
服务提供者
编写流监控Servlet,开启熔断机制,并在控制类中具备熔断操作
package com.coco.springcloud;
import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@EnableEurekaClient //添加后服务启动时自动注册进Eureka中
@EnableDiscoveryClient//向controller中注册discovery获取配置信息
@EnableHystrix//开启熔断
public class DeptProvider_8002 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8002.class, args);
}
@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet() {
ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
registrationBean.addUrlMappings("/actuator/hystrix.stream");
return registrationBean;
}
}
package com.coco.springcloud.controller;
import com.coco.springcloud.pojo.Dept;
import com.coco.springcloud.service.DeptService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@PostMapping("/dept/add")
public boolean addDept(Dept dept) {
return deptService.addDept(dept);
}
@HystrixCommand(fallbackMethod = "hystrixGet")
@GetMapping("/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
Dept dept = deptService.queryById(id);
System.out.println(dept);
if (dept == null) {
throw new RuntimeException("id=>" + id + ", 不存在该用户");
}
return dept;
}
//抛出异常后执行备选方案
public Dept hystrixGet(@PathVariable("id") Long id) {
return new Dept().setDeptno(id).setDname("id=>" + id + ", 不存在该用户").setDb_source("FROM 8002");
}
@GetMapping("/dept/list")
public List<Dept> queryAll() {
return deptService.queryAll();
}
}
9.Zuul-路由网关,统一外部请求访问的地址
pom文件
<?xml version="1.0" encoding="UTF-8"?>
<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">
<parent>
<artifactId>springcloud</artifactId>
<groupId>com.coco</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-zuui-9527</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!--拿到实体类-->
<dependency>
<groupId>com.coco</groupId>
<artifactId>springcloud-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
<version>1.4.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-zuul</artifactId>
<version>2.2.10.RELEASE</version>
</dependency>
</dependencies>
</project>
application.yml
server:
port: 9527
spring:
application:
name: springcloud-zuul-gateway
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: spri-zuul-9527
prefer-ip-address: true
info:
app.name: Zuul网关
company.name: FROM 9527
management:
endpoints:
web:
exposure:
include: "*"
info:
env:
enabled: true
zuul:
routes:
mydept.serverId: springcloud-provider-TiGongZhe
mydept.path: /mydept/**
编写启动类,启动并访问:http://www.star.com:9527/springcloud-provider-tigongzhe/dept/list
package com.coco.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;
@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@EnableZuulProxy
public class ZuulApplication_9527 {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication_9527.class, args);
}
}