1.开发步骤(实用)
- 建module
- 改pom
- 写yml
- 主启动
- 写业务类
前后端分离,后端传json字符串给前端,前端不需要了解后端的具体业务,前端按照约定和规范判断里面的编码是不是成功,成功的话就去完成逻辑的展现
2.搭建父工程
1.新建空项目
2.在空项目中建父项目
删除src无关文件
3.配置JDK版本
4.在父工程中导入相关依赖
注意:
- 父工程dependencyManagement中管理的依赖在你们仓库中可能没有,所以要注释掉dependencyManagement先下载对应版本的依赖
- dependencyManagement只是声明依赖,并不实现引入,因此子项目需要显示声明需要用的依赖
- 子模块继承之后,提供作用:锁定版本并且子modlue不用写groupId和version
- 如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并没有指定具体版本,才会从父项目中继承该项依赖,并且version和scope都取自父pom
- 如果子项目中指定了版本号,则使用子项目指定的jar版
<!--统一管理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.27</mysql.version>
<druid.verison>1.2.6</druid.verison>
<mybatis.spring.boot.verison>1.3.0</mybatis.spring.boot.verison>
</properties>
<!--子模块继承之后,提供作用:锁定版本+子modlue不用写groupId和version-->
<!--dependencyManagement只是声明依赖,并不实现引入,因此子项目需要显示声明需要用的依赖-->
<!--如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并没有指定具体版本,才会从父项目中继承该项依赖,并且version和scope都取自父pom-->
<!--如果子项目中指定了版本号,则使用子项目指定的jar版本-->
<dependencyManagement>
<dependencies>
<!--spring boot 2.2.2-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.2.2.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--spring cloud Hoxton.SR1-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</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>2.2.0.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- MySql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.verison}</version>
</dependency>
<!-- mybatis-springboot整合 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.spring.boot.verison}</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.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>
5.创建数据库
CREATE DATABASE /*!32312 IF NOT EXISTS*/`cloud` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci */;
USE `cloud`;
/*Table structure for table `payment` */
DROP TABLE IF EXISTS `payment`;
CREATE TABLE `payment` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`serial` varchar(200) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
/*Data for the table `payment` */
insert into `payment`(`id`,`serial`) values (1,'尚硅谷'),(2,'alibaba'),(3,'京东'),(4,'头条');
3.搭建cloud-provider-payment8001子工程
1.在父工程下创建cloud-provider-payment8001子工程
2.在子工程中导入相关依赖
<dependencies>
<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.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<!--mysql-connection-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>
</dependency>
</dependencies>
3.在子工程中新建application.yml文件
注意:
- MySQL5用的驱动url是com.mysql.jdbc.Driver
- MySQL6以后用的是com.mysql.cj.jdbc.Driver
server:
port: 8001 #服务端口
spring:
application:
#设置当前应用的名称,将来会在eureka中显示。将来需要该名称来获取路径
name: cloud-payment-service
datasource:
type: com.alibaba.druid.pool.DruidDataSource #当前数据源操作类型
driver-class-name: com.mysql.cj.jdbc.Driver #数据库驱动包
#characterEncoding=UTF-8 指定所处理字符的解码和编码的格式
#useSSL=false MySQL在高版本需要指明是否进行SSL连接 1.true 需要连接 2.false 不需要连接
#serverTimezone 配置连接数据库驱动的时区参数
#TC代表的是全球标准时间,是以原子时计时,更加精准,适应现代社会的精确计时。
#GMT格林威治标准时间,是指位于伦敦郊区的皇家格林尼治天文台的标准时间。
#但是我们使用的时间是北京时区也就是东八区,领先UTC和GMT八个小时。
#一般视为无差别,即:北京时间=UTC+8=GMT+8。
#rewriteBatchedStatements 这个参数允许JDBC连接能够一次执行多条增删改查,假如没配这个参数的话,所有批量操作都会报错。
#MySQL的JDBC连接的url中要加rewriteBatchedStatements参数,并保证5.1.13以上版本的驱动,才能实现高性能的批量插入。
#MySQL JDBC驱动在默认情况下会无视executeBatch()语句,
#把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,
#批量插入实际上是单条插入,直接造成较低的性能。
#只有把rewriteBatchedStatements参数置为true, 驱动才会帮你批量执行SQL
#另外这个选项对INSERT/UPDATE/DELETE都有效
url: jdbc:mysql://localhost:3306/cloud?characterEncoding=UTF-8&&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true
username: root
password: 123456
devtools:
restart:
enabled: true
mybatis:
#如果mapper类和mapper.xml不在同一个路径下的时候,可以指定mapper.xml的路径
#1.classpath:只会到你的classes路径中查找找文件。
#2.classpath*:不仅会到classes路径,还包括jar文件中(classes路径)进行查找。
mapper-locations: classpath*:mapper/*.xml
type-aliases-package: com.asule.entities #所有别名所在包
4.创建实体类
-
Payment实体类
package com.asule.entities; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; import java.math.BigInteger; /** * @author: ASULE * @create: 2022/1/21 22:45 * @version: 1.0 **/ //@Data:生成@Setter、@Getter、@RequiredArgsConstructor、@ToString、@EqualsAndHashCode @Data //@AllArgsConstructor:生产全参构造器 @AllArgsConstructor //@NoArgsConstructor:生产无参构造器 @NoArgsConstructor public class Payment implements Serializable { BigInteger id; String serial; }
-
Json封装体CommonResult
package com.asule.entities; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @author: ASULE * @create: 2022/1/22 16:57 * @version: 1.0 **/ @Data @AllArgsConstructor @NoArgsConstructor //泛型,不管传过来什么类型都可以接受并且发送给前端 public class CommonResult<T> { //报错信息:404 not_found private Integer code; private String message; private T data; //当data为空的时候需要这个构造方法 public CommonResult(Integer code,String message){ this(code,message,null); } }
5.创建dao层
-
新建PaymentDao接口
package com.asule.dao; import com.asule.entities.Payment; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; /** * @author: ASULE * @create: 2022/1/21 22:24 * @version: 1.0 **/ /* @Mapper 和 @MapperScan的区别 1.@Mapper 作用:用在接口类上,在编译之后会生成相应的接口实现类 位置:对应的某个接口类上面 2.@MapperScan 作用:扫描指定包下所有的接口类,然后所有接口在编译之后都会生产相应的实现类 位置:在启动类上添加 小结: @Mapper是对单个接口的注解,适用于单个操作 @MapperScan是对整个包下所有的接口类的注解,适用于批量操作。 使用@MapperScan后接口类就不需要@Mapper */ @Mapper public interface PaymentDao { int create(Payment payment); /* @Param 作用:给参数命名,参数命名后就能根据名字得到参数值, 正确的将参数传入sql语句中(一般通过#{}的方式,${}会有sql注入的问题) 说明:当你使用了@Param注解来声明时,使用#{}和${}的方式都可以,如果 不使用@Param注解来声明参数时,必须使用#{},如果使用${}的方式会报错。 当传递对象时JavaBean时(即一个对象),最好不使用@Param注解,这样 在SQL语句里就可以直接引用JavaBean属性,而且只能引用JavaBean存在的属性。 如果添加了@Param注解在SQL中使用#{名称.属性}会取不到值 */ Payment getPaymentById(@Param("id")Long id); }
-
在resources下创建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"> <!-- 在mybatis中,映射文件中的namespace是用于绑定Dao接口的,即面向接口编程。 当你的namespace绑定接口后,你可以不用写接口实现类,mybatis会通过该绑定自动 帮你找到对应要执行的SQL语句 --> <mapper namespace="com.asule.dao.PaymentDao"> <!-- ResultMap的作用:主要用于解决实体类属性名与数据库表中字段名不 一致的情况下,解决将查询结果映射成实体对象。 ResultMap的属性: id:是该封装规则的唯一标识符 type:是封装出来的类型,可以是jdk自带的,也可以是 自定义的,由于我们开启了别名标签,所以可以不写路径只写类名 <result>:用来映射数据表的列到实体对象的属性 <id>:用来映射标识属性 column:从数据库中查询到的结果集的列名或列别名(字段名) property:将column属性指定的列结果映射到对象的哪个属性 --> <resultMap id="BaseResultMap" type="com.asule.entities.Payment"> <id column="id" property="id" jdbcType="BIGINT"></id> <result column="serial" property="serial" jdbcType="VARCHAR"></result> </resultMap> <!--useGeneratedKeys="true",keyProperty="id" 指的是:如果插入的表id以自增列为主键,则允许JDBC支持自动生成逐渐 并可以将自动生成的主键id返回 注意:useGeneratedKeys参数只针对 insert 语句生效,默认为false--> <insert id="create" parameterType="payment" useGeneratedKeys="true" keyProperty="id"> insert into payment(serial) values(#{serial}) </insert> <select id="getPaymentById" parameterType="Long" resultMap="BaseResultMap"> select * from payment where id = #{id} </select> </mapper>
6.创建服务层
-
创建PaymentService接口
package com.asule.service; import com.asule.entities.Payment; import org.apache.ibatis.annotations.Param; /** * @author: ASULE * @create: 2022/1/21 23:05 * @version: 1.0 **/ public interface PaymentService { int create(Payment payment); Payment getPaymentById(Long id); }
-
创建PaymentServiceImpl实现类实现PaymentService接口
package com.asule.service.impl; import com.asule.dao.PaymentDao; import com.asule.entities.Payment; import com.asule.service.PaymentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; /** * @author: ASULE * @create: 2022/1/21 23:14 * @version: 1.0 **/ @Service public class PaymentServiceImpl implements PaymentService { @Autowired private PaymentDao paymentDao; @Override public int create(Payment payment) { return paymentDao.create(payment); } @Override public Payment getPaymentById(Long id) { return paymentDao.getPaymentById(id); } }
7.创建控制层
@RestController、@Controller、@ResponseBody注解的区别
后续自己写一个自己的理解
package com.asule.controller;
import com.asule.entities.CommonResult;
import com.asule.entities.Payment;
import com.asule.service.PaymentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* @author: ASULE
* @create: 2022/1/21 23:19
* @version: 1.0
**/
@RestController
//用于做日志输出
@Slf4j
@RequestMapping("/payment")
public class PaymentController {
/*
@Autowired的作用:它可以对类成员变量、方法及构造函数进行标注,让 spring完成bean自动装配的工作。
@Autowired 默认是按照类去匹配,配合@Qualifier可以指定按照名称去装配bean。
*/
@Autowired
private PaymentService paymentService;
/*
前后端分离了,我们只能传一个CommonResult
@RequestBody的作用是将前端传来的json格式的数据转为自己定义好的javabean对象
注:@RequestBody要写在方法的参数前,不能写在方法名上方
@ResponseBody的作用是将后端以return返回的javabean类型数据转为json类型数据。
*/
@PostMapping("/create")
public CommonResult create(@RequestBody Payment payment){
int result = paymentService.create(payment);
log.info("插入数据的ID:\t" + payment.getId());
log.info("插入数据的结果:" + result);
if (result > 0){
return new CommonResult(200,"插入数据成功",result);
}else {
return new CommonResult(444,"插入数据失败",null);
}
}
@GetMapping("/get/{id}")
/*
@PathVariable的作用:接收请求路径中占位符的值
*/
public CommonResult getPaymentById(@PathVariable("id") Long id){
Payment payment = paymentService.getPaymentById(id);
int age = 10/2;
System.out.println(age);
log.info("***查询结果:" + payment);
if(payment != null){
return new CommonResult(200,"查询数据成功",payment);
}else {
return new CommonResult(444,"没有对应记录",null);
}
}
}
8.使用Postman测试
- post测试
- get测试
4.搭建cloud-consumer-order80
1.在父工程下创建cloud-consumer-order80子工程
2.在子工程中导入相关依赖
<dependencies>
<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>
</dependency>
</dependencies>
3.在子工程中新建application.yml文件
server:
port: 80
#设置当前应用的名称,将来会在eureka中显示。将来需要该名称来获取路径
spring:
application:
name: cloud-consumer-order80
4.启动类(此后启动类代码无特殊情况不再赘述)
package com.asule;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author: ASULE
* @create: 2022/1/22 18:13
* @version: 1.0
**/
@SpringBootApplication
public class Order80Application {
public static void main(String[] args) {
SpringApplication.run(Order80Application.class,args);
}
}
5.实体类与payment8001工程中相同
直接拷贝payment8001工程中的entities文件
6.使用RestTemplate完成远程调用
RestTemplate是一种简单便捷的访问restful服务的模板类,用于在Java代码里访问restful服务。
package com.asule.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author: ASULE
* @create: 2022/1/22 18:43
* @version: 1.0
**/
@Configuration
public class Config {
/*
@Bean注解:用于告诉方法,产生一个Bean对象
,然后把这个Bean对象交给Spring管理
*/
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
7.创建控制层
package com.asule.controller;
import com.asule.entities.CommonResult;
import com.asule.entities.Payment;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
/**
* @author: ASULE
* @create: 2022/1/22 18:47
* @version: 1.0
**/
@RestController
@Slf4j
@RequestMapping("/consumer")
public class OrderController {
private final static String PAYMENT_URL = "http://localhost:8001";
@Autowired
private RestTemplate restTemplate;
/*
用RestTemplate的postForObject请求其他系统的接口,发现该接口是接收json格式参数
*/
@PostMapping ("/payment/create")
public CommonResult<Payment> create(Payment payment){
return restTemplate.postForObject(PAYMENT_URL+"/payment/create",payment,CommonResult.class);
}
@GetMapping("/payment/get/{id}")
public CommonResult<Payment> getPaymentById(@PathVariable("id") Long id){
return restTemplate.getForObject(PAYMENT_URL+"/payment/get/"+id,CommonResult.class);
}
}
5.工程重构
观察到的问题:系统中有重复的部分,所以要重构
-
建立cloud-api-commons模块
-
导入相关依赖
<dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.1.0</version> </dependency> </dependencies>
-
将消费者和服务者中重复的部分(即entities)拷贝到新模块当中,删除消费者和服务中的重复的那部分
-
clean
-
install
将项目本身编译并打包到本地仓库,这样其他项目引用本项目的jar包时不用去私服上下载jar包,直接从本地就可以拿到刚刚编译打包好的项目的jar包
- 在consumer和provider中引入自己所定义的包
<!--引入自己定义的api通用包,可以使用Payment支付Entity-->
<dependency>
<groupId>com.asule</groupId>
<!--自己所打包模块的名称-->
<artifactId>cloud-api-commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/81911.html