一、springboot2.3.x + eureka + feign

  • Post author:
  • Post category:其他




一、首先创建一个父项目,名称 springcloud

在这里插入图片描述

在这里插入图片描述

注意,springcloud和springboot的版本是有对应的,(如,本项目中,springboot版本为 2.3.7.BUILD-SNAPSHOT ,springcloud 版本为 Hoxton.BUILD-SNAPSHOT),如果不一致,会出现很多问题,我这里是项目创建时,自动匹配的;

在这里插入图片描述

也可以以下网址查找对应的;

在线访问

https://start.spring.io/actuator/info

https://spring.io/projects/spring-cloud



二、创建服务提供者 在父工程下,创建一个子module,项目名称 eureka-provider

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

创建一个接口,我们这里直接返回数据

package com.hnyc.eurekaprovider.controller;

import com.hnyc.eurekaprovider.bean.Goods;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * create by hyq on 2020/11/18
 */
@RestController
@RequestMapping("/goods")
public class GoodsController {

  @GetMapping("/findOne/{id}")
  public Goods findOne(@PathVariable("id") int id) {
    Goods goods = new Goods();
    goods.setId(1);
    goods.setTitle("华为手机");
    goods.setPrice(10000);
    goods.setCount(10000);
    return goods;
  }


}
package com.hnyc.eurekaprovider.bean;

import lombok.Data;

/**
 * create by hyq on 2020/11/18
 */
@Data
public class Goods {
  private int id;
  private String title;//商品标题
  private double price;//商品价格
  private int count;//商品库存

}

application.yml配置端口

server:
  port: 8000



三、创建服务消费者

   项目名称 eureka-consumer,项目创建方法参考  eureka-provider。
   添加以下三个类
package com.hnyc.eurekaconsumer.bean;

import lombok.Data;

/**
 * create by hyq on 2020/11/18
 */
@Data
public class Goods {
  private int id;
  private String title;//商品标题
  private double price;//商品价格
  private int count;//商品库存

}

package com.hnyc.eurekaconsumer.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * create by hyq on 2020/11/18
 */
@Configuration
public class RestTemplateConfig {

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

package com.hnyc.eurekaconsumer.controller;

import com.hnyc.eurekaconsumer.bean.Goods;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * create by hyq on 2020/11/18
 */
@RestController
@RequestMapping("/order")
public class OrderController {

  @Autowired
  private RestTemplate restTemplate;

  @GetMapping("/goods/{id}")
  public Goods findGoodsById(@PathVariable("id") int id) {
    String url = "http://localhost:8080/goods/findOne/" + id;
    // 3. 调用方法
    Goods goods = restTemplate.getForObject(url, Goods.class);
    return goods;
  }


}




四、访问消费者接口

http://localhost:8081/order/goods/1 ,返回成功

在这里插入图片描述

但可以看到,访问服务访问路径的代码写死了,我们需要系统能动态获取路径。



五、使用Eureka配置动态路径

创建一个新module ,名 eureka-server

修改pom.xml文件

<!-- 父项目 -->
 <parent>
    <groupId>com.hnyc</groupId>
    <artifactId>springcloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <relativePath/> <!-- lookup parent from repository -->
 </parent>

<!-- 添加 eureka-server端jar包 -->
<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

启动类上添加注解

package com.hnyc.eurekaserver;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
// 启用EurekaServer ,如果 springboot 和 springcloud版本不对应,这里会找不到或者无法引入这个注解
@EnableEurekaServer
public class EurekaServerApplication {

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


}

application.yml添加配置

server.port: 9090
eureka:
  instance:
    hostname: localhost
  client:
    service-url:
      defaultZone: http://${eureka.instance.hostname}:${server.port}/${spring.application.name} # eureka服务端地址,将来客户端使用该地址和eureka进行通信
    register-with-eureka: false # 是否将自己的路径 注册到eureka上。eureka server 不需要的,eureka provider client 需要
    fetch-registry: false # 是否需要从eureka中抓取路径。eureka server 不需要的,eureka consumer client 需要
spring:
  application:
    name: eureka



六、调整 服务提供方 eureka-provider

pom.xml 修改

<parent>
    <groupId>com.hnyc</groupId><!-- 父项目 -->
    <artifactId>springcloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
  
<!-- 添加 eureka-client 端jar包 -->
<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

启动类添加配置

package com.hnyc.eurekaprovider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class EurekaProviderApplication {

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


}

application.yml 添加配置

server:
  port: 8080
eureka:
  instance:
    hostname: localhost
  client:
    service-url:
      defaultZone: http://localhost:9090/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
spring:
  application:
    name: eureka-provider # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径



七、修改 服务消费端 eureka-consumer

pom.xml 修改

<parent>
    <groupId>com.hnyc</groupId><!-- 父项目 -->
    <artifactId>springcloud</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
  
<!-- 添加 eureka-client 端jar包 -->
<dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

启动类添加配置

package com.hnyc.eurekaconsumer;

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;

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient // 激活DiscoveryClient
public class EurekaConsumerApplication {

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


}

application.yml添加配置

server:
  port: 8081

eureka:
  instance:
    hostname: localhost
  client:
    service-url:
      defaultZone: http://localhost:9090/eureka # eureka服务端地址,将来客户端使用该地址和eureka进行通信
spring:
  application:
    name: eureka-consumer # 设置当前应用的名称。将来会在eureka中Application显示。将来需要使用该名称来获取路径

修改原来controller,改为动态获取访问路径

package com.hnyc.eurekaconsumer.controller;

import com.hnyc.eurekaconsumer.bean.Goods;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * create by hyq on 2020/11/18
 */
@RestController
@RequestMapping("/order")
public class OrderController {

  @Autowired
  private DiscoveryClient discoveryClient;

//  @GetMapping("/goods/{id}")
//  public Goods findGoodsById(@PathVariable("id") int id) {
//    String url = "http://localhost:8080/goods/findOne/" + id;
//    // 3. 调用方法
//    Goods goods = restTemplate.getForObject(url, Goods.class);
//    return goods;
//  }
  @Autowired
  private RestTemplate restTemplate;

  @GetMapping("/goods/{id}")
  public Goods findGoodsById(@PathVariable("id") int id) {
    //演示discoveryClient 使用
    List<ServiceInstance> instances = discoveryClient.getInstances("EUREKA-PROVIDER");

    //判断集合是否有数据
    if (instances == null || instances.size() == 0) {
      //集合没有数据
      return null;
    }

    ServiceInstance instance = instances.get(0);
    String host = instance.getHost();//获取ip
    int port = instance.getPort();//获取端口
    String url = "http://" + host + ":" + port + "/goods/findOne/" + id;
    // 调用方法
    Goods goods = restTemplate.getForObject(url, Goods.class);
    return goods;
  }


}



八、至此,eureka基本配置完成

尝试 启动 eureka-server、eureka-provider、eureka-consumer 三个项目

在这里插入图片描述

启动后,访问尝试调用消费者接口

http://localhost:8081/order/goods/1

在这里插入图片描述

调用成功。



九、整合feign

如果你觉得 刚刚 controller层 的写法稍显复杂,可以使用 feign 代替 RestTemplate

修改服务调用方 eureka-consumer 的代码

pom.xml 添加以下jar包

<!--feign-->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</artifactId>
      <version>2.2.2.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>io.github.openfeign</groupId>
      <artifactId>feign-okhttp</artifactId>
      <version>11.0</version>
    </dependency>

启动类添加注解

package com.hnyc.eurekaconsumer;

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.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient // 激活DiscoveryClient
@EnableFeignClients //添加 feign
public class EurekaConsumerApplication {

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


}

application.yml添加配置

feign:
  hystrix:
    enabled: true
  compression:
    request:
      enabled: true
      mime-types: ["text/xml","application/xml","application/json"]
      min-request-size: 2048
    response:
      enabled: true
  client:
    config:
      default:
        logger-level: basic
      feign-provider-demo1:
        logger-level: full

hystrix:
  command:
    default:  #default全局有效,service id指定应用有效
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 20000 #断路器超时时间,默认1000ms

添加需要调用的接口声明类 RemoteService

package com.hnyc.eurekaconsumer.feign;

import com.hnyc.eurekaconsumer.bean.Goods;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * create by hyq on 2020/11/18
 */
@FeignClient("eureka-provider") //调用端服务名
public interface RemoteService {

  @GetMapping(value = "/goods/findOne/{id}")
  Goods findGoodsById(@PathVariable("id") int id);


}

修改原来controller的调用方法

package com.hnyc.eurekaconsumer.controller;

import com.hnyc.eurekaconsumer.bean.Goods;
import com.hnyc.eurekaconsumer.feign.RemoteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * create by hyq on 2020/11/18
 */
@RestController
@RequestMapping("/order")
public class OrderController {

//  @Autowired
//  private DiscoveryClient discoveryClient;

//  @GetMapping("/goods/{id}")
//  public Goods findGoodsById(@PathVariable("id") int id) {
//    String url = "http://localhost:8080/goods/findOne/" + id;
//    // 3. 调用方法
//    Goods goods = restTemplate.getForObject(url, Goods.class);
//    return goods;
//  }

//  @Autowired
//  private RestTemplate restTemplate;
//
//  @GetMapping("/goods/{id}")
//  public Goods findGoodsById(@PathVariable("id") int id) {
//    //演示discoveryClient 使用
//    List<ServiceInstance> instances = discoveryClient.getInstances("EUREKA-PROVIDER");
//
//    //判断集合是否有数据
//    if (instances == null || instances.size() == 0) {
//      //集合没有数据
//      return null;
//    }
//
//    ServiceInstance instance = instances.get(0);
//    String host = instance.getHost();//获取ip
//    int port = instance.getPort();//获取端口
//    String url = "http://" + host + ":" + port + "/goods/findOne/" + id;
//    // 调用方法
//    Goods goods = restTemplate.getForObject(url, Goods.class);
//    return goods;
//  }

  @Autowired
  private RemoteService remoteService;

  @GetMapping("/goods/{id}")
  public Goods findGoodsById(@PathVariable("id") int id) {
    return remoteService.findGoodsById(id);
  }


}


再次启动 eureka-server、eureka-provider、eureka-consumer 三个项目,访问接口 http://localhost:8081/order/goods/1

在这里插入图片描述

返回成功,



版权声明:本文为weixin_43083074原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。