行业知识
SpringCloud 微服务架构编码构建
一、前言
�� 接下来是开展一系列的 SpringCloud 的学习之旅,从传统的模块之间调用,一步步的升级为 SpringCloud 模块之间的调用,此篇文章为第一篇,即不使用 SpringCloud 组件进行模块之间的调用,后续会有很多的文章循序渐进的添加和融合SpringCloud 组件。慢慢来。
二、工程创建
2.1 创建父工程
创建一个空的父 maven工程 SpringCloud,pom.xml 内容如下所示,SpringCloud 采用的是 H 版本,SpringBoot 采用的是 2.2.2 版本。
4.0.0 com.springcloud SpringCloud 1.0-SNAPSHOT pom cloud-provider-payment8001 cloud-consumer-order80 cloud-api-commons UTF-8 1.8 1.8 4.12 1.2.17 1.16.18 5.1.47 1.1.16 1.3.0 org.springframework.boot spring-boot-dependencies 2.2.2.RELEASE pom import org.springframework.cloud spring-cloud-dependencies Hoxton.SR1 pom import com.alibaba.cloud spring-cloud-alibaba-dependencies 2.1.0.RELEASE pom import mysql mysql-connector-java ${mysql.version} com.alibaba druid ${druid.version} org.mybatis.spring.boot mybatis-spring-boot-starter ${mybatis.spring.boot.version} junit junit ${junit.version} log4j log4j ${log4j.version} org.projectlombok lombok ${lombok.version} true org.springframework.boot spring-boot-maven-plugin 2.2.2.RELEASE true true 2.2 创建支付模块
在父工程中创建 cloud-provider-payment8001 子模块,为其他的模块提供服务,pom.xml 内容如下所示:
4.0.0 com.springcloud SpringCloud 1.0-SNAPSHOT cloud-provider-payment8001 com.springcloud cloud-api-commons ${project.version} org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.mybatis.spring.boot mybatis-spring-boot-starter com.alibaba druid-spring-boot-starter 1.1.10 mysql mysql-connector-java org.springframework.boot spring-boot-starter-jdbc org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test application.yml 的内容如下所示:
server: port: 8001spring: 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/db2019?useUnicode=true&characterEncoding=utf-8&useSSL=false username: root password: 123456mybatis: mapperLocations: classpath:mapper/*.xml type-aliases-package: com.springcloud.entities
主启动类的内容如下所示:
package com.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@SpringBootApplicationpublic class PaymentMain8081 { public static void main(String[] args) { SpringApplication.run(PaymentMain8081.class,args); }} 建表语句如下:
create DATABASE db2019;use db2019;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=utf8insert into payment values(1,'我爱哇哈哈');
dao 层代码如下所示:
package com.springcloud.dao;import com.springcloud.entities.Payment;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Param;@Mapperpublic interface PaymentDao { int create(Payment payment); Payment selectPaymentById(@Param("id") Long id);} mapper.xml 内容如下所示:
INSERT INTO payment(SERIAL) VALUES(#{serial}); SELECT * FROM payment WHERE id=#{id}; service 层代码如下所示:
package com.springcloud.service;import com.springcloud.entities.Payment;public interface PaymentService { int create(Payment payment); Payment selectPaymentById( Long id);} package com.springcloud.service.impl;import com.springcloud.dao.PaymentDao;import com.springcloud.entities.Payment;import com.springcloud.service.PaymentService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class PaymentServiceImpl implements PaymentService { @Autowired PaymentDao paymentDao; @Override public int create(Payment payment) { return paymentDao.create(payment); } @Override public Payment selectPaymentById(Long id) { return paymentDao.selectPaymentById(id); }} controller 层代码如下所示:
package com.springcloud.controller;import com.springcloud.entities.CommonResult;import com.springcloud.entities.Payment;import com.springcloud.service.PaymentService;import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;import lombok.extern.slf4j.Slf4j;@RestController@Slf4jpublic class PaymentController { @Resource PaymentService paymentService; @PostMapping("/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(404,"插入失败",null); } } @GetMapping("/payment/get/{id}") public CommonResult selectPaymentById(@PathVariable("id") Long id){ Payment payment = paymentService.selectPaymentById(id); log.info("*****查询操作返回结果:" + payment); if(payment != null){ int a =2; return new CommonResult(200,"查询成功",payment); }else{ return new CommonResult(404,"未查询到数据"+id,null); } }} 至此,支付模块创建完成,此模块可以对外提供新增和查询数据的功能。
2.3 创建订单模块
创建 cloud-consumer-order80 订单模块,使用户可以通过统一的经过订单模块调用支付模块,pom.xml 内容如下所示:
4.0.0 com.springcloud SpringCloud 1.0-SNAPSHOT cloud-consumer-order80 8 8 UTF-8 com.springcloud cloud-api-commons ${project.version} org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-actuator org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test application.yml 的内容如下所示:
server: port: 80
主启动类的内容如下所示:
package com.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.cloud.netflix.eureka.EnableEurekaClient;@SpringBootApplicationpublic class OrderMain80 { public static void main(String[] args) { SpringApplication.run(OrderMain80.class,args); }} 由于远程调用需要使用 RestTemplate 类,所以需要创建一个配置类,内容如下所示:
package com.springcloud.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.client.RestTemplate;@Configurationpublic class ApplicationContextConfig { @Bean public RestTemplate restTemplate(){ return new RestTemplate(); }} controller 层代码如下所示:
package com.springcloud.controller;import com.springcloud.entities.CommonResult;import com.springcloud.entities.Payment;import lombok.extern.slf4j.Slf4j;import org.springframework.web.bind.annotation.*;import org.springframework.web.client.RestTemplate;import javax.annotation.Resource;@RestController@Slf4jpublic class OrderController { @Resource private RestTemplate restTemplate; public static final String PaymentSrv_URL = "http://localhost:8001"; @GetMapping("/consumer/payment/create") public CommonResult create(Payment payment){ // 客户端用浏览器是get请求,但是底层实质发送post调用服务端8001 return restTemplate.postForObject(PaymentSrv_URL+"/payment/create",payment,CommonResult.class); } @GetMapping("/consumer/payment/get/{id}") public CommonResult getPayment(@PathVariable Long id) { return restTemplate.getForObject(PaymentSrv_URL + "/payment/get/"+id, CommonResult.class, id); }} 2.4 创建通用模块
创建 cloud-api-commons 通用模块,给其他的子模块提供公共服务用的,pom.xml 内容如下所示:
4.0.0 com.springcloud SpringCloud 1.0-SNAPSHOT com.springcloud cloud-api-commons 8 8 UTF-8 org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true cn.hutool hutool-all 5.1.0
两个实体类的代码如下所示:
package com.springcloud.entities;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import lombok.ToString;@Data@AllArgsConstructor@NoArgsConstructor@ToStringpublic class CommonResult { private Integer code; private String message; private T data; private CommonResult(Integer code,String message){ this(code,message,null); }} package com.springcloud.entities;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.io.Serializable;@Data@AllArgsConstructor@NoArgsConstructorpublic class Payment implements Serializable { private Long id; private String serial;} 三、测试
现在的调用流程为:浏览器访问订单模块对外提供的服务,然后订单模块再调用支付模块完成服务的调用,在浏览器输入 http://localhost:80/consumer/payment/create?serial=4567 测试插入功能,如下图:
在浏览器输入 http://localhost:80/consumer/payment/get/1 测试查询功能,如下图