三、服务远程调用

3.1 工程准备

3.1.1 搭建父工程

3.1.1.1 maven依赖:

<?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">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    
    <modules>
        <module>order_server</module>
        <module>store_server</module>
    </modules>

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

    <groupId>com.cloud</groupId>
    <artifactId>parent</artifactId>
    <version>1.0-SNAPSHOT</version>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-logging</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.4</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR10</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
</project>

3.1.2 搭建商品微服务

3.1.2.1 maven依赖:

<?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>01_SpringCloud_RestTemplate</artifactId>
        <groupId>com.cloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>item_server</artifactId>


</project>

3.1.2.2 application.yml

server:
  port: 9000

3.1.2.3 ItemApplication

package com.cloud.item;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@SpringBootApplication
public class ItemApplication {
    public static void main(String[] args) {
        SpringApplication.run(ItemApplication.class);
    }
}

3.1.2.4 ItemController

package com.cloud.item.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@RestController
@RequestMapping("/item")
public class ItemController {


}

3.1.2.5 Order实体类

实际开发应该搭建一个common公共模块,实体类编写在公共模块中,我们为了简单起见,在各个微服务中编写同样的实体类;

package com.cloud.item.entity;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
 * @author lscl
 * @version 1.0
 * @intro: 订单实体类
 */
@Data                   // get/set/toString
@NoArgsConstructor      // 无参构造
@AllArgsConstructor     // 有参构造
public class Order {

    private Integer id;
    private String itemName;
    private Double price;
    private Integer num;
}

3.1.3 搭建订单微服务

3.1.3.1 maven依赖

<?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>01_SpringCloud_RestTemplate</artifactId>
        <groupId>com.cloud</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>order_server</artifactId>

</project>

3.1.3.2 application.yml

server:
  port: 9001

3.1.3.3 OrderApplication

package com.cloud.order;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@SpringBootApplication
public class OrderApplication {
    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class);
    }
}

3.1.3.4 Order实体类

package com.cloud.order.entity;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

/**
 * @author lscl
 * @version 1.0
 * @intro: 订单实体类
 */
@Data                   // get/set/toString
@NoArgsConstructor      // 无参构造
@AllArgsConstructor     // 有参构造
public class Order {

    private Integer id;
    private String itemName;
    private Double price;
    private Integer num;
}

3.1.3.5 OrderController

package com.cloud.order.controller;

import com.cloud.order.entity.Order;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    /**
     * 新增订单
     * @param order
     * @return
     */
    @PostMapping
    public Map save(@RequestBody Order order){

        return new HashMap(){{
            put("flag",true);
            put("message","新增成功");
            put("statusCode","200");
            put("order",order);
        }};
    }

    /**
     * 删除订单
     * @param id
     * @return
     */
    @DeleteMapping("{id}")
    public Map delete(@PathVariable Integer id){

        return new HashMap(){{
            put("flag",true);
            put("message","删除成功");
            put("statusCode","200");
            put("id",id);
        }};
    }

    /**
     *
     * @param id
     * @param order
     * @return
     */
    @PutMapping("{id}")
    public Map update(@PathVariable Integer id,@RequestBody Order order){

        order.setId(id);
        return new HashMap(){{
            put("flag",true);
            put("message","修改");
            put("statusCode","200");
            put("order",order);
        }};
    }

    @GetMapping("{id}")
    public Map findById(@PathVariable Integer id){

        return new HashMap(){{
            put("flag",true);
            put("message","查询成功");
            put("statusCode","200");
            put("id",id);
        }};
    }
}

工程搭建如下:

SpringCloud-Netflix-03-服务远程调用_微服务

3.2 RestTemplate

RestTemplate 是从 Spring3.0 开始支持的一个 HTTP 请求工具,它提供了常见的REST请求方案的模版,例如 GET 请求、POST 请求、PUT 请求、DELETE 请求以及一些通用的请求执行方法 exchange 以及 execute。RestTemplate 继承自 InterceptingHttpAccessor 并且实现了 RestOperations 接口,其中 RestOperations 接口定义了基本的 RESTful 操作,这些操作在 RestTemplate 中都得到了实现。接下来我们就来看看这些操作方法的使用。

3.2.1 RestTemplate方法介绍

请求方式

方法

返回值

GET

getForObject(String,Class,Object...)

GET

getForEntity(String,Class,Object...)

ResponseEntity

POST

postForLocation(String,Object,Object...)

URI

POST

postForObject(String,Object,Class,Object...)

POST

postForEntity(String,Class,Object...)

ResponseEntity

PUT

put(String,Object,Object...)

void

DELETE

delete(String,Object...)

void

自定义

exchange(String,HttpMethod,HttpEntity,Class,Object...)

ResponseEntity

3.2.2 配置 RestTemplate

package com.cloud.item;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@SpringBootApplication
public class ItemApplication {
    public static void main(String[] args) {
        SpringApplication.run(ItemApplication.class);
    }

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

3.2.3 测试类

package com.cloud.demo;

import com.cloud.item.ItemApplication;
import com.cloud.item.entity.Order;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@SpringBootTest(classes = ItemApplication.class)
@RunWith(SpringRunner.class)
public class Demo01 {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * get请求
     */
    @Test
    public void test1() {

        // 直接获取响应体
//        Map resultMap = restTemplate.getForObject("http://localhost:9001/order/1", Map.class);

        // 获取响应实体
        ResponseEntity<Map> entity = restTemplate.getForEntity("http://localhost:9001/order/1", Map.class);

        // 响应码
        System.out.println(entity.getStatusCodeValue());

        // 响应头
        System.out.println(entity.getHeaders());

        // 响应体
        Map resultMap = entity.getBody();
        System.out.println(resultMap);
    }

    /**
     * post请求
     */
    @Test
    public void test2() {
        Map resultMap = restTemplate.postForObject(
                "http://localhost:9001/order",
                new Order(1, "赣南脐橙", 48.8, 10),
                Map.class);

        // 响应码
        System.out.println(resultMap);
    }

    /**
     * put请求
     */
    @Test
    public void test3() {

        // 可以发送put请求,但是没有返回值
        restTemplate.put(
                "http://localhost:9001/order/11",
                new Order(null, "赣南脐橙", 48.8, 10));

        // 封装一个请求对象
        HttpEntity<Order> httpEntity=new HttpEntity(new Order(null, "赣南脐橙", 48.8, 10));

        // 发送PUT请求
        ResponseEntity<Map> responseEntity = restTemplate.exchange(
                "http://localhost:9001/order/110",
                HttpMethod.PUT,
                httpEntity,
                Map.class
        );

        Map resultMap = responseEntity.getBody();
        System.out.println(resultMap);

    }

    /**
     * delete请求
     */
    @Test
    public void test4() {
        // 可以发送put请求,但是没有返回值
//        restTemplate.delete("http://localhost:9001/order/110");

        // 发送PUT请求
        ResponseEntity<Map> responseEntity = restTemplate.exchange(
                "http://localhost:9001/order/110",
                HttpMethod.DELETE,
                null,
                Map.class
        );

        Map resultMap = responseEntity.getBody();
        System.out.println(resultMap);
    }
}