两个微服务模块:goods微服务,orders微服务;

                             orders服务调用goods服务。

 

*通过spring cloud的feign组件进行,此次调用不依赖注册中心。至于feign组件以及注册中心不了解的请自行查阅。

 

步骤一:创建一个maven工程

1.1创建一个空项目

1.2 删除src目录,并在pom.xml中添加所需依赖。

 pom.xml 

<?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>
    <groupId>com.dyj.test</groupId>
    <artifactId>springcloud-test</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.9.RELEASE</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <!-- 资源文件拷贝插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <!-- java编译插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

 

1.3 创建goods微服务:右键springcloudtest项目-->new-->module-->maven-->next,此时目录结构如右图所示:

1.4 创建orders微服务:右键springcloudtest项目-->new-->module-->maven-->next,此时目录结构如右图所示:

说明:为什么goods服务有两个模块?

   dyj-goods-api:微服务对外提供的REST API接口定义,以及接口中所用到的DTO类,供外部服务调用。

   dyj-goods-web:微服务内部的具体实现

          为什么orders服务只有一个模块?

   orders服务其实也可以创建一个dyj-orders-api模块,但是在此次微服务调用例子中,orders服务调用goods服务,其本身并不需要对外部服务提供功能,故没有再创建dyj-orders-api模块。

步骤二:goods服务

2.1 dyj-goods-web模块的pom.xml

<?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>springcloud-test</artifactId>
        <groupId>com.dyj.test</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>dyj-goods-web</artifactId>
    <dependencies>
        <dependency>
            <groupId>com.dyj.test</groupId>
            <artifactId>dyj-goods-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-jdk8</artifactId>
            <version>1.3.1.Final</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.3.1.Final</version>
        </dependency>
    </dependencies>

</project>

说明:dyj-goods-web模块依赖于dyj-goods-api,但两者属于一个服务

2.2 goods微服务模块:结构如下图

2.2.1 GoodsApi

package com.dyj.goods.api;

import com.dyj.goods.dto.GoodsDto;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@RequestMapping("/api/")
public interface GoodsApi {
    @GetMapping("/getGoodsDto")
    GoodsDto getGoodsDto(@RequestParam(value = "id") String id);

}

2.2.2 GoodsDto

package com.dyj.goods.dto;

public class GoodsDto {
    private String id;
    private String name;
    private double advicePrice;
    private String unit;//单位
    public GoodsDto(){}
    public GoodsDto(String id, String name, double advicePrice, String unit) {
        this.id = id;
        this.name = name;
        this.advicePrice = advicePrice;
        this.unit = unit;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getAdvicePrice() {
        return advicePrice;
    }

    public void setAdvicePrice(double advicePrice) {
        this.advicePrice = advicePrice;
    }

    public String getUnit() {
        return unit;
    }

    public void setUnit(String unit) {
        this.unit = unit;
    }
}

2.2.3 Goods

package com.dyj.goods.entity;

public class Goods {
    private String id;
    private String name;
    private String ramark;//备注
    private double costPrice;//成本价
    private double advicePrice;//建议价
    private int num;//存量
    private String unit;//单位
    public Goods(){}

    public Goods(String id, String name, String ramark, double costPrice, double advicePrice, int num, String unit) {
        this.id = id;
        this.name = name;
        this.ramark = ramark;
        this.costPrice = costPrice;
        this.advicePrice = advicePrice;
        this.num = num;
        this.unit = unit;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getRamark() {
        return ramark;
    }

    public void setRamark(String ramark) {
        this.ramark = ramark;
    }

    public double getCostPrice() {
        return costPrice;
    }

    public void setCostPrice(double costPrice) {
        this.costPrice = costPrice;
    }

    public double getAdvicePrice() {
        return advicePrice;
    }

    public void setAdvicePrice(double advicePrice) {
        this.advicePrice = advicePrice;
    }

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getUnit() {
        return unit;
    }

    public void setUnit(String unit) {
        this.unit = unit;
    }
}

2.2.4 GoodsService(为节省时间,只为展示效果,并没有连接数据库,模拟实现)

package com.dyj.goods.service;

import com.dyj.goods.entity.Goods;
import org.springframework.stereotype.Service;

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

@Service
public class GoodsService {
    private static final Map<String, Goods> GOODS_MAP = new HashMap<>();

    static {// 准备一些静态数据,模拟数据库
        GOODS_MAP.put("1", new Goods("1","花生","备注花生",1,2.5,100,"袋"));
        GOODS_MAP.put("2", new Goods("2","啤酒","备注啤酒",20,36,200,"箱"));
        GOODS_MAP.put("3", new Goods("3","碳酸汽水","备注碳酸汽水",1.5,3,3000,"瓶"));
    }
    public Goods getGoodsById(String id){
        Goods goods=new Goods();
        for(Goods g:GOODS_MAP.values()){
            if(id.equals(g.getId())){
               goods=g;
            }
        }
        return goods;
    }


}

2.2.5 GoodsController

package com.dyj.goods.controller;

import com.dyj.goods.entity.Goods;
import com.dyj.goods.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(value="/goods")
public class GoodsController {
    @Autowired
    private GoodsService goodsService;

    /**
     * 对外提供接口服务,查询商品信息
     *
     * @param id
     * @return
     */
    @GetMapping(value="/getGoodsById")
    public Goods getGoodsById(@RequestParam(value="id") String id){
        Goods goods= goodsService.getGoodsById(id);
        return goods;
    }
}

2.2.6 GoodsMapper

package com.dyj.goods.mapper;

import com.dyj.goods.dto.GoodsDto;
import com.dyj.goods.entity.Goods;
import org.mapstruct.Mapper;


@Mapper(componentModel="spring")
public abstract class GoodsMapper {

    public abstract GoodsDto entityToDto(Goods entity);
    /**
     * 将数据传输对象转换为实体。
     *
     * @param dto 数据传输对象。
     * @return 实体。
     */
    public abstract Goods dtoToEntity(GoodsDto dto);
}

2.2.7 GoodsRest

package com.dyj.goods.rest;

import com.dyj.goods.api.GoodsApi;
import com.dyj.goods.dto.GoodsDto;
import com.dyj.goods.mapper.GoodsMapper;
import com.dyj.goods.service.GoodsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GoodsRest implements GoodsApi {
    @Autowired
    GoodsService goodsService;
    @Autowired
    GoodsMapper goodsMapper;

    @Override
    public GoodsDto getGoodsDto(@RequestParam(value = "id") String id){

        GoodsDto g=goodsMapper.entityToDto(goodsService.getGoodsById(id));
        return g;
    }
}

2.2.8 GoodsApplication(启动类)

package com.dyj.goods;

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

@SpringBootApplication(scanBasePackages = {"com.dyj.goods"})

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

在dyj-goods-web模块下的resources目录下新建一个application.properties文件,内容如下:

server.port=8082 
spring.application.name=dyj-goods

说明:GoodsMapper类是用来进行dto与entity互相转换的,GoodsRest是goods服务对外api接口的实现类

至此,goods服务结束,可以直接run GoodsApplication类,效果如下

 

步骤三:orders服务

3.1 dyj-orders-web模块的pom.xml

<?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>springcloud-test</artifactId>
        <groupId>com.dyj.test</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>dyj-orders-web</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.dyj.test</groupId>
            <artifactId>dyj-goods-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-jdk8</artifactId>
            <version>1.3.1.Final</version>
        </dependency>

        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.3.1.Final</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-ribbon -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
            <version>2.0.3.RELEASE</version>
            <exclusions>
                <exclusion>
                    <artifactId>spring-cloud-starter</artifactId>
                    <groupId>org.springframework.cloud</groupId>
                </exclusion>
            </exclusions>
        </dependency>

    </dependencies>
</project>

说明:dyj-orders-web模块依赖于dyj-goods-api

3.2 orders微服务模块:结构如下图

3.2.1 GoodsClient (两个微服务通信的关键类)

package com.dyj.orders.client;

import com.dyj.goods.api.GoodsApi;
import org.springframework.cloud.openfeign.FeignClient;


@FeignClient(value = "dyj-goods" ,url = "localhost:8082")
public interface GoodsClient  extends GoodsApi{

}

说明:@FeignClient注解 value值为依赖的微服务名字(该名字在goods服务的application.properties文件中指定)

3.2.2 Orders

package com.dyj.orders.entity;
import java.util.Date;

public class Orders {
    private String id;

    private Date date;//订单创建日期

    private String address;

    private String goodsId;

    private int saleNum;//销售数量

    public Orders() {

    }

    public Orders(String id, Date date, String address, String goodsId, int saleNum) {
        this.id = id;
        this.date = date;
        this.address = address;
        this.goodsId = goodsId;
        this.saleNum = saleNum;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getGoodsId() {
        return goodsId;
    }

    public void setGoodsId(String goodsId) {
        this.goodsId = goodsId;
    }

    public int getSaleNum() {
        return saleNum;
    }

    public void setSaleNum(int saleNum) {
        this.saleNum = saleNum;
    }
}

3.2.3 OrdersDto

package com.dyj.orders.service.dto;

import java.util.Date;

public class OrdersDto {
    private String id;

    private Date date;

    private String address;

    private int saleNum;

    private String goodsId;

    private String name;

    private double advicePrice;

    private String unit;//单位


    public OrdersDto(){}

    public OrdersDto(String id, Date date, String address, int saleNum, String goodsId, String name, double advicePrice, String unit) {
        this.id = id;
        this.date = date;
        this.address = address;
        this.saleNum = saleNum;
        this.goodsId = goodsId;
        this.name = name;
        this.advicePrice = advicePrice;
        this.unit = unit;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getSaleNum() {
        return saleNum;
    }

    public void setSaleNum(int saleNum) {
        this.saleNum = saleNum;
    }

    public String getGoodsId() {
        return goodsId;
    }

    public void setGoodsId(String goodsId) {
        this.goodsId = goodsId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getAdvicePrice() {
        return advicePrice;
    }

    public void setAdvicePrice(double advicePrice) {
        this.advicePrice = advicePrice;
    }

    public String getUnit() {
        return unit;
    }

    public void setUnit(String unit) {
        this.unit = unit;
    }
}

3.2.4 OrdersMapper

package com.dyj.orders.mapper;

import com.dyj.orders.entity.Orders;
import com.dyj.orders.service.dto.OrdersDto;
import org.mapstruct.Mapper;

@Mapper(componentModel="spring")
public abstract class OrdersMapper {


    public abstract OrdersDto entityToDto(Orders entity);
    /**
     * 将数据传输对象转换为实体。
     *
     * @param dto 数据传输对象。
     * @return 实体。
     */
    public abstract Orders dtoToEntity(OrdersDto dto);
}

3.2.5 OrdersService

package com.dyj.orders.service;

import com.dyj.goods.api.GoodsApi;
import com.dyj.goods.dto.GoodsDto;
import com.dyj.orders.entity.Orders;
import com.dyj.orders.mapper.OrdersMapper;
import com.dyj.orders.service.dto.OrdersDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class OrderService {
    private static final Map<String, Orders> ORDER_DATA = new HashMap<String, Orders>();

    @Autowired
    GoodsApi goodsApi;

    @Autowired
    OrdersMapper ordersMapper;

    static {
        // 模拟数据库
        Orders orders = new Orders();
        orders.setId("007");
        orders.setDate(new Date());
        orders.setAddress("北京市海淀区xx镇");
        orders.setSaleNum(5);
        orders.setGoodsId("2");
        ORDER_DATA.put(orders.getId(), orders);
    }

    /**
     * 根据订单id查询订单数据
     *
     * @param id
     * @return
     */
    public OrdersDto getOrderById(String id) {
        Orders orders = ORDER_DATA.get(id);
        if (null == orders) {
            return null;
        }
        // 通过商品微服务查询商品详细数据
        GoodsDto goodsDto = goodsApi.getGoodsDto(orders.getGoodsId());
        OrdersDto ordersDto= ordersMapper.entityToDto(orders);
        ordersDto.setName(goodsDto.getName());
        ordersDto.setAdvicePrice(goodsDto.getAdvicePrice());
        ordersDto.setUnit(goodsDto.getUnit());
        return ordersDto;
    }
}

3.2.6 OrdersController

package com.dyj.orders.controller;

import com.dyj.orders.service.OrderService;
import com.dyj.orders.service.dto.OrdersDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/orders")
public class OrderController {
    @Autowired
    OrderService orderService;

    @GetMapping(value = "/id")
    public OrdersDto getOrderById(@RequestParam(value = "id")String id) {
        return this.orderService.getOrderById(id);
    }
}

3.2.7 OrdersApplication(启动类)

package com.dyj.orders;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableFeignClients
@SpringBootApplication(scanBasePackages = {"com.dyj.orders"})
public class OrdersApplication {
    public static void main(String[] args){
        SpringApplication.run(OrdersApplication.class,args);
    }
}

在dyj-orderss-web模块下的resources目录下新建一个application.properties文件,内容如下:

server.port=8083 
spring.application.name=dyj-orders

至此,orders服务调用goods服务结束,现在启动两个服务,可以看到,调用orders服务提供的getOrderById方法,orders服务会去调用goods服务,查询goodsId对应的数据,再返回给orders。测试效果效果如下

 

总结:像目录分层里面的controller、service、dto、mapper、api 、rest、client,只是为了便于规范利于后续开发,此篇最重要的就是client目录下的GoodsClient类了,这也是springcloud中feign组件的初体验。

 好了,就这。。。

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐