注:本篇文章主要参考周阳老师讲解的cloud进行整理的!
本章主要以order订单服务来远程调用payment支付服务为例,当然这里只是简单的一个远程调用,没有太复杂的逻辑,重点是要掌握的是maven的聚合工程搭建
,微服务分模块的思想,每一个步骤我都会详细记录,并且文章下方还提供了git源码地址!
最后要实现的代码结构:
框架:mybatis-plus3.4 + springboot2.2.5 + mysql + springcloud的H版本 + spring-cloud-alibaba2.1.0 + maven
本章并不会用到springcloud相关组件,只是在父工程声明了版本!
约定 > 配置 > 编码
<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.0modelVersion>
<groupId>com.gzl.cngroupId>
<artifactId>mscloudartifactId><packaging>pompackaging>
<version>1.0-SNAPSHOTversion>
<modules>
<module>cloud-provider-payment8001module>
modules>
<properties>
<project.build.sourceEncoding>UTF-8project.build.sourceEncoding>
<maven.compiler.source>1.8maven.compiler.source>
<maven.compiler.target>1.8maven.compiler.target>
<junit.version>4.12junit.version>
<log4j.version>1.2.17log4j.version>
<lombok.version>1.16.18lombok.version>
<mysql.version>5.1.47mysql.version>
<druid.version>1.1.16druid.version>
<mybatis-plus.boot.version>3.4.0mybatis-plus.boot.version>
properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>2.2.2.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>org.springframework.cloudgroupId>
<artifactId>spring-cloud-dependenciesartifactId>
<version>Hoxton.SR1version>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-alibaba-dependenciesartifactId>
<version>2.1.0.RELEASEversion>
<type>pomtype>
<scope>importscope>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>${mysql.version}version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>${druid.version}version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>${mybatis-plus.boot.version}version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>${junit.version}version>
dependency>
<dependency>
<groupId>log4jgroupId>
<artifactId>log4jartifactId>
<version>${log4j.version}version>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<version>${lombok.version}version>
<optional>trueoptional>
dependency>
dependencies>
dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-surefire-pluginartifactId>
<configuration>
<skip>trueskip>
configuration>
plugin>
plugins>
build>
project>
关于maven依赖 ${xxx.version}报错问题:不用管他,当我们有了子项目之后,这里就不报错了。
Maven 使用dependencyManagement
元素来提供了一种管理依赖版本号的方式。
通常会在一个组织或者项目的最顶层的父POM 中看到dependencyManagement 元素。
作用: pom.xml 中的dependencyManagement 元素能让所有在子项目中引用一个依赖而不用显式的列出版本号。 Maven 会沿着父子层次向上走,直到找到一个拥有dependencyManagement 元素的项目,然后它就会使用这个dependencyManagement 元素中指定的版本号。
例如在父项目里:xml代码
<dependencyManagement>
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
dependencies>
dependencyManagement>
然后在子项目里就可以添加mysql-connector时可以不指定版本号,例如:xml代码
<dependencies>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
dependencies>
好处: 如果有多个子项目都引用同一样依赖,则可以避免在每个使用的子项目里都声明一个版本号,这样当想升级或切换到另一个版本时,只需要在顶层父容器里更新,而不需要一个一个子项目的修改 ;另外如果某个子项目需要另外的一个版本,只需要声明version就可以。
注意:
dependencyManagement里只是声明依赖,并不实现引入,因此子项目需要显示的声明需要用的依赖。
如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,
才会从父项目中继承该项,并且version和scope都读取自父pom;
如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。
父工程创建完成执行mvn:install将父工程发布到仓库方便子工程继承
创建过后的项目结构:
(1)、删掉无用的文件
(2)、创建cloud-provider-payment8001项目
右键项目-》new-》Module
(3)、改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>mscloudartifactId><groupId>com.gzl.cngroupId><version>1.0-SNAPSHOTversion>parent>
<modelVersion>4.0.0modelVersion>
<artifactId>cloud-provider-payment8001artifactId>
<properties>
<maven.compiler.source>8maven.compiler.source>
<maven.compiler.target>8maven.compiler.target>
properties>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-actuatorartifactId>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druid-spring-boot-starterartifactId>
<version>1.1.10version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-jdbcartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
dependencies>
project>
(4)、写yml
server:
port: 8001
spring:
application:
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/db2022?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: root
# mybatis-plus配置打印sql日志
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
(5)、创建表
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
(6)、创建启动类
@SpringBootApplication
@MapperScan("com.gzl.cn.mapper")
public class PaymentMain8001 {
public static void main(String[] args) {
SpringApplication.run(PaymentMain8001.class, args);
}
}
(7)、创建实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("payment")
public class Payment implements Serializable {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@TableField(value = "serial")
private String serial;
}
这个类用于作为controller统一接口返回参数类
@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);
}
}
(8)、创建mapper类
@Repository
public interface PaymentMapper extends BaseMapper<Payment> {
}
(9)、创建controller类
@RestController
@Slf4j
public class PaymentController {
@Autowired
private PaymentMapper paymentMapper;
@PostMapping(value = "/payment/create")
public CommonResult create(@RequestBody Payment payment) {
int result = paymentMapper.insert(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<Payment> getPaymentById(@PathVariable("id") Long id) {
Payment payment = paymentMapper.selectById(id);
log.info("*****查询结果:{}", payment);
if (payment != null) {
return new CommonResult(200, "查询成功", payment);
} else {
return new CommonResult(444, "没有对应记录,查询ID: " + id, null);
}
}
}
(10)、测试一下两个接口,确保接口可以正常访问
创建过后的项目结构:
(1)、创建cloud-provider-payment8001项目
(2)、改pom(pom跟上个model的pom一样就行)
(3)、写yml(跟上面的model也一样,端口不一样,名称不一样)
server:
port: 80
spring:
application:
name: cloud-order-service
(4)、主启动
(5)、创建配置类,远程调用我用的RestTemplate,所以这个配置类主要就是把RestTemplate注入到容器
@Configuration
public class ApplicationContextConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
(6)、创建实体类(跟上个服务的实体类一模一样)
(7)、创建controller
@RestController
public class OrderController {
public static final String PaymentSrv_URL = "http://localhost:8001";
@Autowired
private RestTemplate restTemplate;
@GetMapping("/consumer/payment/create") //客户端用浏览器是get请求,但是底层实质发送post调用服务端8001
public CommonResult create(Payment payment) {
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);
}
}
(8)、测试接口
(1)、观察问题,我们可以创建一个model来专门存放公用的 entity 或者 util 等等,甚至共用的pom依赖我们都可以放到这个里面来。
假如要是存放公用的依赖一定要注意点,例如mysql的依赖,一旦放到公共的model里面,那也就是意味着只要是web的模块引入了公用model,就需要配置mysql,否则项目启动就会报错!所以向model存放公用依赖的时候一定要慎重!
(2)、新建cloud-api-common
(3)、创建pom
<dependencies>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>cn.hutoolgroupId>
<artifactId>hutool-allartifactId>
<version>5.1.0version>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-annotationartifactId>
<version>3.4.0version>
<scope>compilescope>
dependency>
dependencies>
(4)、将entity放到这个项目当中
(5)、maven命令clean install一下,或者可以在这里clean install
clean install就是打成jar包放到我们的maven本地仓库当中,然后我们别的项目就可以通过坐标来引用他。
(6)、删除各自的原先有过的entity文件夹
(7)、添加依赖,在8001和80的model当中添加,让他引入我们自己的common
<dependency>
<groupId>com.gzl.cngroupId>
<artifactId>cloud-api-commonartifactId>
<version>${project.version}version>
dependency>
创建过后的项目结构:
git源码:https://gitee.com/gzl_com/spring-cloud.git