1. Rest微服务工程构建
- 这里要做的是一个支付订单的项目
1. 单个模块的建立步骤
- 新建模块
- 修改 POM
- 编写 YAML
- 配置主启动类
- 编写业务类
2. 构建服务提供者模块
- 端口号 8001
-
新建一个 Maven 模块
cloud-provider-payment-8001 -
编写 POM 文件,引入依赖
<dependencies> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/druid --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.1.10</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
-
编写 YML 配置文件,application.yml
# 配置端口号 server: port: 8001 spring: # 配置服务名称 application: name: cloud-payment-service # 配置数据源 datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: org.gjt.mm.mysql.Driver url: jdbc:mysql://localhost:3306/spring_cloud_01?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC username: root password: 123456 # 配置 Mybatis 的包扫描 mybatis: mapperLocations: classpath:mapper/*.xml type-aliases-package: com.demo.springcloud.pojo
-
新建一个主启动类,PaymentMain8001
@SpringBootApplication public class PaymentMain8001 { public static void main(String[] args) { SpringApplication.run(PaymentMain8001.class, args); } }
-
业务类
-
建立 SQL 表
CREATE TABLE `payment` ( `id` bigint(20) NOT NULL COMMENT '编号', `serial` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '流水号', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
自己插入点数据
-
编写订单的实体类 :Payment
@Data @AllArgsConstructor @NoArgsConstructor @Accessors(chain = true) /** Lombok链式编程 */ public class Payment implements Serializable { /** 编号 */ private Long id; /** 流水号 */ private String serial; }
-
编写用于封装返回数据的实体类 :CommonResult
@Data @AllArgsConstructor @NoArgsConstructor public class CommonResult<T> { /** 返回的结果代码 */ private Integer code; /** 返回的结果的说明 */ private String message; /** 得到的结果集 */ private T data; /** 自定义一个没有结果集的情况的构造 */ public CommonResult(Integer code, String message){ this(code, message, null); } }
-
Dao:PaymentMapper
@Mapper public interface PaymentMapper { public int create(Payment payment); public Payment getPaymentById(@Param("id") Long id); }
-
Mapper : PaymentMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.demo.springcloud.dao.PaymentMapper"> <insert id="create" parameterType="Payment" useGeneratedKeys="true" keyProperty="id"> insert into payment(serial) values(${serial}); </insert> <resultMap id="BaseResultMap" type="com.demo.springcloud.pojo.Payment"> <id column="id" property="id" jdbcType="BIGINT"></id> <id column="serial" property="serial" jdbcType="VARCHAR"></id> </resultMap> <select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap"> select * from payment where id=#{id} </select> </mapper>
-
Service:PaymentService
@Mapper public interface PaymentService { public int create(Payment payment); public Payment getPaymentById(@Param("id") Long id); }
-
ServiceImpl :PaymentServiceImpl
@Service public class PaymentServiceImpl implements PaymentService { @Resource private PaymentDao paymentDao; public int create(Payment payment){ return paymentDao.create(payment); } public Payment getPaymentById( Long id){ return paymentDao.getPaymentById(id); } }
-
Controller :PaymentController
@RestController @Slf4j public class PaymentController { @Resource private PaymentService paymentService; @PostMapping(value = "/payment/create") // 这个的 @RequestBody 在测试 provider 的时候可以不写 // 但是通过 RestTemlate 远程访问该方法时,就要加上了,不然识别不到该参数 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(444,"插入数据库失败",null); } } @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(200,"查询成功",payment); }else { return new CommonResult(444,"没有对应记录,查询ID:"+id,null); } } }
注意: 这个的 @RequestBody 在测试 provider 的时候可以不写,但是通过 RestTemlate 远程访问该方法时,就要加上了,不然识别不到该参数
- 测试 provider 模块
- 测试 provider 模块
3. 构建服务消费者模块
- 端口号 80
-
新建一个 Maven 项目 :cloud-consumer-order-80
-
修改 POM 文件
<dependencies> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
-
编写 YML
server: port: 80
-
配置主启动类
@SpringBootApplication public class orderMain80 { public static void main(String[] args) { SpringApplication.run(orderMain80.class, args); } }
-
业务类
-
实体类,先把服务端的实体类复制过来
-
RestTemplate
- RestTemplate 提供了多种便捷访问远程 HTTP 服务的方法
- 是一种简单便捷的访问 RestFul 服务的模板类,是 Spring 提供的用于访问 Rest 服务的客户端模板工具
ApplicationContextConfig
@Configuration public class ApplicationContextConfig { /** 将 RestTemplate 注入 Bean */ @Bean public RestTemplate getRestTemplate(){ return new RestTemplate(); } }
-
Controller :OrderController
@RestController @Slf4j public class OrderController { public static final String PAYMENT_URL = "http://localhost:8001"; @Resource private RestTemplate restTemplate; @GetMapping("/consumer/payment/create") public CommonResult<Payment> create(Payment payment){ return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class); //写操作 } @GetMapping("/consumer/payment/get/{id}") public CommonResult<Payment> getPayment(@PathVariable("id") Long id){ return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class); } }
- 测试 consumer 模块
2. 热部署 Devtools
-
添加 devtools 依赖
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency>
-
在父工程的 POM 中配置插件
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> <addResources>true</addResources> </configuration> </plugin> </plugins> </build>
-
开启自动编译的选项
-
更新值
- 快捷键 :Ctrl + Shift + Alt + /
- 重启 IDEA
3. 系统重构
- 在上面的 provider 和 consumer 中都重复的部分,为减少代码冗余,需要进行重构、提出来
-
新建一个工程 :cloud-api-commons
这个工程中,不但可以存放重复的代码,还可以存放接口、工具类……
该工程不对外暴露
-
修改 POM 文件
<dependencies> <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--轻量级的 JAVA 工具包--> <!-- https://mvnrepository.com/artifact/cn.hutool/hutool-all --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.1.0</version> </dependency> </dependencies>
-
将重复的代码都复制过来
pojo / entities 下所有的内容
删除 provider 和 consumer 中的相关内容
-
将 cloud-api-commons 工程,打包发布到本地 Maven 仓库
为了该项目的其他工程可以方便调用
-
改造 provider 和 consumer 工程
修改 POM 文件
引入 cloud-api-commons 工程对应的坐标
<!--引入 cloud-api-commons 工程对应的坐标--> <dependency> <groupId>com.demo.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>1.0-SNAPSHOT</version> </dependency>
-
重启项目测试
4. 项目目录
- 到这里为止,基本的环境已经搭建好了,下面是项目目录