1.RestTemplate是什么?
RestTemplate是Spring对Http客户端进行封装的一个模板工具类,对常用的Http客户端例如:HttpClient、OKHttp、JDK原生的URLConnection(默认的)都支持。
2.RestTemplate能做什么?
基于Restful风格可以对远程服务基于http协议进行远程调用
一:小demo:
RestTemplate的使用
新建一个父工程,命名为 microservice_cloud_01
创建父模块:
父工程,父模块创建完毕
目录结构如下图:
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.xhn</groupId> <artifactId>microservice_cloud_01</artifactId> <version>1.0-SNAPSHOT</version> <!--对应的子类--> <modules> <module>microservice_cloud_02_api</module> <module>microservice_cloud_04_consumer_productor_80</module> <module>microservice_cloud_03_provider_product_8001</module> </modules> <!--手动指定 pom--> <packaging>pom</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.7.RELEASE</version> </parent> <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> <spring-cloud.version>Finchley.SR2</spring-cloud.version> </properties> <!--依赖声明--> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.12</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.13</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> </dependencies> </project>
一。新建子模块,命名为 microservice_cloud_02_api(用来存放实体类,与数据库表对应)
目录结构如下图:
实体类Product:
package com.xhn.springcloud.entities; import java.io.Serializable; //如果要实现跨服访问使用,需要将类序列化 public class Product implements Serializable { private Long id; private String productName; private String dbSource; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getProductName() { return productName; } public void setProductName(String productName) { this.productName = productName; } public String getDbSource() { return dbSource; } public void setDbSource(String dbSource) { this.dbSource = dbSource; } @Override public String toString() { return "Product{" + "id=" + id + ", productName='" + productName + '\'' + ", dbSource='" + dbSource + '\'' + '}'; } public Product(Long id, String productName, String dbSource) { this.id = id; this.productName = productName; this.dbSource = dbSource; } public Product() { } }
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>microservice_cloud_01</artifactId> <groupId>com.xhn</groupId> <version>1.0-SNAPSHOT</version> <relativePath>../../microservice_cloud_01/pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>microservice_cloud_02_api</artifactId> </project>
实体类装备完成
二。新建第二个子模块(和前边创建一样)
命名为 microservice_cloud_03_provider_product_8001(业务逻辑操作和mapper操作数据库<mapper接口和mapper映射>)
各配置和代码:
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>microservice_cloud_01</artifactId> <groupId>com.xhn</groupId> <version>1.0-SNAPSHOT</version> <relativePath>../../microservice_cloud_01/pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>microservice_cloud_03_provider_product_8001</artifactId> <dependencies> <dependency> <groupId>com.xhn</groupId> <artifactId>microservice_cloud_02_api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>1.3.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> <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> <version>1.1.12</version> </dependency> </dependencies> </project>
ProductController:
package com.xhn.springcloud.controller; import com.xhn.springcloud.entities.Product; import com.xhn.springcloud.service.ProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/product") public class ProductController { @Autowired private ProductService productService; //查询出所有数据 @RequestMapping(value = "/get/list",method = RequestMethod.GET) public List<Product> list(){ return productService.list(); } //添加数据 @RequestMapping(value = "/add",method = RequestMethod.POST) public boolean add(@RequestBody Product product){ return productService.add(product); } //删除操作 @RequestMapping(value = "/delete/{id}",method = RequestMethod.DELETE) public boolean delete(@PathVariable("id" ) Long id){ return productService.delete(id); } //修改操作 //先查询单个数据 @RequestMapping(value = "/get/{id}",method = RequestMethod.GET) public Product getProductById(@PathVariable("id" ) Long id){ return productService.getProductById(id); } @RequestMapping(value = "/update",method = RequestMethod.PUT) public boolean update(Product product){ return productService.update(product); } }
ProductMapper:
package com.xhn.springcloud.mapper; import com.xhn.springcloud.entities.Product; import java.util.List; public interface ProductMapper { //增加 boolean add(Product product); //删除 boolean delete(Long id); //查询所有数据 List<Product> list(); //修改 查询单条数据 Product getProductById(Long id); //修改 将查询到的单条数据修改 boolean update(Product product); }
ProductMapper.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"> <mapper namespace="com.xhn.springcloud.mapper.ProductMapper"> <select id="getProductById" resultType="Product" parameterType="Long"> select id,product_name,db_source from product where id=#{id} </select> <select id="list" resultType="Product"> select id,product_name,db_source from product </select> <insert id="add" parameterType="Product"> INSERT INTO product(product_name,db_source) VALUES(#{productName},DATABASE()) </insert> <update id="update" parameterType="Product"> update product p set p.product_name=#{productName},p.db_source=#{dbSource} where p.id=#{id} </update> <delete id="delete" parameterType="Long"> delete from product p where p.id=#{id} </delete> </mapper>
mybatis.cfg.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="mapUnderscoreToCamelCase" value="true"/> </settings> </configuration>
application.yml:
server:
port: 8001
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
type-aliases-package: com.xhn.springcloud.entities # 所有Entity别名类所在包
mapper-locations: classpath:mybatis/mapper/**/*.xml # mapper映射文件
spring:
application:
name: microservice-product #这个很重要,这在以后的服务与服务之间相互调用一般都是根据这个name
datasource:
type: com.alibaba.druid.pool.DruidDataSource # 当前数据源操作类型
driver-class-name: com.mysql.jdbc.Driver # mysql驱动包
url: jdbc:mysql://127.0.0.1:3306/springcloud_product?serverTimezone=GMT%2B8 # 数据库名称
username: root
password: root
dbcp2:
min-idle: 5 # 数据库连接池的最小维持连接数
initial-size: 5 # 初始化连接数
max-total: 5 # 最大连接数
max-wait-millis: 150 # 等待连接获取的最大超时时间
ProductServiceImpl:
package com.xhn.springcloud.service.impl; import com.xhn.springcloud.entities.Product; import com.xhn.springcloud.mapper.ProductMapper; import com.xhn.springcloud.service.ProductService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.List; @Service public class ProductServiceImpl implements ProductService { @Autowired private ProductMapper productMapper; @Override public boolean add(Product product) { return productMapper.add(product); } @Override public boolean delete(Long id) { return productMapper.delete(id); } @Override public List<Product> list() { return productMapper.list(); } @Override public Product getProductById(Long id) { return productMapper.getProductById(id); } @Override public boolean update(Product product) { return productMapper.update(product); } }
ProductService:
package com.xhn.springcloud.service; import com.xhn.springcloud.entities.Product; import java.util.List; public interface ProductService { //增加 boolean add(Product product); //删除 boolean delete(Long id); //查询所有数据 List<Product> list(); //修改 查询单条数据 Product getProductById(Long id); //修改 将查询到的单条数据修改 boolean update(Product product); }
8001主启动类StratApplication:
package com.xhn.springcloud; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @MapperScan("com.xhn.springcloud.mapper") @SpringBootApplication public class StratApplication { public static void main(String[] args) { SpringApplication.run(StratApplication.class,args); } }
三。新建第二个子模块(和前边创建一样)
各大配置和java代码:
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>microservice_cloud_01</artifactId> <groupId>com.xhn</groupId> <version>1.0-SNAPSHOT</version> <relativePath>../../microservice_cloud_01/pom.xml</relativePath> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>microservice_cloud_04_consumer_productor_80</artifactId> <dependencies> <dependency> <groupId>com.xhn</groupId> <artifactId>microservice_cloud_02_api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> </project>
RestConfigraion
package com.xhn.springcloud.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration //创建配置类 public class RestConfigraion { @Bean public RestTemplate restTemplate(){ return new RestTemplate(); } }
controller层:
package com.xhn.springcloud.controller; import com.xhn.springcloud.entities.Product; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import java.util.List; @RestController @RequestMapping("/consumer") public class ConsumerController { private static final String STRING_URL="http://localhost:8001/product"; @Autowired private RestTemplate restTemplate; @RequestMapping("/get/list") public List<Product> list(){ List<Product> list = restTemplate.getForObject(STRING_URL + "/get/list", List.class); return list; } //获取单个数据 @RequestMapping("/findById/{id}") public Product findById(){ Product product = restTemplate.getForObject(STRING_URL + "/get/{id}", Product.class); return product; } }
主启动类:
package com.xhn.springcloud; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; @SpringBootApplication @EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class}) public class ProductApplication { public static void main(String[] args) { SpringApplication.run(ProductApplication.class,args); } }
代码验证;
测试使用
分别启动eureka-provider01和eureka-consumer01,启动顺序没关系
浏览器访问http://127.0.0.1:8080/findById/1
总结
在ConsumerController中,RestTemplate调用远程服务
User user = restTemplate.getForObject("http://127.0.0.1:8081/findById", User.class);
1
RestTemplate通过getForObject方法传递url地址及实体类的字节码,自动发起请求,接收响应,并且帮我们对响应结果通过SpringMVC内置的Jackson中的ObjectMapper进行json反序列化,最后返回一个User对象
虽然RestTemplate能够调用远程服务,但是这样还存在着很多问题:
1、请求地址http://127.0.0.1:8081/findById硬编码了,如果更换环境,那么需要更改大量的代码
2、并没有一个中心来控制并管理provider和consumer之间的关系与调用
3、使用RestTemplate调用远程服务代码开发量相对而言大,现在的Demo是业务简单,只需要简单调用getForObject就能获取数据。事实上,RestTemplate还有大量基于Http协议的方法,比如delete()、getForEntity()、getForObject()、put()、headForHeaders()等。但是在后期的SpringCloud学习过程中,Feign作为SpringCloud的核心组件,用于远程服务调用,也是基于Http协议,并且支持注解开发,能够大量减少发