本次SpringCloud之微服务集成会用到之前我介绍的SpringBoot集成Mybatis的知识,不清楚的可以查看我之前的博客,链接为https://blog.csdn.net/chenpeixing361/article/details/88620189。首先简单介绍一下Spring Cloud,Spring Cloud是基于SpringBoot的一整套实现微服务的框架。它提供了微服务开发所需的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态管理等组件。具体应用如下图所示:
Spring Cloud与Dubbo的区别如下表所示:
Dubbo | Spring Cloud | |
服务注册中心 | Zookeeper | Spring Cloud Netflix Eureka |
服务调用方式 | RPC | REST API |
服务网关 | 无 | Spring Cloud Netflix Zuul |
断路器 | 不完善 | Spring Cloud Netflix Hystrix |
分布式配置 | 无 | Spring Cloud Config |
服务跟踪 | 无 | Spring Cloud Sleuth |
消息总线 | 无 | Spring Cloud Bus |
数据流 | 无 | Spring Cloud Stream |
批量任务 | 无 | Spring Cloud Task |
…… | …… | …… |
当然,还有一些区别就不列举了。总的来说Spring Cloud相对于Dubbo而言,有更加完善的分布式体系结构,组件相对更多。
接下来进入这次分享的主题,Spring Cloud之REST微服务案例,本次案例用到Spring Boot2.1.3+Mybatis3.5.0+Mysql8.0+Spring Cloud Greenwich.M1,本案例分为以下四个模块:
- spring-cloud:项目父工程,集成以下三个子模块;
- spring-cloud-api:接口子模块,主要实现公共实体类;
- spring-cloud-provider:提供者子模块,主要包含数据层,服务层以及控制层;
- spring-cloud-consumer:消费者子模块,主要包含配置层,控制层。
好了,理论介绍好了,接下来就是撸起袖子实干吧!
spring-cloud
本父工程为一个Maven模块,主要包含一个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.chen</groupId>
<artifactId>spring-cloud</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<!-- 三个子模块放在父工程下面 -->
<modules>
<module>../spring-cloud-api</module>
<module>../spring-cloud-provider</module>
<module>../spring-cloud-consumer</module>
</modules>
<properties>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<!-- springboot2.1.x对应springcloud版本为Greenwich -->
<version>Greenwich.M1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.1.3.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- 接下来一段必须要加,主要是为了能够集成Spring Cloud最新版本 -->
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>
spring-cloud-api
该模块是一个接口子模块,主要提供公共的实体User类,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>spring-cloud</artifactId>
<groupId>com.chen</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../spring-cloud/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-api</artifactId>
<dependencies>
<dependency>
<!-- 当前Module需要用到的jar包,按自己需求添加,如果父类已经包含了,可以不用版本 -->
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
User类代码如下:
package com.chen.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* @Author:autumn_leaf
* @Date:2019/03/19
* 用户实体类
*/
@SuppressWarnings("serial")
@AllArgsConstructor
@NoArgsConstructor
@Data
@Accessors(chain = true)
public class User implements Serializable {
private Integer id;//主键
private String loginName;//登录名
private String username;//用户名
private char sex;//性别
private int age;//年龄
}
其中因为在pom.xml配置了lombok,所以在写User类时可以用注解表示无参和有参构造函数,getter和setter方法以及toString函数,equal函数等等,确实非常方便。到这儿之后我们点击右边的Maven Projects,找到install,双击,直至出现Build Success,代表生成了可供提供者和消费者调用的jar包,截图如下:
spring-cloud-provider
该子模块项目树如下图所示:
我们先配置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>spring-cloud</artifactId>
<groupId>com.chen</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../spring-cloud/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-provider</artifactId>
<dependencies>
<!-- 引入自定义的接口模块 -->
<dependency>
<groupId>com.chen</groupId>
<artifactId>spring-cloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!-- 热部署插件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
配置文件application.yml代码如下:
#端口
server:
port: 8081
#spring连接数据库配置
spring:
application:
name: spring-cloud-user
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/springdatajpa?serverTimezone=GMT%2B8&characterEncoding=utf8
driver-class-name: com.mysql.cj.jdbc.Driver
#mybatis配置环境
mybatis:
mapper-locations: classpath:mapping/*Mapper.xml
type-aliases-package: com.chen.entity
#显示sql
logging:
level:
com:
chen:
dao : debug
接下里的步骤有点类似我之前写的一篇关于SpringBoot整合Mybatis的,我们新建UserDao数据接口类,代码如下:
package com.chen.dao;
import com.chen.entity.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @Author:autumn_leaf
* @Date:2019/03/19
* 用户接口类
*/
@Mapper
public interface UserDao {
User findById(int id);
List<User> findAll();
}
我们在src/main/resources目录下创建UserMapper.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.chen.dao.UserDao">
<select id="findById" resultType="com.chen.entity.User" parameterType="Integer">
select * from tb_user where id = #{id};
</select>
<!-- 返回值为list,resultType仍为User,而不是List -->
<select id="findAll" resultType="com.chen.entity.User">
select * from tb_user;
</select>
</mapper>
接下来我们创建服务接口层UserService,代码如下:
package com.chen.service;
import com.chen.entity.User;
import java.util.List;
/**
* @Author:autumn_leaf
* @Date:2019/03/19
* 服务接口类
*/
public interface UserService {
User findById(int id);
List<User> findAll();
}
然后是服务接口继承类UserServiceImpl,代码如下:
package com.chen.service.impl;
import com.chen.dao.UserDao;
import com.chen.entity.User;
import com.chen.service.UserService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserDao userDao;
public User findById(int id) {
return userDao.findById(id);
}
public List<User> findAll() {
return userDao.findAll();
}
}
最后到控制层了,我们新建UserController类,代码如下:
package com.chen.controller;
import com.chen.entity.User;
import com.chen.service.UserService;
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.RestController;
import java.util.List;
/**
* @Author:autumn_leaf
* @Date:2019/03/19
* 提供者控制类
*/
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/user/{id}")
public User findById(@PathVariable("id") int id){
return userService.findById(id);
}
@GetMapping("/user/list")
public List<User> findAll(){
return userService.findAll();
}
}
好了,到这儿提供者子模块可以运行了,运行截图如下所示。
spring-cloud-consumer
该消费者子模块包含配置层和控制层两个部分,模块树如下图所示:
其中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>spring-cloud</artifactId>
<groupId>com.chen</groupId>
<version>1.0-SNAPSHOT</version>
<relativePath>../spring-cloud/pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-cloud-consumer</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 引入自定义的接口模块 -->
<dependency>
<groupId>com.chen</groupId>
<artifactId>spring-cloud-api</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!-- 热部署插件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
application.yml代码很简单,仅需要配置端口就行,如下:
server:
port: 8080
这里多了一个配置层,其实相当于SSM框架中ApplicationContext.xml文件一样,把bean组件注入进去,方便调用,ConfigBean类代码如下:
package com.chen.cfgbean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @Author:autumn_leaf
* @Date:2019/03/19
* 配置类
*/
@Configuration//该配置等同于SSM框架中的applicaitonContext.xml
public class ConfigBean {
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
然后是控制类UserController_Consumer,代码如下:
package com.chen.controller;
import com.chen.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.List;
/**
* @Author:autumn_leaf
* @Date:2019/03/19
* 消费者控制类
*/
@RestController
public class UserController_Consumer {
private static final String REST_URL_PREFIX = "http://localhost:8081";
/**
* 使用RestTemplate访问接口,三个参数(url,requestMap,ResponseBean.class)
* 分别代表REST请求地址,请求参数,HTTP响应转换被转换成的对象类型
*/
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/consumer/user/{id}")
public User findById(@PathVariable("id") int id){
return restTemplate.getForObject(REST_URL_PREFIX+"/user/"+id,User.class);
}
@SuppressWarnings("unchecked")
@RequestMapping("/consumer/user/list")
public List<User> findAll(){
return restTemplate.getForObject(REST_URL_PREFIX+"/user/list",List.class);
}
}
上述代码我们调用了接口模块的公共实体类User,同时调用了提供者模块的访问结果,记住,消费者只需要消费,而不管中间过程如何,好了,敲完收工,接下来是运行阶段了,注意,必须先运行提供者的main方法,后运行消费者main方法,运行结果截图如下:
好了,这次的讲解就到这里了,有疑惑的同学可以在下方评论区留言哦!