SpringCloud简介 Ribbon Eureka 远程调用RestTemplate类 openfeign

〇、SpringCloud

0.区别于单体项目和soa架构,微服务架构每个服务独立,灵活。

  1. spring cloud是一个完整的微服务框架,springCloud包括三个体系:

spring cloud Netflix

spring cloud Alibaba

spring 其他

2.spring cloud 版本命名

早期以伦敦地铁名命名,后来采用年份命名。

3.spring cloud 涵盖有非常多的子框架,每个框架有属于自己的版本。学习阶段需要先了解每一个子框架的用法。每个spring cloud框架 对应的spring boot版本也不一样

这里采用H版本

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.12.RELEASE</version>
    </parent>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR12</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


一、Eureka

1.Eureka 分为 Eureka service服务器 和 Eureka client客户端

所有客户端都在 服务器中注册自己:

将自己的客户端主机名和ip端口号储存在服务器中,这个存储过程也可以使用redis完成。如果给客户端搭建集群,主机名一样。

当客户端需要远程调用其他客户端时,通过告知服务器客户端主机名获取多个ip及端口号

这时客户端拿到了一系列的ip及端口号。可以使用Ribbon计算出这次远程调用哪一个客户端。

2.搭建Eureka service服务器 配置文件

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

server:
  port: 8761
eureka:
  client:
    # 因为当前项目为服务,不需要向服务注册自己,默认为true
    register-with-eureka: false
    # 因为当前为非集群版eureka,所以不需要同步其他节点数据
    fetch-registry: false

3.搭建Eureka client服务器 配置文件

   <dependencies>
        <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>
    </dependencies>

server:
  port: 9999
# 配置服务注册的名称
spring:
  application:
    name: application-client
#配置EureKaServer的地址 默认为 http://localhost:8761/eureka/
#eureka:
#  client:
#    service-url:
#      defaultZone: http://localhost:8761/eureka/

4.访问Eureka

①开启service项目;
② 客户端编写三个启动类,每次启动时更改端口号;主机名application-client
③访问Eureka服务器


二、Ribbon

Ribbon是负责负载均衡的springCloud Netflix 子框架。

在访问Eureka 拿到访问地址后,本客户端调用Ribbon通过算法计算出一个访问地址。

核心接口为 LoadBalancerClient

1.这里启动两个 主机名为application-service 的客户端。

2.用一个application-client的客户端通过Eureka拿到application-service主机地址

3.多次访问localhost:9999/demo

可以看到默认的负载均衡策略为轮循。



三、远程调用 RestTemplate类

0)RestTemplate是spring用于发送http请求的模板类。这里配置该对象:

@LoadBalanced 注解用于开启Robbin负载均衡策略。

RandomRule对象是负载均衡的算法,随机选择调用地址。

1)创建springboot的父项目 、公共项目

新建子项目commen

commen依赖:

<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.22</version> <!-- 请使用最新的版本号 -->
            <scope>provided</scope>
</dependency>

2)服务器

服务器正常写增删改查的项目,这里测试就直接返回对应数据方便观察接口调用

java 复制代码
@RestController
public class MyController {
//    @Value("${server.port}")
    private int port = 8080;

    /**
     * 返回类型为集合,泛型为自定类型。
     */
    @RequestMapping("/returnUsers")
    public List<User> returnUsers(int nums){
        List<User> result = new ArrayList<>();
        for(int i = 0; i < nums; i++){
            result.add(new User(100 + i, "姓名-" + i, 20+i));
        }
        return result;
    }

    /**
     * 任意请求方式, 返回值类型是集合。相对复杂的Java类型。
     * @return
     */
    @RequestMapping("/returnList")
    public List<String> returnList(int nums){
        List<String> result = new ArrayList<>();
        for(int i = 0; i < nums; i++){
            result.add("返回结果 - " + i);
        }
        return result;
    }

    /**
     * 任意请求,传递路径地址参数
     * @param name
     * @param age
     * @return
     */
    @RequestMapping("/restfulParams/{name}/{age}")
    public String restfulParams(@PathVariable("name") String name,
                                @PathVariable int age){
        System.out.println("端口号: " + port + ", 任意请求方式,restful参数, name = " +
                name + " ; age = " + age);
        return "restful参数, name = " + name + " ; age = " + age;
    }


    /**
     * post请求,请求体传递参数。参数使用@RequestBody处理。
     */
    @PostMapping("/postBodyParams")
    public String postBodyParams(@RequestBody Map<String, String> params){
        System.out.println("端口号: " + port + " , post请求,有请求体参数, params = " +
                params);
        return "post请求,请求体参数, params = " + params;
    }

    /**
     * post请求,有参数
     */
    @PostMapping("/postWithParams")
    public String postWithParams(String name, int age){
        System.out.println("端口号: " + port + " , post请求,有参数, name = " +
                name + " ; age = " + age);
        return "post请求有参数 : name = " +
                name + " ; age = " + age;
    }

    /**
     * post请求,没有参数
     */
    @PostMapping("/postNoParams")
    public String postNoParams(){
        System.out.println("端口号: " + port + " , post请求,没有参数");
        return "post请求,没有参数";
    }

    /**
     * get请求,包含参数
     */
    @GetMapping("/getWithParams")
    public String getWithParams(String name, int age){
        System.out.println("端口号: " + port + " 。 get请求,有参数, name = "
                + name + " ; age = " + age);
        return "get请求,包含参数 : name = " + name + " ; age = " + age;
    }

    /**
     * get请求,没有参数
     * @return
     */
    @GetMapping("/getNoParams")
    public String getNoParams(){
        System.out.println("端口号:" + port + "。 get请求,无参数。");
        return "get请求,无参数。";
    }
}

服务器依赖:

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.example</groupId>
            <artifactId>commen</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

3)客户端配置RestTemplate对象

客户端依赖:

java 复制代码
  <dependencies>
        <dependency>
            <artifactId>spring-boot-starter-web</artifactId>
            <groupId>org.springframework.boot</groupId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.example</groupId>
            <artifactId>commen</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

4)使用RestTemplate对象在客户端测试服务器方法的调用

①请求行携带键值对的几种形式

②post请求自定义请求头 请求体为键值对

③post请求 传输请求体为json格式

④post请求 自定义传输请求体为json格式

⑤ exchange()通用公式

java 复制代码
@SpringBootTest
public class RestTemplateTest {
    @Autowired
    private RestTemplate restTemplate;
    @Test
    public void test(){
        String forObject = restTemplate.getForObject("http://localhost:8080/getNoParams", String.class);
        System.out.println("forObject = " + forObject);
    }

    @Test
    public void test1(){
        String forObject1 = restTemplate.getForObject("http://localhost:8080/getWithParams?name=张三&age=20", String.class);
        String forObject2 = restTemplate.getForObject("http://localhost:8080/getWithParams?name={a}&age={b}", String.class,"战法",29);

        Map<String,Object>  map= new HashMap();
        map.put("x","阿森纳");
        map.put("y",20);
        String forObject3 = restTemplate.getForObject("http://localhost:8080/getWithParams?name={x}&age={y}", String.class,map);
        System.out.println("forObject1 = " + forObject1);
        System.out.println("forObject2 = " + forObject2);
        System.out.println("forObject3 = " + forObject3);
    }

    @Test
    public void testPost(){
        restTemplate.postForObject("http://localhost:8080/postNoParams",null,String.class);
    }

    @Test
    public void testPost1(){

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("content-type","application/x-www-form-urlencoded");

        MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();
        map.add("name","埃德加");
        map.add("age","20");

        HttpEntity<MultiValueMap<String,Object>> entity = new HttpEntity<>(map,httpHeaders);
        String s = restTemplate.postForObject("http://localhost:8080/postWithParams", entity, String.class);
        String s1 = restTemplate.postForObject("http://localhost:8080/postWithParams?name=咋很难&age=29", entity, String.class);
        System.out.println("s = " + s);
        System.out.println("s1 = " + s1);
    }


    @Test
    public void testPost2(){
        Map<String,Object> map = new HashMap<>();
        map.put("name","绽放");
        map.put("age",29);
        restTemplate.postForObject("http://localhost:8080/postBodyParams",map,String.class);
    }

    @Test
    public void testPost3() throws JsonProcessingException {

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("content-type","application/json");

//        MultiValueMap<String,Object> map = new LinkedMultiValueMap<>();
        Map<String,Object> map = new HashMap<>();
        map.put("name","埃德加");
        map.put("age","20");
        ObjectMapper objectMapper = new ObjectMapper();
        String s1 = objectMapper.writeValueAsString(map);

        HttpEntity<String> entity = new HttpEntity<>(s1,httpHeaders);
        String s = restTemplate.postForObject("http://localhost:8080/postBodyParams", entity, String.class);
        System.out.println("s = " + s);
    }

    @Test
    public void testEvery(){
        ResponseEntity<List<User>> exchange = restTemplate.exchange("http://localhost:8080/returnUsers?nums=9",
                HttpMethod.GET,
                null,
                new ParameterizedTypeReference<List<User>>() {
                });
        System.out.println("exchange = " + exchange);
    }
}


四、openfeign

1)编写Feign接口:

1.将要调用服务主机的Controller中所有单元方法全部复制

2.创建Feign接口,并粘贴所有方法,改写为抽象方法

java 复制代码
@FeignClient("application-service")
public interface Feign {

    @RequestMapping("/returnUsers")
    public List<User> returnUsers(int nums);

    /**
     * 任意请求方式, 返回值类型是集合。相对复杂的Java类型。
     * @return
     */
    @RequestMapping("/returnList")
    public List<String> returnList(@RequestParam("nums") int nums);

    /**
     * 任意请求,传递路径地址参数
     * @param name
     * @param age
     * @return
     */
    @RequestMapping("/restfulParams/{name}/{age}")
    public String restfulParams(@PathVariable("name") String name,
                                @PathVariable("age") int age);


    /**
     * post请求,请求体传递参数。参数使用@RequestBody处理。
     */
    @PostMapping("/postBodyParams")
    public String postBodyParams(@RequestBody Map<String, String> params);
    /**
     * post请求,有参数
     */
    @PostMapping("/postWithParams")
    public String postWithParams(@RequestParam("name") String name,@RequestParam("age") int age);

    /**
     * post请求,没有参数
     */
    @PostMapping("/postNoParams")
    public String postNoParams();

    /**
     * get请求,包含参数
     */
    @GetMapping("/getWithParams")
    public String getWithParams(@RequestParam("name")String name,@RequestParam("age")int age);

    /**
     * get请求,没有参数
     * @return
     */
    @GetMapping("/getNoParams")
    public String getNoParams();
}

3.添加注解



2)开启Eureka service 及Eureka client主机application-service:



3)调用Feign接口:

相关推荐
杨荧18 分钟前
【JAVA毕业设计】基于Vue和SpringBoot的服装商城系统学科竞赛管理系统
java·开发语言·vue.js·spring boot·spring cloud·java-ee·kafka
想进大厂的小王3 小时前
Spring-cloud 微服务 服务注册_服务发现-Eureka
微服务·eureka·服务发现
aloha_78913 小时前
从零记录搭建一个干净的mybatis环境
java·笔记·spring·spring cloud·maven·mybatis·springboot
茶馆大橘16 小时前
微服务系列五:避免雪崩问题的限流、隔离、熔断措施
java·jmeter·spring cloud·微服务·云原生·架构·sentinel
荆州克莱20 小时前
[FE] React 初窥门径(四):React 组件的加载过程(render 阶段)
spring boot·spring·spring cloud·css3·技术
Genius Kim1 天前
SpringCloud Sentinel 服务治理详解
spring cloud·sentinel·php
为美好的生活献上中指1 天前
Java学习Day60:微服务总结!(有经处无火,无火处无经)
java·spring boot·spring cloud·微服务·sentinel·jetty
licy__1 天前
Docker 基础命令简介
docker·云原生·eureka
BUG指挥官1 天前
深度解析阿里的Sentinel
spring boot·spring·spring cloud·sentinel