前言
- Rest环境搭建
1.1 Rest-Springcloud版本说明
1.2 SpringCloud-Rest环境搭建(服务提供者)
1.3 ## SpringCloud-Rest环境搭建(服务消费者)
前言
本文主要讲解SpringCloud实现’Rest环境搭建’(服务提供最和服务消费者)。并实现’服务消费者’正常访问’服务提供者’的具体服务。
1. Rest环境搭建
1.1 Rest-Springcloud版本说明
- SpringCloud版本选择-“图-spingcloud版本-1”
- SpringBoot实际开发的版本-“图-spingcloud版本-1”
图-spingcloud版本-1
图-spingcloud版本-2
1.2 SpringCloud-Rest环境搭建(服务提供者)
① 创建SpringCloud项目,演示如下
⑴ 第一步:首先创建一个父工程:来存放接下去要创建的一个个子工程项目。
IDEA打开-->Create Project -->左边:Maven-->
- groupid:com.lzk
- Aritifactid:springcloud
- version:1.0-SNAPSHOT
-->之后直接点击Next,之后选择对应的存放路径-->Finish。
⑵ 第二步:上面第一步创建的是一个父工程,它要代表一个总的。
- 删掉上面创建的父工程的"src"
- 在父工程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">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lzk</groupId>
<artifactId>springcloud</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 修改父工程项目的打包方式为: pom-->
<packaging>pom</packaging>
<!-- 总版本号管理:
1. 将下面在<dependencyManagement>这个标签导入
依赖的版本提到这个<properties>标签里面。
2. 以后需要修改下面依赖的版本,直接在这个<properties>
标签里面修改即可,当要修改某依赖的版本时,不用特意去下对应的依赖!
-->
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler>1.8</maven.compiler>
<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>
<!--这是一个父工程项目,因此在此项目的pom.xml中
需要使用<dependencyManagement>这个标签
来实现对所有导入的进来的依赖jar包进行依赖管理
-->
<dependencyManagement>
<dependencies>
<!-- 这是springcloud的依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- 由于springcloud是依赖于springboot,因此这里还要导入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>
<!--Druid 数据库连接池组件-->
<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>
<!--
${lombok.version},${junit.version},
${log4j.version}等等
表示此依赖的版本号从上面的<properties>
标签里面来设置。
-->
<!--log4j单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
</dependency>
<!--主要用于日志测试相关的依赖-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<!--Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<!--Log4j-->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<!--用来配置打包的插件的,不一定每个pom.xml都要配-->
<build></build>
</project>
-------------子项目模块springcloud-api 开发----------------
⑶ 第三步:创建子工程项目(springcloud-api子模块)
-1 File-->New-->Project-->Maven-->输入子工程项目名-->Next
-->springcloud-api模块-->finish。
-2 创建完成,可以看出这个子项目模块:
springcloud-api 的pom.xml的<parent>父依赖是刚才我们创建的
那个父工程项目,而父工程项目通过<dependencyManagement>标签来实
现管理我们导入的依赖。
-3 但是注意我们在父工程项目中只是对导入的依赖进行管理
<dependencyManagement>标签,如果在子项目模块中需要用
到父工程项目中的某一个依赖,需要到子项目工程模块中去
导入使用需要的依赖,以此来去父项目工程中得到刚才导入
的依赖。
-->比如子项目模块的pom.xml需要lombok,直接在pom.xml中输入
依赖来导入使用lombok依赖:
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
⑷ 第四步:到数据库创建springcloud-api子模块对应的数据库"DB01",以及"DB01"下面对应的表。
- 到Mysql中手动创建DB01数据库,然后使用IDEA中连接DB01,在IDEA中创建对应的表,
并在IDEA中输入Sql语句,实现数据插入,相同语句创建5条数据:
insert into dept (dname,db_source) values ('开发部',DATABASE());
---> 这里的db_source字段表示:当前表对应的数据库名。
⑸ 第五步:springcloud-api子模块中创建实体类
- 在java下创建com.lzk.springcloud下创建"pojo"包
- "pojo"包下创建实体类"Dept",且所有实体类实现序列化接口
(实体类若没有实现序列化接口,在通讯传输中就会报一个错误。)
- 实体类如下所示↓:
package com.lzk.springcloud.pojo;
/**
* Created by Linzk on 2020/12
* <p>
* 部门表(实体类需要实现序列化)
* -->实现序列化,避免数据传输出现错误。
*
* 1. @Accessors(chain = true) : 此注解为true表示支持"链式写
* 法"
* 1.1 什么是链式写法呢?
* 1.2 因为之前创建一个对象并赋值步骤为如下所示↓:
* Dept dept = new Dept();
* dept.setDeptNo(10);
* dept.setDname("a1");
*
* 1.3 现在开启支持链式写法在创建对象并赋值可以采用"链式写法"来实现赋值,
* 如下所示↓:
* Dept dept = new Dept();
* dept.setDeptNo(10)setDname("a1"); -->像这样"链式写法"赋值
*
*/
@Data
@NoArgsConstructor
@Accessors(chain = true)
public class Dept implements Serializable {
/**
* 主键
*/
private Long deptno;
private String dname;
/**
* 1.这个字段表示:
* -->该表对应的数据存于哪个数据库中。
* 1.1 因为"微服务架构"是一个服务对应一个数据库
* -->在存数据时,可能会存在:同一个数据信息
* 被存储到不同的数据库中,所以就创建此字段来区别数据
* 存储的位置。
*
*/
private String db_source;
/**
* 构造器
*/
public Dept(String dname) {
this.dname = dname;
}
}
↑ 此时子项目模块springcloud-api就只管负责pojo实体类的事情,
---->这个子模块的功能就写完了。
----------------------------------------------------
⑹ 第六步:接下去创建另一个子项目模块"服务的提供者模块"
(springcloud-provider-dept-8001)
▲:我们需要在这个子模块下完成编写:Dao接口 +
mapper.xml配置文件(用Mybatis就需要创建一个这个配置文件) +
Service接口 + ServiceImpl实现类 + Controller提供访问接口 +
创建项目的主启动类。
↓↓↓↓↓↓
↓↓↓
↓(具体配置步骤如下)
-1. 由于我们后面会创建多个服务的提供者,因此可以在子项目模块的名
字后面,添加上对应提供者模块的端口号8001
-2. 首先在pom.xml中导入(springcloud-provider-dept-8001)需要的依赖
*** 注意 ***:注意我们在子项目模块中对于需要导入的依赖如果已经在
父项目模块中已经被<dependencyManagement>这个标签下管理和引入了,
就可以不用写对应依赖的版本号,子模块会自动继承父项目模块中的版本号。
-3. (springcloud-provider-dept-8001)子模块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>springcloud</artifactId>
<groupId>com.lzk</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-provider-dept-8001</artifactId>
<dependencies>
<!--
首先:我们需要拿到实体类,所以需要将存放实
体类的子模块依赖引入,这就叫服务拆分。
-->
<dependency>
<groupId>com.lzk</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--其次:测试类junit依赖引入
由于junit的依赖在父工程项目中已被管理,因此我们
在此模块中引入junit依赖,不用写版本号,自动继承父工程项目
里面junit的版本号
-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<!--数据库的连接依赖,同时这里版本号也不用写,
该依赖也已经在父项目工程中被管理,这里自动继承父项目工程
的版本号-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--数据库连接池相关依赖依赖-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
</dependency>
<!--日志相关-->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<!--Springboot的test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<!--springboot web的启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--jetty:可以使用jetty作为应用服务器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency>
<!--热部署工具:代码修改自动更新代码,不用重启项目-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
⑺ 第七步:在(springcloud-provider-dept-8001)子模块中,编写
配置文件application.yml的配置 及 mybatis的.xml配置文件配置(mybatis-config.xml)
-1 配置文件application.yml的配置
server:
port: 8001
# mybatis配置
mybatis:
# 配置Mybatis读取实体类路径配置
type-aliases-package: com.lzk.springcloud.pojo
# mybatis核心配置文件所在路径
config-location: classpath:mybatis/mybatis-config.xml
# mybatis的mapper配置所在路径
mapper-locations: classpath:mybatis/mapper/*.xml
# Spring的配置
spring:
application:
# spring服务提供者项目的名字
name: springcloud-provider-dept
# spring数据源
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: org.gjt.mm.mysql.Driver
url: jdbc:mysql://127.0.0.1:3306/db01?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: xxx
password: xxx
-2 mybatis的.xml配置文件配置(mybatis-config.xml)
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>
</settings>
</configuration>
-3 之后在(springcloud-provider-dept-8001)子模块中,编写接口
- com.lzk.springcloud.dao层接口编写
package com.lzk.springcloud.dao;
/**
* 1. @Mapper注解:声明这是一个mapper接口,
* 能够被Mybatis的配置文件mapper.xml扫描到,执行mapper.xml里面
* 的Sql语句来操作数据库
*
* 2. @Repository注解:将此接口注入到Spring容器中
* -->接口注入容器中,bean
*
*/
@Mapper
@Repository
public interface DeptDao {
public boolean addDept(Dept dept);
public Dept queryById(Long id);
public List<Dept> queryAll();
}
-4 使用Mybatis实现持久层操作,就需要编写mapper.xml配置文件
在里面写入Sql语句
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--Mybatis配置文件中,配置mapper绑定操作数据库的接口所在路径-->
<mapper namespace="com.lzk.springcloud.dao.DeptDao">
<!--添加的SQL语句-->
<insert id="addDept" parameterType="Dept">
insert into dept(dname,db_source)
values (@{dname},DATABASE())
</insert>
<!--查询单条数据的SQL语句-->
<select id="queryById" resultType="Dept" parameterType="Long">
select * from dept where deptno = #{deptno};
</select>
<!--添加所有数据的SQL语句-->
<select id="queryAll" resultType="Dept">
select * from dept;
</select>
</mapper>
-5 继续在(springcloud-provider-dept-8001)子模块中,编写Service层
(创建service包-->DeptService接口 + DeptServiceImpl实现类)
/**
* -->这个接口类似Dept里面的一个服务
*/
public interface DeptService {
public boolean addDept(Dept dept);
public Dept queryById(Long id);
public List<Dept> queryAll();
}
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptDao deptDao;
@Override
public boolean addDept(Dept dept) {
return deptDao.addDept(dept);
}
@Override
public Dept queryById(Long id) {
return deptDao.queryById(id);
}
@Override
public List<Dept> queryAll() {
return deptDao.queryAll();
}
}
-5 在(springcloud-provider-dept-8001)子模块中,编写Controller
提供访问接口
package com.lzk.springcloud.controller;
/**
* -->这个Controller类就是用来提供restful服务的
*/
@RestController
public class DeptController {
@Autowired
private DeptService deptService;
@PostMapping("/dept/add")
public boolean addDept(Dept dept) {
return deptService.addDept(dept);
}
@GetMapping("/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
return deptService.queryById(id);
}
@GetMapping("/dept/list")
public List<Dept> queryAll() {
return deptService.queryAll();
}
}
-6 在(springcloud-provider-dept-8001)子模块中,创建项目的主启动类
@SpringBootApplication
public class DeptProvider_8001 {
public static void main(String[] args) {
SpringApplication.run(DeptProvider_8001.class,args);
}
}
⑻ 第八步:最后测试
- 启动Main()启动类-->
- 访问网页测试:http://localhost:8001/dept/get/1
- 如图所示"图test1"
-----------------------------------------------------
② 以上就是对创建一个服务提供者的项目(springcloud-provider-dept-8001)以及
springcloud-api的实体类创建。
⑴ 对于上面子项目模块中springcloud-provider-dept-8001中主要提供的服务是↓
- 增加部门
- id查询部门
- 查询全部部门
--->上面这三个服务。
1.3 ## SpringCloud-Rest环境搭建(服务消费者)
① 由于上面"## SpringCloud-Rest环境搭建(服务提供者)"中已经创建
了两个子项目模块"(springcloud-provider-dept-8001)和
(springcloud-api)"-->接下去就要创建服务消费者子模块。
② 接下去在"## SpringCloud-Rest环境搭建(服务提供者)"基础上,在
创建一个子模块作为"服务消费者"模块,此模块端口号设置为80端口,网
站默认端口是80端口,只要设置为80端口,你写请求的话就不需要带上端
口号。
⑴ 第一步:创建子项目模块(springcloud-consumer-dept-80)
- 并在springcloud-consumer-dept-80子模块pom.xml中导入依赖
(消费者模块与前端打交道的,不需要去连接数据库,因此只需要一些实体类和web依赖)
<?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>springcloud</artifactId>
<groupId>com.lzk</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud-consumer-dept-80</artifactId>
<!--实体类+web-->
<dependencies>
<dependency>
<groupId>com.lzk</groupId>
<artifactId>springcloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<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>
⑵ 第二步:实现子项目模块(springcloud-consumer-dept-80)的配置文件配置
- 对于消费者模块,只需要配置一个端口号即可
server:
port: 80
⑶ 第三步:子项目模块(springcloud-consumer-dept-80)创建controller
/**
* --->此消费者模块,不应该有service层
* 1. 任何东西在springboot都有一个对应的xxxxTemplate的模板
* 这个xxxxTemplate的模板,就是有对应的请求,我们直接调用模板
* 里面的方法即可。
* 1.1 我们要使用这个xxxxTemplate的模板,就需要将其注册到
* Spring中,我们可以自己创建一个配置类,将RestTemplate可以获
* 取到服务请求的这个模板类,注入的SPring容器中,
*
* 1.2 将RestTemplate模板注入到Spring后,我们就可以使用它来实
* 现请求服务获取
*
*/
@RestController
public class DeptConsumerController {
/**
* 为了获取对应的服务,我们注入RestTemplate模板来实现,服务
* 请求获取
* 1. RestTemplate有三个参数
* (String url,请求的实体使用Map来存放, Class<T>
* responseType>
* 2. 我们现在这个"消费者模块"没有service层,但是我们要去调
* 用远程的服务
* -->我们要去远程的服务获取"部门表"的信息,就需要
* 到"http://localhost:8001/dept/list"
* 这样一个地址拿,我们就需要在消费者这里
* 将"http://localhost:8001/dept/list"这
* 个地址获取到
*
* 2.1 "http://localhost:8001/dept/list" 这个前缀
* http://localhost:8001/是固定的,因此我们可以将这个固定
* 的前缀写成一个常量
*
* 3. 方法请求返回值:return 里面传入的参数有两个:URL请
* 求的地址 + 响应的参数类型
*
*
* 4. RestTemplate ==>就是提供多种便捷访问远程http服务的
* 方法。是一种简单的restful服务模板,是spring提供的一种模
* 板集即:你想要去远程拿东西 == 什么方式拿 + 去哪个地方拿
* + 拿什么东西
*
*/
@Autowired
private RestTemplate restTemplate;
private static final String REST_URL_PREFIX = "http://localhost:8001/";
@RequestMapping("/consumer/dept/add")
public boolean add(Dept dept) {
/**
* 1. postForObject() ==>表示是Post请求
* 2. dept ==>表示传进来的参数拼接到请求路径URL中去的
* 值
* 3. boolean ==> 表示返回值的类型
*/
return restTemplate.postForObject(REST_URL_PREFIX + "/dept/add",dept,boolean.class);
}
@RequestMapping("/consumer/dept/get/{id}")
public Dept get(@PathVariable("id") Long id) {
/**
* 1. getForObject() ==>表示是Get请求
* 2. id ==>表示传进来的参数拼接到请求路径URL中去的值
* 3. 括号参数后面的Dept.class ==》是方法的返回值类型
*/
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/get/" + id,Dept.class);
}
@RequestMapping("/consumer/dept/list")
public List<Dept> list() {
return restTemplate.getForObject(REST_URL_PREFIX + "/dept/list",List.class);
}
}
⑷ 第四步:由于我们消费者需要获取服务,而springboot对任何东西都
提供一个xxxxTemplate的模板,我们需要请求某个东西直接调用
xxxxTemplate的模板即可。
- 因此我们可以创建一个"xxxxTemplate的模板"的bean,将其注入到
spring中并实现调用xxxxTemplate的模板来发起请求,完成服务的请求
获取。
/**
* 1. 回顾一下
* 我们在类上添加@Configuration注解,就相当于
* 将这个类作为Spring里面的"applicationContext.xml配置类"
* 在这个配置类里面配置bean
*
*
*/
@Configuration
public class ConfigBean {
/**
* 想要获取哪一个bean,创建方法的时候返回想要的那个bean即可
* -->这样就将RestTemplate这个bean注册到我们Spring里面,
* 此时我们就可以用它了。
*
*/
@Bean
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
⑸ 第五步:创建一个启动类DeptConsumer_80,测试来获取远程服务
-1 先启动"服务提供者"8001的子项目模块启动类,并检查访问(里面的三个服务)是否可以正常的访问。
-->测试访问是否成功:http://localhost:8001/dept/get/1
8001端口"服务提供者"测试,如图所示-"图provider-1"。
-2 在启动"服务消费者"80的子项目模块启动类,测试远程获取服务是否成功
--> http://localhost/consumer/dept/get/1
80端口"服务消费者"测试,如图所示-"图consumer-1"(由于网页默认是
80端口因此我们访问网站的时候,可以不用带上80端口)。
-------------------------------------------------------
③ 至此,我们服务的"提供者和消费者"的增删改就搭建完成了。
⑴ 服务的消费者"DeptConsumerController"-->这是一个非常核心的东西。
- 这也是我们RestFule,Http基于RPC的一个本质的区别
⑵ 对于使用SpringBoot(Dubbo+Zookeeepr)搭建"服务提供者和服务消费者"的项目中:
- 第一点:需要他们有共同的接口。
- 第二点:我们消费者是从远程@Reference去引用的。
⑶ 现在我们使用SpringCloud搭建"服务提供者和服务消费者"的项目中:
- 第一点:只需要知道远程的一个URL地址就可以了。知道那个地址,我
们可以从地址入手去发送请求就好了。
图provider-1
图consumer-1