【SrpingCloud】一、provider和consumer的消息互通
一、功能设计
- provider:提供者(服务器端),提供查询数据库并返回提供json数据的接口,处理consumer回传的数据
- consumer:消费者,使用provider提供的接口显示数据或回传数据
二、目录结构
- 擦掉的两处是我用来测试的,忽略即可
三、父级maven项目实现
- 创建一个空的Maven项目,把src删除,加入以下依赖
- 每个依赖都有注释说明
<?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.common</groupId>
<artifactId>srpingcloud</artifactId>
<version>1.0-SNAPSHOT</version>
<modules>
<module>springcloud-api</module>
<module>springcloud-provider-dept-8001</module>
<module>springcloud-consumer-dept-80</module>
<module>springcloud-consumer-dept-81</module>
<module>springcloud-provider-dept-8002</module>
</modules>
<!-- 打包方式-->
<packaging>pom</packaging>
<!-- 依赖版本控制-->
<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>
</properties>
<!-- 依赖管理-->
<dependencyManagement>
<dependencies>
<!-- springcloud的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Greenwich.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- springboot的依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.4.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 数据库依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<!-- 数据源依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
<!-- springboot启动依赖-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.2</version>
</dependency>
<!-- junit测试依赖-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!-- lombok插件依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!-- 日志依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
四、创建springcloud-api
- 在当前目录下,新建一个module,命名为springcloud-api
- 作用:实现pojo层,与数据表的字段一一对应
- maven依赖
- 留意注释,springcloud-api的maven的父类是srpingcloud
<?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">
<!-- 父类的依赖是 srpingcloud 的 maven-->
<parent>
<artifactId>srpingcloud</artifactId>
<groupId>com.common</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-api</artifactId>
<dependencies>
<!-- 当前的module依赖,可以导入父工程依赖(如果父工程有此依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
- srpingcloud-api的目录结构
- 数据表设计
- pojo层:Dept类的编写
- 与数据库一一对应,实现Get和Set方法
@Data // 用注解的方式实现Get和Set
@NoArgsConstructor // 生成一个无参数的构造方法
@Accessors(chain = true) // 支持链式写法,下方讲解
//实现序列化的目的是为了保证流传输不出问题
public class Dept implements Serializable {
private long deptno; //主键
private String dname;
private String db_source;
}
/**
* 链式写法
* dept.setDeptNo(11).setDname('sss').setDb_source()
*/
五、提供者provider的设计与实现
- 目录结构
- maven文件
<?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>srpingcloud</artifactId>
<groupId>com.common</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-provider-dept-8002</artifactId>
<dependencies>
<!-- 通过maven,把 springcloud-api 中的pojo层进行共享 -->
<dependency>
<groupId>com.common</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web-services</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>
</dependency>
<!--mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<!--整合mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--json @responseBody/@requestBody-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
</dependencies>
</project>
- 通过maven的方式,实现 springcloud-api 共享(在当前Module可以调用另一个Module的方法)
<dependency>
<groupId>com.common</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
- application.properties配置文件
- 没什么特别,就把端口改成 8002
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db01?serverTimezone=UTC&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=1234
spring.mvc.favicon.enabled=false
server.port=8002
- Mapper层的Dept接口设计
- 用于实现数据持久化操作
- 三个方法
- 插入操作
- 通过 id 查询数据操作
- 查询所有数据操作
@Mapper //将dao交给spring管理 不用写mapper.xml了 自动注册一个接口实现类
@Repository //将dao类声明为bean
public interface DeptDao {
@Insert("insert into dept(dname,db_source) values (#{dname},DATABASE())")
// DATABASE() 自动插入当前数据表名
boolean addDept(Dept dept);
@Select("select * from dept where deptno = #{id}")
Dept queryId(Integer id);
@Select("select * from dept")
List<Dept> queryAll();
}
- Service层:DeptService类的设计
- 实现Mapper层的接口
@Service
public class DeptService {
@Autowired
private DeptDao deptDao;
public boolean addDept(Dept dept) {
return deptDao.addDept(dept);
}
public Dept queryId(Integer id) {
return deptDao.queryId(id);
}
public List<Dept> queryAll() {
return deptDao.queryAll();
}
}
- Controller层:DeptController类的设计与实现
- 因为没有做前端页面,所以用 @RestController 注解,不返回页面,直接返回数据
// @RestController = @Controller + @ResponseBody组成,
// @RestController注解Controller,则Controller中的方法无法返回jsp页面,
// 这里没有前端页面使用@RestController就够了
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@PostMapping("dept/add")
// 使用 json 数据通信,加 @RequestBody
public boolean addDept(@RequestBody Dept dept) {
return deptService.addDept(dept);
}
@GetMapping("/dept/get/{id}")
public Dept get(@PathVariable("id") Integer id){
return deptService.queryId(id);
}
@GetMapping("/dept/list")
public List<Dept> queryAll() {
return deptService.queryAll();
}
}
- 启动类
//启动类
@SpringBootApplication
public class DeptProvider_8002 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8002.class, args);
}
}
六、消费者Consumer的设计与实现
- 概述
- 运用provider的接口,通过 RestTemplate(springBoot提供的http通信模板)进行与provider互传数据
-
目录结构
-
maven依赖
- 同 provider ,需要 springcloud-api 的实体类进行操作
<?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>srpingcloud</artifactId>
<groupId>com.common</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-consumer-dept-81</artifactId>
<dependencies>
<!-- 实体类+web-->
<dependency>
<groupId>com.common</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- spirngboot的web依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 热部署依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
- 配置类:实现 RestTemplate
@Configuration
// 调用网络请求模板:RestTemplate,进行网络请求
public class configBean {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
- 控制层:DeptConsumerController
- 消费者,不应该有server层
- 这里运用到了SpringBoot的一个网络请求模板 RestTemplate
- 第4点的就是对 RestTemplate 的基础配置
- 该方法的核心参数:① url ② 实体:Mapper ③ class responseType(返回值.class)
- 详细看代码的注解
@RestController
public class DeptConsumerController {
// 理解:消费者,不应该有server层
// 使用RestTemplate获取provider提供的数据
// springboot中的一种网络请求:RestTemplate
//核心参数( url , 实体:Map , class<T> responseType(返回值.class) )
@Autowired
private RestTemplate restTemplate; //提供多种便捷访问远程http服务的方法,一种简单的restful服务模板
// 创建一个静态的参数 REST_URL_PREDIX ,用于保存 provider 的网络地址:
private static final String REST_URL_PREDIX = "http://localhost:8002";
// 服务器端给你什么方法就用什么方法 给你 "/dept/list" ,就在网络请求方法里面调用 "/dept/list"
@RequestMapping("/consumer/dept/list")
public List<Dept> list(){
return restTemplate.getForObject(REST_URL_PREDIX + "/dept/list", List.class);
}
@RequestMapping("/consumer/dept/add")
public boolean add(Dept dept){
return restTemplate.postForObject(REST_URL_PREDIX + "/dept/add",dept,Boolean.class );
}
@RequestMapping("/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Integer id){
return restTemplate.getForObject(REST_URL_PREDIX + "/dept/get/" + id ,Dept.class);
}
}
- 配置文件 .yml
- provider 用的是 .properties,而 consumer 用的是 .yml
- yml文件的好处,天然的树状结构,一目了然,实质上跟properties是差不多的,两个都用一下
- 就改成 81端口 而已
server:
port: 81
druid:
# 指明是否在从池中取出连接前进行检验,如果检验失败, 则从池中去除连接并尝试取出另一个,
#注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
test-on-borrow: false
# 指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除.
#注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串
test-while-idle: true
# 指明是否在归还到池中前进行检验,注意: 设置为true后如果要生效,
#validationQuery参数必须设置为非空字符串
test-on-return: false
# SQL查询,用来验证从连接池取出的连接,在将连接返回给调用者之前.
#如果指定,则查询必须是一个SQL SELECT并且必须返回至少一行记录
validation-query: select 1
- 启动类
@SpringBootApplication
public class DeptConsumer_81 {
public static void main(String[] args) {
SpringApplication.run(DeptConsumer_81.class, args);
}
}
七、实现效果
-
同时开启 provider(8002端口)和 consumer(81端口)
-
用 consumer 中 controller 的方法,进行网路访问
- 方法1:/consumer/dept/list 查询所有数据
- 方法2:/consumer/dept/add 增加一条数据
- 方法3:/consumer/dept/get/{id} 通过ID查询单条数据
- 图就不截了,懒=- =,反正可以跑,大功告成!