SpringCloud04-编码实现:订单支付模块

    科技2022-08-10  100

    SpringCloud04-编码实现:订单支付模块

    SpringCloud系列文档地址: SpringCloud 进阶之路

    1、IDEA新建空的父Project IDEA和Eclipse不同,没有工作空间的概念,所以我们都是创建一个空的父Project,然后在里面New Module。

    1.1 配置Maven 在创建Project之前,需要先配置我们的maven,要求maven的版本是3.5以上,File——Other Settings——Settings For New Projects:

    1.2 创建空父Project 1.2.1 创建一个Project:springcloud2020 File —— New —— Project:JDK要求1.8

    1.2.2 配置字符编码

    1.2.3 开启注解生效

    1.2.4 选择Java编译版本为1.8

    1.2.5 FileType文件过滤,删除src目录 因为创建的工程中,会出现后缀为 .idea 和 .iml 的文件,为了不显示他们,可以设置FileType,过滤掉他们:

    因为父工程不会写代码,所以删除src目录。只留下一个pom.xml文件即可。

    1.3 父工程的pom文件

    <?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.zdw.springcloud</groupId> <artifactId>springcloud2020</artifactId> <version>1.0-SNAPSHOT</version> <modules> <module>cloud-provider-payment8001</module> </modules> <!--打包方式--> <packaging>pom</packaging> <!--统一管理jar包版本--> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <junit.version>4.12</junit.version> <log4j.version>1.2.17</log4j.version> <lombok.version>1.16.18</lombok.version> <mysql.version>8.0.19</mysql.version> <druid.version>1.1.16</druid.version> <spring.boot.version>2.2.2.RELEASE</spring.boot.version> <spring.cloud.version>Hoxton.SR1</spring.cloud.version> <spring.cloud.alibaba.version>2.1.0.RELEASE</spring.cloud.alibaba.version> <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version> <druid.spring.boot.starter.version>1.1.1</druid.spring.boot.starter.version> </properties> <!--子模块继承后,提供作用:锁定版本+子module不用groupId和version--> <dependencyManagement> <dependencies> <!--springboot 2.2.2--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring.boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!--Spring cloud Hoxton.SR1--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring.cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!--Spring cloud alibaba 2.1.0.RELEASE--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring.cloud.alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>${mysql.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>${druid.version}</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>${druid.spring.boot.starter.version}</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </dependency> <!--MyBatis的依赖--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>${mybatis.spring.boot.version}</version> </dependency> </dependencies> </dependencyManagement> <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> <!--第三方maven私服--> <repositories> <repository> <id>nexus-aliyun</id> <name>Nexus aliyun</name> <url>http://maven.aliyun.com/nexus/content/groups/public</url> <releases> <enabled>true</enabled> </releases> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> </project>

    dependencyManagement 和 dependency 的区别:

    1、dependencyManagement 一般只会出现在父pom文件中,它可以让子项目引入依赖只会,不用显示的指定版本号,做到统一管理版本的目的。Maven会沿着父子层次向上走,直到找到一个有dependencyManagement 元素的项目,然后就会使用 dependencyManagement 指定的版本号;所以在子项目中可以不显示的指定版本号。

    2、如果子项目中没有声明依赖,是不会从父项目中继承下来的;只有在子项目中声明了该依赖项,并且没有指定具体的版本,才会从父项目中继承下来;

    3、如果子项目中显示声明了版本号,那么就会使用子项目中指定的版本的依赖。

    这样做的好处就是:如果有多个子项目都引用同一样的依赖,则可以避免在每个使用的子项目里都声明一个版本号,这样想升级或切换到另一个版本时,只需在顶层父容器里更新,而不需要一个一个子项目的修改l;另外如果某个子项目需要另外的一个版本,只需声明version版本 。

    2、支付模块payment8001 2.1 五个步骤和sql文件

    1、建Module 2、改pom文件 3、写yml文件 4、写主启动类 5、编写业务逻辑

    sql文件: CREATE TABLE payment ( id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT ‘主键’, serial VARCHAR(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT ‘支付流水号’, PRIMARY KEY (id) USING BTREE ) ENGINE = INNODB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = ‘支付表’ ROW_FORMAT = DYNAMIC;

    2.2 创建Module 在刚才创建的SpringCloud2020,右键 New —— Module ,JDK选择1.8,不要使用Maven骨架:

    2.3 改pom文件

    <?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>springcloud2020</artifactId> <groupId>com.zdw.springcloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloud-provider-payment8001</artifactId> <description>支付模块</description> <dependencies> <!--web和actuator基本是绑定到一块使用的--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--监控--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--MyBatis的依赖--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <!--如果没写版本,从父层面找,找到了就直接用,全局统一--> <!--<version>1.1.1</version>--> </dependency> <!--mysql-connector-java--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--jdbc--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <!--热部署--> <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> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>

    2.4 写yml

    server: port: 8001 spring: application: name: cloud-payment-service datasource: # 当前数据源操作类型 type: com.alibaba.druid.pool.DruidDataSource # mysql驱动类 driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/cloud2020?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=GMT+8 username: root password: 123 mybatis: mapper-locations: classpath*:mapper/*.xml type-aliases-package: com.zdw.springcloud.entities

    2.5 编写主启动类

    package com.zdw.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class PaymentMain8001 { public static void main(String[] args) { SpringApplication.run(PaymentMain8001.class,args); } }

    2.6 编写业务代码 参见4

    3、公共模块common 因为项目中很多地方都要用到一些实体和工具类,如果在每个工程中都要创建肯定是不行的。对于这种公共的东西,我们应该进行抽取,所以可以创建一个cloud-api-common模块,里面主要存放的就是相关的实体类和工具类:

    创建cloud-api-common模块的方式和payment8001是一样的,不要选maven骨架,创建之后,修改pom文件:

    3.1 改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>springcloud2020</artifactId> <groupId>com.zdw.springcloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloud-api-common</artifactId> <description>公共模块</description> <dependencies> <!-- 热部署 --> <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> <!-- 糊涂工具类的依赖 --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>${hutool-all.version}</version> </dependency> </dependencies> </project>

    注意:里面引入了hutool工具类,它的官网地址是: https://hutool.cn/docs/#/ ,它对很多我们常用的进行了封装,我们可以直接使用。

    3.2 创建实体 3.2.1 编写Payment

    package com.zdw.springcloud.entities; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; @Data //get/set以及toString方法 @NoArgsConstructor //无参构造 @AllArgsConstructor //有参构造 public class Payment implements Serializable { private Long id; /** * 支付流水号 */ private String serial; }

    3.2.2 编写统一的返回结果类

    package com.zdw.springcloud.entities; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data //get/set以及toString方法 @NoArgsConstructor //无参构造 @AllArgsConstructor //有参构造 public class CommonResult<T> { private Integer code; private String message; private T data; public CommonResult(Integer code, String message) { this(code, message, null); } }

    创建完成之后,我们需要执行install操作,安装到我们的仓库里面,然后其他的模块才能引入它。

    4、编写支付模块payment8001的业务代码 4.1 改pom.xml 因为我们的业务代码需要用到cloud-api-common的实体类,所以需要在pom.xml文件中添加cloud-api-common的依赖:

    <!--引入公共模块的依赖--> <dependency> <groupId>com.zdw.springcloud</groupId> <artifactId>cloud-api-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency>

    4.2 编写dao

    package com.zdw.springcloud.dao; import com.zdw.springcloud.entities.Payment; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; @Mapper public interface PaymentDao { /** * 新增 * @param payment */ int create(Payment payment); /** * 根据Id查询 * @param id */ Payment getPaymentById(@Param("id") Long id); }

    注意:类上要用 @Mapper 注解修饰,表明这是一个MyBatis的Mapper接口

    4.3 编写service业务层代码 4.3.1 service业务接口

    package com.atguigu.springcloud.service; import com.atguigu.springcloud.entities.Payment; public interface PaymentService { /** * 新增 */ int create(Payment payment); /** * 根据Id查询 */ Payment getPaymentById(Long id); }

    4.3.2 service实现类

    package com.atguigu.springcloud.service.impl; import com.atguigu.springcloud.dao.PaymentDao; import com.atguigu.springcloud.entities.Payment; import com.atguigu.springcloud.service.PaymentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class PaymentServiceImpl implements PaymentService { @Autowired private PaymentDao paymentDao; /** * 新增 */ @Override public int create(Payment payment) { return paymentDao.create(payment); } /** * 根据Id查询 */ @Override public Payment getPaymentById(Long id) { return paymentDao.getPaymentById(id); } }

    4.4 编写controller

    package com.zdw.springcloud.controller; import com.zdw.springcloud.entities.CommonResult; import com.zdw.springcloud.entities.Payment; import com.zdw.springcloud.service.PaymentService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.*; @RestController @Slf4j //日志记录,添加这个注解之后,可以直接使用 log public class PaymentController { @Autowired PaymentService paymentService; @Value("${server.port}")//从配置文件中获取server.port的值 String serverPort; @PostMapping(value = "payment/create") public CommonResult create(@RequestBody Payment payment){ int result = paymentService.create(payment); if(result>0){ return new CommonResult(200,"++插入数据库成功,serverPort:" + serverPort, result); } return new CommonResult(444,"--插入数据库失败,serverPort:" + serverPort, null); } @GetMapping(value = "payment/get/{id}") public CommonResult<Payment> get(@PathVariable("id") Long id){ Payment payment = paymentService.getPaymentById(id); log.info("*****查询结果: " + payment); if (payment != null) { return new CommonResult(200, "查询成功,serverPort:" + serverPort, payment); } return new CommonResult(444, "没有对应记录,查询ID:" + id, null); } }

    注意:类上使用@RestController注解,相当于 @ResponseBody和@Controller,返回的json数据;

    create(@RequestBody Payment payment) :注意create方法的形参一定要使用@RequestBody进行修饰,否则,数据保存就会不成功。

    4.5 测试 4.5.1 测试create进行新增操作 需要用到PostMan工具类,因为浏览器地址不支持post请求:

    返回结果成功:

    { “code”: 200, “message”: “++插入数据库成功111,serverPort:8001”, “data”: 1 }

    4.5.2 测试get方法获取数据 直接浏览器访问:http://localhost:8001/payment/get/1 能访问到数据就是成功了,建议使用火狐浏览器,它能格式化json数据

    5、热部署devtools 为了方便修改代码,进行调试的方便,我们希望修改之后立马生效,而不是重启工程。Spring为我们提供了热部署操作。热部署需要执行以下几步:

    5.1 添加devtools依赖 在需要热部署的工程的pom文件中,引入devtools依赖:

    org.springframework.boot spring-boot-devtools runtime true

    之前的工程payment8001在前面以及引入了该依赖。

    5.2 添加一个maven插件 在pom文件中添加下面的maven插件,本次我们可以在父Project的pom文件中添加,这样子项目就都可以使用了:

    <build> <fileName>你自己的工程名字<fileName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork> <addResources>true</addResources> </configuration> </plugin> </plugins> </build>

    5.3 IDEA开启自动构建

    5.4 IDEA开启热注册,更新我们的值 快捷键:crtl+shift+alt+/ 选择第一个 registry

    5.5 重启IDEA 然后我们修改之后,idea就会自动编译,能立马看到结果以及改了。

    6、订单模块order80 6.1 创建module 6.2 改pom

    <?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>springcloud2020</artifactId> <groupId>com.zdw.springcloud</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>cloud-consumer-order80</artifactId> <description>订单消费者</description> <dependencies> <!--引入公共模块--> <dependency> <groupId>com.zdw.springcloud</groupId> <artifactId>cloud-api-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!--web和actuator监控 一般要一起--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <!--热部署--> <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> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> </project>

    6.3 写yml

    server: port: 80 spring: application: name: cloud-consumer-order

    6.4 主启动类OrderMain80

    package com.zdw.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class OrderMain80 { public static void main(String[] args) { SpringApplication.run(OrderMain80.class,args); } }

    6.5 业务编码 6.5.1 注册RestTemplate RestTemplate提供了多种便捷访问远程Http服务的方法,是一种简单便捷的访问RESTful服务的模板类,是Spring提供的用于访问Rest服务的客户端模板工具集;

    官方网址: https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

    package com.zdw.springcloud.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class OrderConfig { /** * 注册RestTemplate * @return */ @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } }

    6.5.2 编写controller 客户端80是通过远程调用8001的支付服务的,所以它只要一个Controller来接受请求就可以了,不需要编写service和dao等;

    package com.zdw.springcloud.controller; import com.zdw.springcloud.entities.CommonResult; import com.zdw.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 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> get(@PathVariable("id") Long id){ log.info("====从80去查询了8001支付模块...."); return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class); } }

    6.6 测试 浏览器访问:http://localhost/consumer/payment/create?serial=zdw19910904 新增数据成功。

    浏览器访问:http://localhost/consumer/payment/get/2 可以查询到刚才新增的数据

    本次课程的讲解是尚硅谷的周阳老师,如有需要请购买正版书籍或网上到尚硅谷官网进行学习。

    Processed: 0.031, SQL: 8