SpringCloud入门手册

一.项目结构

1.搭建父工程

2.父工程继承springboot

<parent>
        <groupId> org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
    </parent>

3.父工程管理SpringCloud依赖

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR1</spring-cloud.version>
    </properties>

	<dependencyManagement>
	    <dependencies>
	        <dependency>
	            <groupId>org.springframework.cloud</groupId>
	            <artifactId>spring-cloud-dependencies</artifactId>
	            <version>${spring-cloud.version}</version>
	            <type>pom</type>
	            <scope>import</scope>
	        </dependency>
	    </dependencies>
    </dependencyManagement>

二.EurekaServer搭建

1.搭建子模块集成 父工程

<parent>
        <artifactId>springcloud</artifactId>
        <groupId>cn.xh</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>

2.导入依赖:eureks-server, web包

<dependency>
      	<groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

3.主配置类添加注解:

@SpringBootApplication
@EnableEurekaServer

4.application.yml配置: 端口 , 注册中心地址 ,禁止向自己注册,禁止拉取注册列表

单个服务器配置:

server:
  port: 1010  #端口
eureka:
  instance:
    hostname: localhost #主机名
  client: #客户端配置
    registerWithEureka: false  #EurekaServer自己不要注册到EurekaServer自己 ,只有EurekaClient才注册
    fetchRegistry: false  #EurekaServer不要拉取服务的通信地址列表 ,只有EurekaClient才拉取地址列表
    serviceUrl:  #注册中心的注册地址
      defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #http://localhost:1010/eureka/
  server:
    enable-self-preservation: false #关闭自我保护警告

spring:
  application:
    name: eureka-server #服务器名

三.EurekaClient集成

1.搭建子模块集成父工程

<parent>
        <groupId> org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
    </parent>

2.导入依赖 eureks-client, web包

<dependency>
      	<groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

3.在主配置类添加注解

@SpringBootApplication
@EnableEurekaClient //可以不加

4.配置application.yml

eureka:
  client:
    serviceUrl:
      defaultZone: http://peer1:1011/eureka/,http://peer2:1012/eureka/,http://peer3:1013/eureka/
      #defaultZone: http://peer1:1011/eureka  单个服务器配置
  instance:
    instance-id: order-server:1030
    prefer-ip-address: true
spring:
  application:
    name: order-server
server:
  port: 1030

5.启动项目

springcloud 入门级 springcloud官方教程_User


红色字体为自我保护警告,可通过yml配置关闭。实际开发中建议开启。

四.EurekaServer集群

1.模拟三个服务器,修改system32/driver/etc/host文件:

127.0.0.1 peer1

127.0.0.1 peer2

127.0.0.1 peer3

2.修改Run/Debug Configuration配置如下,使单个主配置类可以多次启动

springcloud 入门级 springcloud官方教程_spring boot_02

3.服务器集群配置:

eureka:
  client:
    serviceUrl:
      defaultZone: http://peer1:1011/eureka/,http://peer2:1012/eureka/,http://peer3:1013/eureka/
  instance:
    prefer-ip-address: true
spring:
  application:
    name: eurela-server
  profiles:
    active: peer1
---
spring:
  profiles: peer1
eureka:
  instance:
    hostname: peer1
    ip-address: peer1:1011
server:
  port: 1011
---
spring:
  profiles: peer2
eureka:
  instance:
    hostname: peer2
    ip-address: peer1:1012
server:
  port: 1012
---
spring:
  profiles: peer3
eureka:
  instance:
    hostname: peer3
    ip-address: peer1:1013
server:
  port: 1013

4通过修改active分别启动三个Eureka服务器端

springcloud 入门级 springcloud官方教程_spring boot_03

五.服务通信RestTemplate

通过Eureka客户端去调用另一个客户端的资源使用RestTemplate通过http请求实现
1.创建子模块,创建一个domain实体类作为jar包来封装公共数据
springcloud-user-common
2.导入依赖的jar包

<dependency>
        <groupId>cn.xh</groupId>
        <artifactId>springboot-user-common</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>

3.配置RestTemplate的bean
在主配置类中配置

@Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

4.在调用端创建controller通过RestTemplate向被调用端发http请求

@RestController
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value = "/order/{id}",method = RequestMethod.GET)
    public User getUser(@PathVariable Long id){
        String url = "http://peer1:1011/user/"+id;
        User forObject = restTemplate.getForObject(url, User.class);
        return forObject;
    }

}

5.被调用端接收到RestTemplate发送的请求后,获取资源返回给调用端

//获取当前被调用客户端的端口号
	@Value("${server.port}")
    private int port;

	@RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    public User getUser(@PathVariable Long id){
    	//模拟数据
        User user = new User(1L,"thor","666666","雷神,prot"+port);
        return user;
    }

6.启动调用客户端和被调用客户端,调用客户端通过浏览器发送请求得到模拟的数据:

springcloud 入门级 springcloud官方教程_spring boot_04

六.Ribbon集成

1.导入依赖

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>

2.在只配置类的RestTemplate配置上加@loadBalance注解

@Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

3.将调用端请求url中的ip+端口号该为被调用端的服务名

@Autowired
    private RestTemplate restTemplate;

    @RequestMapping(value = "/order/{id}",method = RequestMethod.GET)
    public User getUser(@PathVariable Long id){
        String url = "http://user-server/user/"+id;
        User forObject = restTemplate.getForObject(url, User.class);
        return forObject;
    }

4.在被调用端controller类加上一个当前被调用客户端端口号字段,在返回值中加上该字段的值

@Value("${server.port}")
    private String port;

5.在浏览器中通过调用端访问资源

springcloud 入门级 springcloud官方教程_springcloud 入门级_05


springcloud 入门级 springcloud官方教程_spring boot_06


可以得到模拟的资源,并且ribbon的默认均衡负载模式为轮询。

可以通过在调用端主配置类中添加@Bean来改变负载均衡模式:

RoundRobinRule(默认) 简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。

springcloud 入门级 springcloud官方教程_User_07


代码如下:

//随机模式
	@Bean
    public RandomRule randomRule(){
        return new RandomRule();
    }

七.Feign的集成

1.导入依赖

<dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

2.主配置类添加注解开启Feign

@EnableFeignClients

3.在调用端创建FeignClient的接口,接口中的方法与被调用客户端的方法名,参数,请求,返回类型完全一致,添加@FeignClient(value = “user-server”),value为要调用的服务名

@FeignClient(value = "user-server")
public interface UserFeignClient {

    @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    User getUserById(@PathVariable("id") Long id);
}

5.在浏览器中通过调用端访问资源

springcloud 入门级 springcloud官方教程_spring boot_08

八.Ribbon+Hystrix使用

1.导入依赖

<dependency>
     	<groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>

2.在主配置类上添加@EnableCircuitBreaker注解开启Hystrix

@EnableCircuitBreaker

3.在controller类方法@RequestMapping注解中添加属性fallbackMethid指向降级方法

@HystrixCommand(fallbackMethod = "getUserFallbackMethod")

4.申明降级方法: 参数和返回值必须和被熔断的方法一致 ,方法名要和 fallbackMethod 的值一致

@HystrixCommand(fallbackMethod = "getUserFallbackMethod")
    @RequestMapping(value = "/order/{id}",method = RequestMethod.GET)
    public User getUser(@PathVariable Long id){
        String url = "http://user-server/user/"+id;
        User forObject = restTemplate.getForObject(url, User.class);
        return forObject;
    }

    public User getUserFallbackMethod(@PathVariable Long id){
        User user = new User(-1L,"无法找到该用户","系统繁忙!请稍后再试!");
        return user;
    }

5.重启客户端,关闭被调用客户端,在浏览器中通过调用端访问资源

springcloud 入门级 springcloud官方教程_spring boot_09

九.Feign开启Hystrix

1.导入依赖

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>

2.主配置类添加注解@EnableCircuitBreaker开启Hystrix

@EnableCircuitBreaker

3.application.yml配置开启Hysrix

feign:
  hystrix:
    enabled: true #开启熔断支持

4.配置熔断
方式1:
托底类实现FeignClient接口方式
①申明一个托底类实现FeignClient接口,添加@Component注解,将托底类交给Spring管理

@Component
public class UserFeignClientFallback implements UserFeignClient{

    @Override
    public User getUserById(Long id) {
        User user = new User(-1L,"无法找到该用户","系统繁忙!请稍后再试!");
        return user;
    }
}

②在FeignClient接口的@FeignClient注解中添加fallback属性,值为托底类.class

@FeignClient(value = "user-server",fallback = UserFeignClientFallback.class)
public interface UserFeignClient {

    @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    User getUserById(@PathVariable("id") Long id);
}

③重启客户端,关闭被调用客户端,在浏览器中通过调用端访问资源

springcloud 入门级 springcloud官方教程_spring_10


方式2:

托底类实现FeignClient接口方式

①申明一个托底类实现FallbackFactory接口,添加@Component注解将托底类交给Spring管理

@Component
public class UserFeignClientFallbackFactory implements FallbackFactory<UserFeignClient> {
    @Override
    public UserFeignClient create(Throwable throwable) {
        return new UserFeignClient() {
            @Override
            public User getUserById(Long id) {
                User user = new User(-1L,"无法找到该用户","系统繁忙!请稍后再试!");
                return user;
            }
        };
    }
}

②在FeignClient接口的@FergnClient注解中添加属性fallbackFactory值为托底工厂类.class

@FeignClient(value = "user-server",fallbackFactory = UserFeignClientFallbackFactory.class)
public interface UserFeignClient {

    @RequestMapping(value = "/user/{id}",method = RequestMethod.GET)
    User getUserById(@PathVariable("id") Long id);
}

③重启客户端,关闭被调用客户端,在浏览器中通过调用端访问资源

springcloud 入门级 springcloud官方教程_java_11

十.zuul

1.创建子模块导入依赖

<dependency>
       <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    </dependency>

2.添加注解

@EnableZuulProxy

3.配置application.yml

eureka:
  client:
    serviceUrl:
      defaultZone: http://peer1:1011/eureka/,http://peer2:1012/eureka/,http://peer3:1013/eureka/
  instance:
    instance-id: zuul-server:1060
    prefer-ip-address: true
spring:
  application:
    name: zuul-server
server:
  port: 1060
zuul:
  prefix: "/servers"  #统一访问前缀
  ignoredServices: '*' #禁用掉使用浏览器通过服务名的方式访问服务
  routes:
    user-server: /user/** #给服务名取别名
    pay-server: /pay/**
    order-server: /order/**

4.创建前置过滤器,做登录认证

@Component
public class MyZuulFilter extends ZuulFilter{
    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.SEND_ERROR_FILTER_ORDER;
    }

    @Override
    public boolean shouldFilter() {
        //获取请求对象
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();

        String uri = request.getRequestURI();

        if (uri.contains("/login") || uri.contains("/register")){
            return false;
        }
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        //获取请求对象
        RequestContext currentContext = RequestContext.getCurrentContext();
        HttpServletRequest request = currentContext.getRequest();
        //获取响应对象
        HttpServletResponse response = currentContext.getResponse();
        //设置编码
        response.setContentType("application/json;charset=utf-8");
        //获取请求头的toke
        String token = request.getHeader("token");
        //判断是否登录
        if (StringUtils.isEmpty(token)){
            Map<String,Object> result = new HashMap<>();
            result.put("success",false);
            result.put("msg","未登陆,没有权限访问");
            String s = JSON.toJSONString(result);
            try {
                response.getWriter().write(s);
            } catch (IOException e) {
                e.printStackTrace();
            }
            //响应状态403
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            //程序不再往后执行
            currentContext.setSendZuulResponse(false);
        }
        return null;
    }
}

5.启动客户端,用idea自带的工具测试

springcloud 入门级 springcloud官方教程_spring_12


请求头没有添加token的结果

springcloud 入门级 springcloud官方教程_spring boot_13


请求头添加token后的结果

springcloud 入门级 springcloud官方教程_java_14


springcloud 入门级 springcloud官方教程_spring boot_15

十一.ConfigServer

1.创建码云仓库

springcloud 入门级 springcloud官方教程_spring_16


2.创建子模块导入依赖

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-server</artifactId>
    </dependency>

3.主配置类添加注解开启配置中心

@EnableConfigServer

4.配置application.yml

spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        git:
          uri: 码云仓库地址
          username: 码云账号 
          password: 密码
eureka:
  instance:
    prefer-ip-address: true
    instance-id: config-server:1070
  client:
      serviceUrl:
        defaultZone: http://peer1:1011/eureka/,http://peer2:1012/eureka/,http://peer3:1013/eureka/

5创建本地文件夹克隆

springcloud 入门级 springcloud官方教程_java_17


springcloud 入门级 springcloud官方教程_User_18


6将项目中的application.yml文件复制到该文件夹中,注意命名application-服务名,提交并推送

springcloud 入门级 springcloud官方教程_spring boot_19


springcloud 入门级 springcloud官方教程_spring_20


查看码云仓库,上传成功

springcloud 入门级 springcloud官方教程_springcloud 入门级_21


7启动客户端,在浏览器中访问资源,得到对应配置文件

springcloud 入门级 springcloud官方教程_spring_22

十二.ConfigClient

1集成ConfigClient,在应用客户端添加依赖

<dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-config-client</artifactId>
    </dependency>

2.配置bootstrap.yml

#配置中心的地址
spring:
  cloud:
    config:
      uri: http://localhost:1070 #order要从配置中心拉取文件
      #你要拉取具体的哪个配置文件
      name: application-order  #配置文件名字
      label: master #主分支

3将application文件修改名字使springcloud无法自动识别该服务的application.yml

springcloud 入门级 springcloud官方教程_java_23


4重启客户端,端口为1030则表示拉去成功,若为8080则拉去失败,需要重新检查配置

springcloud 入门级 springcloud官方教程_spring_24


5.通过浏览器访问,得到结果,配置成功

springcloud 入门级 springcloud官方教程_spring_25