全国咨询/投诉热线:400-618-9090

首页技术文章正文

怎么使用Spring Boot 实现一个微服务?[java培训]

更新时间:2020-04-10 来源:黑马程序员 浏览量:

在正式学习 Spring Cloud 之前我们先使用 Spring Boot 实现一个微服务。

业务非常简单:

(1)商品微服务:通过商品 id 查询商品的服务;

(2)订单微服务:通过订单 id 查询订单数据,同时需要调用商品微服务查询出订单详情数据对应的商品数据

Spring Boot 实现微服务01


说明:

(1)对于商品微服务而言,商品微服务是服务的提供者,订单微服务是服务的消费者;

(2)对于订单微服务而言,订单微服务是服务的提供者,人是服务的消费者。


3.1 实现商品微服务

3.1.1 pom.xml 文件的配置

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

    <groupId>cn.itcast.microservice</groupId>

    <artifactId>itcast-micorservice-item</artifactId>

    <version>0.0.1-SNAPSHOT</version>

    <!-- 定义变量 -->

    <properties>

        <java.version>1.8</java.version>

    </properties>

    <parent>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-parent</artifactId>

        <version>1.5.14.RELEASE</version>

    </parent>

    <dependencies>

        <!-- 加入 web 的支持 -->

        <dependency>

            <groupId>org.springframework.boot</groupId>

            <artifactId>spring-boot-starter-web</artifactId>

        </dependency>

    </dependencies>

</project>


3.1.2 创建实体 Item

package cn.itcast.microservice.pojo;

public class Item {

    private Long id;        // 唯一标识

    private String title;    // 商品标题

    private String pic;     // 图片的 pic 地址

    private String desc;    // 描述信息

    private Long price;    // 价格

}

3.1.3 编写 ItemService

package cn.itcast.microservice.service;

import java.util.HashMap;

import java.util.Map;

import org.springframework.stereotype.Service;

import cn.itcast.microservice.pojo.Item;

@Service

public class ItemService {

    private static final Map<Long, Item> MAP = new HashMap<Long, Item>();

        static { // 准备一些静态数据

            MAP.put(1L, new Item(1L, "商品标题 1", "http://图片 1", "商品描述 1", 1000L));

            MAP.put(2L, new Item(1L, "商品标题 2", "http://图片 2", "商品描述 2", 2000L));

            MAP.put(3L, new Item(1L, "商品标题 3", "http://图片 3", "商品描述 3", 3000L));

            MAP.put(4L, new Item(1L, "商品标题 4", "http://图片 4", "商品描述 4", 4000L));

            MAP.put(5L, new Item(1L, "商品标题 5", "http://图片 5", "商品描述 5", 5000L));

            MAP.put(6L, new Item(1L, "商品标题 6", "http://图片 6", "商品描述 6", 6000L));

            MAP.put(7L, new Item(1L, "商品标题 7", "http://图片 7", "商品描述 7", 7000L));

            MAP.put(8L, new Item(1L, "商品标题 8", "http://图片 8", "商品描述 8", 8000L));

       }

      /**

      * 模拟实现商品查询

      *

       * @param id

       * @return

       */

    public Item queryItemById(Long id) {

        return MAP.get(id);

    }

}


3.1.4 编写 ItemController

package cn.itcast.microservice.controller;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.GetMapping;

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

import cn.itcast.microservice.pojo.Item;

import cn.itcast.microservice.service.ItemService;

@RestController

public class ItemController {

    @Autowired

    private ItemService itemService;

    /**

    * 对外提供接口服务,查询商品信息

    *

    * @param id

    * @return

    */

    @GetMapping(value = "/item/{id}")

    public Item queryItemById(@PathVariable("id") Long id) {

        return this.itemService.queryItemById(id);

    }

}


3.1.5 程序入口

package cn.itcast.microservice;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication    //声明这是一个 Spring Boot 项目

    public class ItemApplication {

    public static void main(String[] args) {

        SpringApplication.run(ItemApplication.class, args);

    }

}


3.1.6 创建配置文件

在 src/main/resources 目录下创建一个 application.properties 配置文件,在该文件中可以配置如下内容:

server.port=8081

指定服务启动占用的端口


3.1.7 启动项目进行访问

Spring-Boot-实现微服务02

3.2 实现订单微服务

3.2.1 pom.xml 文件的配置

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

<groupId>cn.itcast.microservice</groupId>

<artifactId>itcast-microservice-order</artifactId>

<version>0.0.1-SNAPSHOT</version>

<!-- 定义变量 -->

<properties>

    <java.version>1.8</java.version>

</properties>

<parent>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-parent</artifactId>

    <version>1.5.14.RELEASE</version>

</parent>

<dependencies>

    <!-- 加入 web 的支持 -->

    <dependency>

        <groupId>org.springframework.boot</groupId>

        <artifactId>spring-boot-starter-web</artifactId>

    </dependency>
</dependencies>

</project>


3.2.2 创建实体 Order

package cn.itcast.microservice.pojo;

import java.util.Date;

import java.util.List;

public class Order {

    private String orderId; // 订单的 id

    private Long userId; // 用户 id

    private Date createDate; // 创建时间

    private Date updateDate; // 修改时间

    private List<OrderDetail> orderDetails; // 订单详情

}

3.2.3 创建实体 OrderDetail

package cn.itcast.microservice.pojo;

public class OrderDetail {

    private String orderId ; // 订单 id

    private Item item ; // 商品

}

3.2.4 复制 Item 实体

Spring-Boot-实现微服务03


3.2.5 编写 OrderService

该 Service 实现的根据订单 Id 查询订单的服务,为了方便测试,我们将构造数据实现,不采用查询数据库的方式。

package cn.itcast.microservice.service;

import java.util.ArrayList;

import java.util.Date;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import org.springframework.stereotype.Service;

import cn.itcast.microservice.pojo.Item;

import cn.itcast.microservice.pojo.Order;

import cn.itcast.microservice.pojo.OrderDetail;

@Service

public class OrderService {

    private static final Map<String, Order> MAP = new HashMap<String, Order>();

    static {

        // 构造测试数据

        Order order = new Order();

        order.setOrderId("59193738268961441");

        order.setCreateDate(new Date());

        order.setUpdateDate(order.getCreateDate());

        order.setUserId(1L);

       // 创建 OrderDetail 集合对象

        List<OrderDetail> orderDetails = new ArrayList<OrderDetail>();

        Item item = new Item(); // 此处并没有商品的数据,需要调用商品微服务获取

        item.setId(1L);

        orderDetails.add(new OrderDetail(order.getOrderId(), item));

        item = new Item(); // 构造第二个商品数据

        item.setId(2L);

        orderDetails.add(new OrderDetail(order.getOrderId(), item));

        // 将 OrderDetail 数据集设置给 Order 对象

        order.setOrderDetails(orderDetails);

        // 将 Order 对象添加到 Map 中

        MAP.put(order.getOrderId(), order);

    }

    /**

   * 根据订单 id 查询订单数据

   *

   * @param orderId

   * @return

   */

    public Order queryOrderById(String orderId) {

        Order order = MAP.get(orderId);

        // 获取 Order 中的 OrderDetail 列表数据,然后遍历集合获取每一个 OrderDetail,然后调用商品微服务根据商品的 id 查询商品数据

        return order;

    }

}

3.2.6 实现 ItemService

package cn.itcast.microservice.service;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;

import org.springframework.web.client.RestTemplate;

import cn.itcast.microservice.pojo.Item;

@Service

public class ItemService {

    @Autowired

    private RestTemplate restTemplate ;

    /**

    * 根据商品的 id 进行查询

    * @param id

    * @return

    */

    public Item queryById(Long id) {

        // 使用 HttpClient 工具发送请求获取商品的数据

        // 我们也可以使用 spring 给我们提供的另个一个类 RestTemplate,来发送 Http 请求

        Item item = restTemplate.getForObject("http://localhost:8081/item/" + id, Item.class) ;

        // 返回

        return item ;

    }

}


3.2.7 完善 OrderService

@Autowired

private ItemService itemService ;

/**

* 根据订单 id 查询订单数据

*

* @param orderId

* @return

*/

public Order queryOrderById(String orderId) {

    Order order = MAP.get(orderId);

    // 获取 Order 中的 OrderDetail 列表数据,然后遍历集合获取每一个 OrderDetail,然后调用商品微服务根据商品的 id 查询商品数据

    for (OrderDetail orderDetail : order.getOrderDetails()) {

        Item item = itemService.queryById(orderDetail.getItem().getId()) ;

        orderDetail.setItem(item);

}

    return order;

}


3.2.8 编写 OrderController

package cn.itcast.microservice.controller;

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.RestController;

import cn.itcast.microservice.pojo.Order;

import cn.itcast.microservice.service.OrderService;

@RestController

public class OrderController {

    @Autowired

    private OrderService orderService;

    @GetMapping(value = "/order/{orderId}")

    public Order queryOrderById(@PathVariable("orderId") String orderId) {

        return this.orderService.queryOrderById(orderId);

    }

}

3.2.9 编写启动类

package cn.itcast.microservice;

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.context.annotation.Bean;

import org.springframework.web.client.RestTemplate;

@SpringBootApplication

public class OrderApplication {

    @Bean

    public RestTemplate restTemplate() {

        return new RestTemplate();

}

// 程序入口

public static void main(String[] args) {

    /**

    * 启动程序

    */

    SpringApplication.run(OrderApplication.class, args) ;

    }

}

3.2.10创建配置文件

在 src/main/resources 目录下创建一个 application.properties 配置文件,在该文件中可以配置如下内容:

server.port=8082

3.2.11启动测试

Spring-Boot-实现微服务04


3.3 发现问题与解决问题

3.3.1 问题描述

在刚才的服务调用过程中我们的商品服务地址是直接写死在程序中,存在硬编码问题

如果商品微服务部署了多个,那么我们订单微服务如何去调用呢?

3.3.2 问题处理

1. 关于硬编码的问题我们可以使用配置文件处理,我们可以将地址信息编写到配置文件中,然后读取配置文件获取请求地址信息.

在配置文件中加入如下配置:

itcast.item.url=http://127.0.0.1:8081/item/

修改 ItemService 的实现,通过@Value 注解获取该值

package cn.itcast.microservice.service;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.stereotype.Service;

import org.springframework.web.client.RestTemplate;

import cn.itcast.microservice.pojo.Item;

@Service

public class ItemService {

    @Autowired

    private RestTemplate restTemplate ;

    @Value("${itcast.item.url}")

    private String itemUrl ;

    /**

    * 根据商品的 id 进行查询

    * @param id

    * @return

    */

    public Item queryById(Long id) {

        // 我们也可以使用 spring boot 给我们提供的另个一个类 RestTemplate,来发送 Http 请求

       Item item = restTemplate.getForObject(itemUrl + id, Item.class) ;

        // 返回

        return item ;

    }

}

注: 我们本次的解决方案只是一种临时的处理方案,如果我们商品微服务的 ip 地址发送了改变,那么我们对应的订单微服务的配置文件也需要做响应的改变,因此这种处理方案并没有本质的解决硬编码的问题。

2. 如果商品微服务部署了多个,那么我们订单微服务如何去调用呢? 

关于这个问题,有的开发人员可能会想。我们可以将多个商品微服务的地址配置到配置文件中,然后在进行读取配置文件的地址,进行调用。听起来好像可以,但是我们需要考虑以后问题就是后期维护的问题。

·如果商品微服务的我们又添加或者减少了一个部署,相应的我们需要去更改配置文件的内容。

·如果商品微服务的 ip 地址发送了改变,那么我们也需要相应的修改配置文件的地址。

所以我们自己这样实现比较麻烦。

我们可以使用服务注册于发现机制来完成


猜你喜欢:

Spring Cloud微服务架构解决方案详细介绍

javaee

python

web

ui

cloud

test

c

netmarket

pm

Linux

movies

robot

http://www.itcast.cn/subject/uizly/index.shtml?seozxuids

14天免费试学

基础班入门课程限时免费

申请试学名额

15天免费试学

基础班入门课程限时免费

申请试学名额

15天免费试学

基础班入门课程限时免费

申请试学名额

15天免费试学

基础班入门课程限时免费

申请试学名额

20天免费试学

基础班入门课程限时免费

申请试学名额

8天免费试学

基础班入门课程限时免费

申请试学名额

20天免费试学

基础班入门课程限时免费

申请试学名额

5天免费试学

基础班入门课程限时免费

申请试学名额

0天免费试学

基础班入门课程限时免费

申请试学名额

12天免费试学

基础班入门课程限时免费

申请试学名额

5天免费试学

基础班入门课程限时免费

申请试学名额

5天免费试学

基础班入门课程限时免费

申请试学名额

10天免费试学

基础班入门课程限时免费

申请试学名额
在线咨询 我要报名