REST是什么
REST即表述性状态传递(英文:Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。
在三种主流的Web服务实现方案中,因为REST模式的Web服务与复杂的SOAP和XML-RPC对比来讲明显的更加简洁,越来越多的web服务开始采用REST风格设计和实现。例如,Amazon.com提供接近REST风格的Web服务进行图书查找;雅虎提供的Web服务也是REST风格的。
总体介绍
会使用一个Dept部门模块作为微服务通用案例Consumer消费者(Client),通过Rest调用Provider提供者(Server)提供的服务
Spring、SpringMVC、Mybatis
Maven的分包分模块架构
一个简单的Maven模块结构
—app -parent :一个父项目(app-parent)聚合多个子项目(app-util、app-dao、app-web)
|— pom.xml
|
|—app-core
|—-pom.xml
|
|—app-web
||—pom,xml
一个父工程带多个Module子模块
MicaoServiceCloud 父工程(Project)下初次带3个子模块(Module)
MicaoServiceCloud-api (封装整体entity、接口、公共配置等)
MicaoServiceCloud-Provider-dept-8001 (服务提供者)
MicaoServiceCloud-Consumer-dept-8002(服务消费者)
SpringCloud版本选择
Demo编写步骤
1:创建maven项目(父工程)
file新建new maven porject
next下一步
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"><modelVersion>4.0.0</modelVersion><groupId>com.junjay</groupId><artifactId>SpringCloud</artifactId><version>0.0.1-SNAPSHOT</version><!-- 1:打包方式pom --><packaging>pom</packaging><name>SpringCloud</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><!-- 版本控制 --><maven.comiler.source>1.8</maven.comiler.source><maven.comiler.targer>1.8</maven.comiler.targer><junit.version>4.12</junit.version><lombok.version>1.16.10</lombok.version></properties><dependencyManagement><dependencies><!-- 2:spring-cloud依赖 --><!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-dependencies --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-dependencies</artifactId><version>Greenwich.SR1</version><type>pom</type><scope>import</scope></dependency><!-- 3:导入springboot依赖 --><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-test --><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>2.1.4.RELEASE</version><type>pom</type><scope>import</scope></dependency><!-- 4:数据库依赖 --><!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><!-- 5:数据源 --><!-- https://mvnrepository.com/artifact/com.alibaba/druid --><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.10</version></dependency><!-- 6:springboot启动器 --><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter --><!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>1.3.2.RELEASE</version></dependency><!-- 7:junit --><!-- https://mvnrepository.com/artifact/junit/junit --><!-- https://mvnrepository.com/artifact/junit/junit --><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>test</scope></dependency><!-- 8:Lombok --><!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.16.10</version><scope>provided</scope></dependency><!-- 9:log4j --><!-- https://mvnrepository.com/artifact/log4j/log4j --><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><!-- 10:logback --><!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core --><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-core</artifactId><version>1.2.3</version></dependency><!-- 11: mybatis boot 启动器 --><!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>1.3.2</version></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency></dependencies><!-- 父工程下的子模块 --><modules><module>springcloud-pai</module><module>springcloud-provider-dept-8081</module></modules></project>
3:创建maven项目(子工程api)
右键选中父工程,创建maven项目,选择maven module进行创建
继续下一步,完成finish。
目录层级:
4:修改子工程api-pom文件
<?xml version="1.0"?><projectxsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><modelVersion>4.0.0</modelVersion><parent><groupId>com.junjay</groupId><artifactId>SpringCloud</artifactId><version>0.0.1-SNAPSHOT</version></parent><groupId>com.junjay</groupId><artifactId>springcloud-pai</artifactId><version>0.0.1-SNAPSHOT</version><name>springcloud-pai</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><!-- 子工程使用父工程jar --><!-- 当前的module自己需要的依赖,如果父工程中已经配置了版本,在引用依赖时候就不需要设置会向父工程中查找 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency></dependencies></project>
子工程下新建包,org.springcloud.pojo
创建实体类Dept
package org.springcloud.pojo;import java.io.Serializable;import lombok.Data;import lombok.NoArgsConstructor;import lombok.experimental.Accessors;/*** @author My 首先分布式,第一步需要网络通信,* 第二步序列化,所有的实体类必须实现序列化才可通讯*///@SuppressWarnings(“serial”)//如果编译器出现这样的警告信息:The serializable class WmailCalendar does not declare a static final serialVersionUID field of type long,使用这个注释将警告信息去掉。@SuppressWarnings("serial")@Data@NoArgsConstructor // 生成一个无参数的构造方法@Accessors(chain = true) // 链式写法public class Dept implements Serializable {/*** 主键*/private Long deptno;/*** dept名称*/private String dname;/*** 微服务架构,可以一个服务对应一个数据库,* 一个信息存到不同数据库,db_source标识是哪个数据库*/private String db_source;public Dept(String dname) {this.dname = dname;}// 链式写法:public static void main(String[] args) {Dept dept = new Dept();dept.setDeptno(11L).setDname("aaa").setDb_source("000");}}
5:创建服务提供者子工程
以 创建api 工程一样创建新工程 springcloud-provider-dept-8081
修改provider 子工程pom文件
<?xml version="1.0"?><projectxsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><modelVersion>4.0.0</modelVersion><parent><groupId>com.junjay</groupId><artifactId>SpringCloud</artifactId><version>0.0.1-SNAPSHOT</version></parent><groupId>com.junjay</groupId><artifactId>springcloud-provider-dept-8081</artifactId><version>0.0.1-SNAPSHOT</version><name>springcloud-provider-dept-8081</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency><!-- 我们需要拿到实体类,所以需要配置api-module --><dependency><groupId>com.junjay</groupId><artifactId>springcloud-pai</artifactId><version>0.0.1-SNAPSHOT</version></dependency><!-- 引用父工程中定义好的jar直接引用无需选择版本,因为在父工程中已经设置 --><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><!-- test --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-test</artifactId></dependency><!-- web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- jetty 内置是tomcat 也可以使用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>
编写相关springboot的yml配置文件,配置服务端口,mybatis配置,数据库配置
server:port: 8081#mybatis配置mybatis:type-aliases-package: org.springcloud.pojoconfig-location: classpath:mybatis/mybatis-config.xmlmapper-locations: classpath:mybatis/mapper/*.xml#开启自动驼峰命名# configuration:# map-underscore-to-camel-case:#spring配置spring:application:name: springcloud-provider-deptdatasource:# 数据库名称type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/db01?useUncode=true&characterEncoding=utf8&verifyServerCertificate=false&useSSL=false&allowMultiQueries=trueusername: rootpassword: root
撰写mybatis-config配置
<?xml version="1.0" encoding="UTF-8" ?><!-- 标识文件类型改文件为配置configuration DOCTYPE configuration--><!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd"><configuration><settings><!-- 全局性地开启或关闭所有映射器配置文件中已配置的任何缓存 开启二级缓存 --><setting name="cacheEnabled" value="true" /></settings></configuration>
创建controller,dao,service,mapper包以及文件
DeptMapper.xml
<?xml version="1.0" encoding="UTF-8" ?><!-- 标识文件类型改文件为mapper DOCTYPE mapper --><!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!-- namespace 绑定接口包路径 --><mapper namespace="org.springcloud.dao.DeptDao"><insert id="addDept">INSERT INTO db01.dept( dname, db_source)VALUES(#{dname}, DATABASE())</insert><select id="queryById" resultType="Dept" parameterType="Long">SELECT *FROM db01.dept where 1=1 deptno =#{deptno}</select><select id="queryList" resultType="Dept">SELECT *FROM db01.deptwhere1=1</select></mapper>
DeptController
package org.springcloud.controller;import java.util.List;import org.springcloud.pojo.Dept;import org.springcloud.service.DeptService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RestController;/*** @author My 提供RestFul 风格服务*/@RestControllerpublic class DeptController {@Autowiredprivate DeptService deptService;@PostMapping("/dept/add")public boolean addDept(@RequestBody Dept dept) {return deptService.addDept(dept);}@GetMapping("/dept/queryById/{deptno}")public Dept queryById(@PathVariable("deptno") Long deptno) {return deptService.queryById(deptno);}@PostMapping("/dept/queryList")public List<Dept> queryList() {return deptService.queryList();}}
DeptDao
package org.springcloud.dao;import java.util.List;import org.apache.ibatis.annotations.Mapper;//通过其他项目导入相关实体import org.springcloud.pojo.Dept;import org.springframework.stereotype.Repository;@Mapper@Repositorypublic interface DeptDao {public boolean addDept(Dept dept);public Dept queryById(Long deptno);public List<Dept> queryList();}
DeptService
package org.springcloud.service;import java.util.List;//通过其他项目导入相关实体import org.springcloud.pojo.Dept;public interface DeptService {public boolean addDept(Dept dept);public Dept queryById(Long deptno);public List<Dept> queryList();}
DeptServiceImpl
package org.springcloud.service;import java.util.List;import org.springcloud.dao.DeptDao;import org.springcloud.pojo.Dept;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;@Servicepublic class DeptServiceImpl implements DeptService {@Autowiredprivate DeptDao deptDao;public boolean addDept(Dept dept) {return deptDao.addDept(dept);}public Dept queryById(Long deptno) {return deptDao.queryById(deptno);}public List<Dept> queryList() {return deptDao.queryList();}}
创建boot启动类
添加 @SpringBootApplication 注解,以main方法 用SpringApplication 点run 启动本类
DeptProvider_8081
package org.springcloud;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;// 启动类@SpringBootApplicationpublic class DeptProvider_8081 {public static void main(String[] args) {SpringApplication.run(DeptProvider_8081.class, args);}}
启动问题
解决方案https://blog.csdn.net/qq_34322008/article/details/89954934
错误原因:resources 配置文件包名 写错成 resoures 导致没有加载到yml配置文件,再次加深springboot 约定大于配置
启动成功
以RestFul 风格访问,访问成功
根据id 查询 dept表数据
测试添加用户,提示不能使用GET请求因为后端RestFul请求为POST请求,为了服务安全
通过postman以post请求测试用户添加

服务提供者创建创建完成
6:创建服务消费者子工程
以之前创建子工程相似
创建消费者工程后 ,修改pom文件
<?xml version="1.0"?><projectxsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><modelVersion>4.0.0</modelVersion><parent><groupId>com.junjay</groupId><artifactId>SpringCloud</artifactId><version>0.0.1-SNAPSHOT</version></parent><groupId>com.junjay</groupId><artifactId>springcloud-consumer-dept-8082</artifactId><version>0.0.1-SNAPSHOT</version><name>springcloud-consumer-dept-8082</name><url>http://maven.apache.org</url><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding></properties><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope></dependency><!-- 消费者只需要实体类+web --><dependency><groupId>com.junjay</groupId><artifactId>springcloud-pai</artifactId><version>0.0.1-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>
创建对应消费者的yml 配置文件

#服务消费者只需要配置启动端口server:port: 8082
restful 风格 肯定有Rest TempLate Rest模板

配置RestTemplate bean

配置RestTemplate bean
package org.springcloud.config;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.client.RestTemplate;// 相当于spring 中的 applicationContext.xml//指示一个类声明一个或多个@Bean方法,并且可以由Spring容器处理,以便在运行时为这些bean生成BeanDefinition和服务请求@Configurationpublic class ConfigBean {// 原来是<bean></bean>// 现在使用spring注解/*** RestTemplate中没有@Bean,容器中没有该类,需要new一个新类,* 所以需要手动配置一个bean,这样容器中就有改类,就可以使用@Autowired进行注入* 也就是说通过@Bean 将该类交给spring进行管理及ioc*/@Beanpublic RestTemplate getRestTemplate() {return new RestTemplate();}}
消费者controller
package org.springcloud.controller;import java.util.List;import org.springcloud.pojo.Dept;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PathVariable;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.client.RestTemplate;@RestControllerpublic class DeptConsumerController {// 在这边没有service接口,// 理解:消费者 应不应该有service 结果是不需要执行访问就好// 因为需要restful 风格 肯定有RestTempLate spring会提供模板,供我们调用使用/*** 注入RestTemplate bean 参数 url,request请求:一般用map,class<T>,*/@Autowiredprivate RestTemplate restTemplate;// 提供多种便捷访问远程http服务的方法,简单的restful服务模板private static final String REST_URL = "http://localhost:8081";// @Override// @Nullable// public URI postForLocation(String url, @Nullable Object request, Map<String, ?> uriVariables)// throws RestClientException {// RequestCallback requestCallback = httpEntityCallback(request);// HttpHeaders headers = execute(url, HttpMethod.POST, requestCallback, headersExtractor(), uriVariables);// return (headers != null ? headers.getLocation() : null);// }// 将请求和处理请求的控制器方法关联起来,建立映射关系// 标识类:设置映射请求的请求路径的初试信息// 表示方法:设置映射请求的请求路径的具体信息@RequestMapping("/consumer/dept/get/{id}")public Dept get(@PathVariable("id") Long id) {// 服务消费者需要调用返回但是没有service 所以需要一个访问地址// 如:http://localhost:8081/dept/queryById/1return restTemplate.getForObject(REST_URL + "/dept/get/" + id, Dept.class);}@RequestMapping("/consumer/dept/add")public Boolean add(Dept dept) {return restTemplate.postForObject(REST_URL + "/dept/add/", dept, Boolean.class);}@RequestMapping("/consumer/dept/list")public List<Dept> list() {return restTemplate.getForObject(REST_URL + "/dept/queryList", List.class);}}
7:测试消费者服务调用提供者
http://localhost:8081/ 服务提供者
http://localhost:8082/ 服务消费者
http://localhost:8082/consumer/dept/get/1 通过服务消费者调用服务提供者
消费者内部实现 url 访问服务提供者 http://localhost:8082/consumer/dept/get/1


数据库得到dname为空
查询问题,消费服务端没有问题,查看消费提供者

提供者addDept 参数添加 @RequestBody 注解后提供者拿到对应值
@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);而最常用的使用请求体传参的无疑是POST请求了,所以使用@RequestBody接收数据时,一般都用POST方式进行提交。在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个
[
](https://blog.csdn.net/justry_deng/article/details/80972817)




