本次入门demo的业务逻辑是调用订单微服务,也就是用户下单的时候,我们要调用订单微服务下单,同时我们也可以查看我们的订单。
因此订单微服务提供2个接口,一个是创建订单接口create,一个是查看订单接口get。
一开始为啥不直接开始创建订单模块?为啥不上来就开始创建实体类,controller,service这些?公共工程又是干什么的?
原因是,在创建订单模块的时候,我们会创建一个订单的实体类Payment。同理在消费订单模块中,我们还得创建这个订单实体类Payment。而以后的实际工作业务肯定远比这个demo复杂,不可能每个模块中都保存一份实体类,如果后面出现了两边不一致的情况怎么办呢?
因此第一步是先构建一个公共工程,把公用的先构建并发布出来,供其余服务使用。同理,以后一些公用的工具类等等都可以放在这个工程中。
接着在上一篇博文的基础上,建一个新module。
鼠标右键总工程cloud 2021 -> New -> Module,得到下图
选择Maven,jdk选择1.8,点击Next
填写工程名称:cloud-api-commons
点击Finish后,得到父工程cloud 2021和新建的module,如下图。注意红框中的pom文件是父工程cloud 2021的pom文件。后面的module会越来越多,不能混为一谈。
下图为2.1中新建的pom文件
添加依赖项如下:
注:如是第一次在IDEA中导入和使用lombok,那么需要先安装lombok插件。操作如下:
点击File -> Settings -> Plugins,在联网的状态下输入lombok,找到并安装上。
安装完成后,在pom文件处,鼠标右键 ->Maven -> Reload project。
我们这边没有填写版本号version,按照上一篇博文的介绍,这里会使用父工程cloud 2021中的版本1.16.18。如下图
由于无法解析maven显示无法解析1.16.18版本,因此我回到父工程处,将lombok的版本进行了修改,尝试改成1.14.0。
如下图,此时再编译cloud api commons模块时,没有再显示lombok的报错了。
本次demo的公共模块目前主要是实体类:包含订单类和公共返回类,因此需要需要在cloud api commons中新建一个包com.example.springcloud.entities
在实体中新建一个订单类:Payment
订单类中只有2个字段:id和订单号serial
接下来需要使用maven打包发布到公共库供其他模块调用公共部分。
先maven clean
然后mvn install,发布到本地库
接下来构建订单模块,如上一篇博文所述,订单服务只提供2个接口,即创建订单接口和查看订单接口。
其次,公共实体类一共也只有2个,都在第2节的cloud-api-commons中已经创建并发布到本地库中,我们只需要引入即可。
首先建一个提供服务的module模块:cloud-provider-payment-8001
该模块的端口号为8001
鼠标右键父工程cloud2021 -> New -> Module,得到下图
选择Maven,jdk选择1.8,点击Next,得到下图。
可以看到父工程为cloud2021,输入子模块名称:cloud-provider-payment-8001。
点击Finish,得到新构建的子模块:
这个时候我们可以先看下父工程cloud2021的pom文件,如下图,可以看到,父工程下面现在有2个子工程了,也就是我们在刚刚创建的2个子工程:
第二步是修改支付模块的pom文件,修改后的pom文件如下,
<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>cloud2021artifactId>
<groupId>org.example.springcloudgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>cloud-provider-payment8001artifactId>
<dependencies>
<dependency>
<groupId>org.example.springcloudgroupId>
<artifactId>cloud-api-commonsartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.10version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.10version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
<version>1.14.0version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
project>
鼠标右键cloud-provider-payment-8001的resources文件夹 -> New -> File,新建application.properties:
application.properties的内容如下:
server.port=8001
spring.application.name=cloud-payment-service
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=org.gjt.mm.mysql.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=123
mybatis.mapperLocations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.example.springcloud.entities
鼠标右键java,新建PaymentMain8001主启动类
在mysql数据库中新建一个数据库springcloud,然后新建一个订单表payment,现在订单表的数据为空:
create database springcloud character set utf8;
use springcloud;
create table payment (
id bigint(20) not null auto_increment comment 'ID',
serial varchar(200) default '',
primary key (id)
) engine=innodb auto_increment=1 default charset=utf8;
select * from payment;
由于我们在公共工程中已经建立好了,因此这里就不用再新建了。但是我们的pom文件需要引入刚刚发布的本地工程。
新建PaymentDtao,并且提供2个方法,即创建订单和查看订单
在resources/mapper文件夹下面新建PaymentMapper.xml文件,内容如下:
DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.springcloud.dao.PaymentDao">
<insert id="create" parameterType="com.example.springcloud.entities.Payment" useGeneratedKeys="true" keyProperty="id">
insert into payment(serial) values(#{serial});
insert>
<resultMap id="BaseResultMap" type="com.example.springcloud.entities.Payment">
<id column="id" property="id" jdbcType="BIGINT"/>
<id column="serial" property="serial" jdbcType="VARCHAR"/>
resultMap>
<select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap">
select * from payment where id=#{id};
select>
mapper>
订单服务接口PaymentService,代码如下:
package com.example.springcloud.service;
import com.example.springcloud.entities.Payment;
import org.apache.ibatis.annotations.Param;
public interface PaymentService {
/**
* 创建订单
*/
public int create(Payment payment);
/**
* 根据id查询订单
*/
public Payment getPaymentById(@Param("id") Long id);
}
订单服务接口实现类PaymentServiceImpl,代码如下:
package com.example.springcloud.service.impl;
import com.example.springcloud.dao.PaymentDao;
import com.example.springcloud.entities.Payment;
import com.example.springcloud.service.PaymentService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class PaymentServiceImpl implements PaymentService {
@Resource
private PaymentDao paymentDao;
@Override
public int create(Payment payment) {
return paymentDao.create(payment);
}
@Override
public Payment getPaymentById(Long id) {
return paymentDao.getPaymentById(id);
}
}
构建订单controller:PaymentController,代码如下:
package com.example.springcloud.controller;
import com.example.springcloud.entities.CommonResult;
import com.example.springcloud.entities.Payment;
import com.example.springcloud.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
@RestController
@Slf4j
public class PaymentController {
@Resource
private PaymentService paymentService;
@PostMapping(value = "/payment/create")
public CommonResult create(@RequestBody Payment payment) {
int result = paymentService.create(payment);
log.info("插入结果" + result);
if (result > 0) {
return new CommonResult(200, "插入数据库成功", result);
} else {
return new CommonResult(500, "插入数据失败");
}
}
@GetMapping(value = "/payment/get/{id}")
public CommonResult getPaymentById(@PathVariable("id") Long id) {
Payment payment = paymentService.getPaymentById(id);
log.info("读取订单: " + payment);
if (payment==null) {
return new CommonResult(500, "未查询到该订单,查询id: " + id);
} else {
return new CommonResult(200, "查询成功", payment);
}
}
}
启动模块主启动类:PaymentMain8001。如下图,可以看到8001端口的订单服务已经启动。
创建订单类是post方法,使用postman发送一个创建订单请求,订单号是:cloth-00001
如上图所示,postman显示插入数据库成功。
如下图所示,在mysql里面确实看到了刚刚调用服务所插入的订单号:
通过查询数据库可以看到,id为3,我们可以再测试下获取订单接口:
到此,订单微服务就已经构建并测试完成。
构建消费订单模块:cloud-consumer-order-80,由于使用1024以下的端口则需要root权限,为了避免报错,我们设置消费订单模块的端口号为:8080
鼠标右键cloud2021 -> New -> Module,选择Maven,jdk选择1.8
此时,可以看到父工程下已经有3个子模块了:
消费订单模块的pom文件现在可以直接复制订单服务中的pom文件中用到的组件了,pom文件内容如下:
<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>cloud2021artifactId>
<groupId>org.example.springcloudgroupId>
<version>1.0-SNAPSHOTversion>
parent>
<modelVersion>4.0.0modelVersion>
<artifactId>cloud-consumer-order-80artifactId>
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>org.example.springcloudgroupId>
<artifactId>cloud-api-commonsartifactId>
<version>1.0-SNAPSHOTversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-configuration-processorartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
<version>1.14.0version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
project>
该服务的application.properties只需要填写服务的端口号:8080
由于我们的demo业务逻辑比较简单,因此消费订单模块的业务类中就不再需要Service,Mapper,Mysql等,因此刚刚的pom文件中也没有导入这些模块。
现在我们的消费订单模块要调用订单服务的接口时,由于两个模块可能部署在不同的服务器上面,因此我们需要构建远程调用Http服务的方法,此时可以使用RestTemplate。
RestTemplate提供了多种便捷访问远程http服务的方法,是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集。
使用方式:一般仅使用3个参数:
url:rest请求地址
requestMap:请求参数
responseBean.class:http响应转换被转换成的对象类型
OrderController类的代码如下:
package com.example.springcloud.controller;
import com.example.springcloud.entities.CommonResult;
import com.example.springcloud.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
@RestController
@Slf4j
public class OrderController {
public static final String PAYMENT_URL = "http://localhost:8001";
@Resource
private RestTemplate restTemplate;
@GetMapping(value = "/consumer/payment/create")
public CommonResult create(Payment payment) {
return restTemplate.postForObject(PAYMENT_URL+"/payment/create", payment, CommonResult.class);
}
@GetMapping(value = "/consumer/payment/get/{id}")
public CommonResult getPayment(@PathVariable("id") Long id) {
return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id, CommonResult.class);
}
}
启动订单服务:cloud-provider-payment-8001
和消费订单服务类:cloud-consumer-order-80
在订单接口模块中,已经创建了一个订单:{id=4, serial=cloth00001},所以我们先测试获取订单接口。
通过下图可以看到,我们调用8080端口的消费订单服务,已经成功获取到了3号订单的内容。
本次创建一个水果相关的订单:fruit-00001
由以上2图可以看到,通过8080端口,我们也成功地创建了接口。
到这里,我们就完成了spring cloud的入门demo,即通过8080端口模拟远程调用另一台服务器上的订单服务,从而完成创建订单和查看订单。