SpringCloud是什么?
SpringCloud
是一个基于SpringBoot
实现的微服务架构开发工具。 它为微服务架构中涉及的配置管理、 服务治理、 断路器、 智能路由、 微代理、 控制总线、 全局锁、 决策竞选、 分布式会话和集群状态管理等操作提供了一 种简单的开发方式。总结为以下两点:
SpringCloud
是分布式一站式的解决方案。SpringCloud
是微服务技术的一种落地的体现和实现。
SpringCloud和SpringBoot的区别和关系?
SpringBoot
专注于快速方便的开发单个个体微服务。SpringCloud
是关注全局的微服务协调整理治理框架以及一整套的落地解决方案,它将SpringBoot
开发的一个个单体微服务整合并管理起来,为各个微服务之间提供:配置管理,服务发现,断路器,路由,微代理,事件总线等的集成服务。SpringBoot
可以离开SpringCloud
独立使用,但是SpringCloud
离不开SpringBoot
,属于依赖的关系。
总结:SpringBoot专注于快速,方便的开发单个微服务个体,SpringCloud关注全局的服务治理框架。
SpringCloud和Dubbo区别和对比
- SpringCloud功能比Dubbo更加强大,涵盖面更广,并且作为Spring的拳头项目,它能够与Spring Framework,SpringBoot,Spring Data等其他Spring项目完美整合,这些对于微服务而言是至关重要的。
- 而使用Dubbo构建的微服务架构就像组装电脑,各环节我们的选择自由度很高,但是最终很可能因为一条内存质量不行就点不亮了,而SpringCloud就像品牌机,在Spring Source的整合下,做了大量的兼容性测试,保证了机器拥有更高的稳定性,但是如果要在使用非原装组件外的东西,就需要对其基础有足够的了解。
- 那么最大的区别在于:SpringCloud抛弃了Dubbo的RPC通信,采用的是基于HTTP的REST方式。
Rest微服务项目实战
就简单做一个用户管理的服务吧,Consumer消费者(Client)通过REST调用Provider提供者(Server)提供的服务
创建Maven项目作为父项目
POM.xml
配置如下,注意父项目打包类型<packaging>pom</packaging>
<?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.zealzhangz</groupId>
<artifactId>user-management</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>dto</module>
<module>microservice-cloud-provider-user-8001</module>
<module>microservice-cloud-consumer-user-8002</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<junit.version>4.12</junit.version>
<log4j.version>1.2.17</log4j.version>
<lombok.version>1.16.18</lombok.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.10.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.0.4</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.31</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<inherited>true</inherited>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
创建第一个子模块
DTO
数据传输对象模块,该模块定义PO VO
等,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>user-management</artifactId>
<groupId>com.zealzhangz</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>dto</artifactId>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
</project>
- 该模块的目录结构如下
.
├── main
│ ├── java
│ │ └── com
│ │ └── zealzhangz
│ │ └── dto
│ │ ├── po
│ │ │ └── User.java
│ │ └── vo
│ └── resources
└── test
└── java
User.java
package com.zealzhangz.dto.po;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author Created by xxxx.<br/>
* @version Version: 1.0
*/
//set设置值/get获取值注解
@Data
//无参数构造注解
@NoArgsConstructor
public class User {
private Integer id;
private String name;
private Short age;
private Byte gender;
/**
* 来自那个数据库,因为微服务架构可以一个服务对应一个数据库,同一个信息被存储到不同数据库。
*/
private String dbSource;
}
创建第二个模块--用户服务提供者
主要提供用户信息的CRUD
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>user-management</artifactId>
<groupId>com.zealzhangz</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>microservicecloud-provider-user-8001</artifactId>
<dependencies>
<!-- 引入自己定义的api通用包,可以使用User用户Entity -->
<dependency>
<groupId>com.zealzhangz</groupId>
<artifactId>dto</artifactId>
<version>${project.version}</version>
</dependency>
<!-- actuator监控信息完善 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</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>
</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>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</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-test</artifactId>
</dependency>
<!-- 修改后立即生效,热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
- 代码结构
.
├── main
│ ├── java
│ │ └── com
│ │ └── zealzhangz
│ │ ├── UserProvider8001App.java
│ │ ├── controller
│ │ │ └── UserController.java
│ │ ├── dao
│ │ │ └── UserDao.java
│ │ └── service
│ │ ├── UserService.java
│ │ └── impl
│ │ └── UserServiceImpl.java
│ └── resources
│ ├── application.yml
│ └── mybatis
│ ├── mapper
│ │ └── UserMapper.xml
│ └── mybatis.cfg.xml
└── test
└── java
- 创建配置文件 主要配置服务端口,数据源,数据库连接池等信息
server:
port: 8001
mybatis:
config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文件所在路径
type-aliases-package:
mapper-locations:
- classpath:mybatis/mapper/**/*.xml # mapper映射文件
spring:
application:
name: microservicecloud-user
datasource:
driver-class-name: org.gjt.mm.mysql.Driver # mysql驱动包
url: jdbc:mysql://localhost:3306/user_db # 数据库名称
username: root
password: root
druid:
initial-size: 1 # 数据库连接池的最小维持连接数
max-active: 3
min-idle: 1 # 初始化连接数
max-wait: 10
test-while-idle: true
validation-query: SELECT 1 FROM DUAL
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
instance:
instance-id: microservicecloud-user-8001
prefer-ip-address: true #访问路径可以显示IP地址
ip-address: 127.0.0.1
metadata-map:
fixed-s1: "value_1"
info:
app.name: zhanga-micro-service-cloud
company.name: www.zhangaoo.com #我的博客地址
build.artifactId: @project.artifactId@
build.version: @project.version@
mybatis.cfg.xml mybatis
配置文件
<?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>
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.zealzhangz.dao.UserDao">
<resultMap id="user" type="com.zealzhangz.dto.po.User">
<result column="db_source" jdbcType="VARCHAR" property="dbSource" />
</resultMap>
<select id="findUserByName" resultMap="user" parameterType="com.zealzhangz.dto.po.User">
select id,name,age,gender,db_source from user where name=#{name};
</select>
<select id="getAll" resultMap="user">
select id,name,age,gender,db_source from user;
</select>
<insert id="addUser" parameterType="com.zealzhangz.dto.po.User">
INSERT INTO user(name,age,gender,db_source) VALUES(#{name},#{age},#{gender},#{dbSource});
</insert>
</mapper>
mysql
数据库脚本
DROP DATABASE IF EXISTS user_db;
CREATE DATABASE user_db CHARACTER SET UTF8;
USE user_db;
CREATE TABLE user
(
id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(60) NOT NULL DEFAULT '' COMMENT '姓名',
age TINYINT NOT NULL DEFAULT 0 COMMENT '年龄',
gender TINYINT NOT NULL DEFAULT 0 COMMENT '男:1,女:0',
db_source VARCHAR(60) NOT NULL DEFAULT 'db1' COMMENT '来自那个数据库,因为微服务架构可以一个服务对应一个数据库'
);
INSERT INTO user(name,age,gender,db_source) VALUES('zhangsan',18,1,DATABASE());
INSERT INTO user(name,age,gender,db_source) VALUES('lisi',19,0,DATABASE());
INSERT INTO user(name,age,gender,db_source) VALUES('wangwu',20,1,DATABASE());
INSERT INTO user(name,age,gender,db_source) VALUES('zengliu',21,0,DATABASE());
INSERT INTO user(name,age,gender,db_source) VALUES('chengli',22,1,DATABASE());
- UserDao.java
package com.zealzhangz.dao;
import com.zealzhangz.dto.po.User;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @version Version: 1.0
* @date DateTime: 2018/08/15 00:22:00<br/>
*/
@Mapper
public interface UserDao {
/**
* add a user to db
* @param user
*/
void addUser(User user);
/**
* find a user by user name
* @param user
* @return
*/
User findUserByName(User user);
/**
* get all user
* @return
*/
List<User> getAll();
}
- UserService.java
package com.zealzhangz.service;
import com.zealzhangz.dto.po.User;
import java.util.List;
/**
* @version Version: 1.0
* @date DateTime: 2018/08/15 00:32:00<br/>
*/
public interface UserService {
/**
* add a user to db
* @param user
*/
void addUser(User user);
/**
* find a user by user name
* @param user
* @return
*/
User findUserByName(User user);
/**
* get all user
* @return
*/
List<User> getAll();
}
- UserServiceImpl.java
package com.zealzhangz.service.impl;
import com.zealzhangz.dao.UserDao;
import com.zealzhangz.dto.po.User;
import com.zealzhangz.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @version Version: 1.0
* @date DateTime: 2018/08/15 00:33:00<br/>
*/
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserDao userDao;
@Override
public void addUser(User user){
userDao.addUser(user);
}
@Override
public User findUserByName(User user){
return userDao.findUserByName(user);
}
@Override
public List<User> getAll(){
return userDao.getAll();
}
}
- UserController.java
package com.zealzhangz.controller;
import com.zealzhangz.dto.po.User;
import com.zealzhangz.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* @version Version: 1.0
* @date DateTime: 2018/08/15 00:39:00<br/>
*/
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping(value="/add",method= RequestMethod.POST)
public String addUser(@RequestBody User user){
userService.addUser(user);
return "SUCCESS";
}
@RequestMapping(value="/get/{name}",method=RequestMethod.GET)
public User get(@PathVariable("name") String name) {
User user = new User();
user.setName(name);
return userService.findUserByName(user);
}
@RequestMapping(value="/list",method=RequestMethod.GET)
public List<User> list() {
return userService.getAll();
}
}
- 最后添加启动入口
UserProvider8001App.java
package com.zealzhangz;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @version Version: 1.0
* @date DateTime: 2018/08/15 00:44:00<br/>
*/
@SpringBootApplication
public class UserProvider8001App {
public static void main(String[] args) {
SpringApplication.run(UserProvider8001App.class,args);
}
}
- 运行访问接口
http://127.0.0.1:8001/user/list
[
{
"id": 1,
"name": "zhangsan",
"age": 18,
"gender": 1,
"dbSource": "user_db"
},
{
"id": 2,
"name": "lisi",
"age": 19,
"gender": 0,
"dbSource": "user_db"
}
]
创建第三个模块--用户服务消费者
该模块直接调用用户服务提供者的服务
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>user-management</artifactId>
<groupId>com.zealzhangz</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>microservice-cloud-consumer-user-8002</artifactId>
<dependencies>
<!-- 引入自己定义的api通用包,可以使用User用户Entity -->
<dependency>
<groupId>com.zealzhangz</groupId>
<artifactId>dto</artifactId>
<version>${project.version}</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-jetty</artifactId>
</dependency>
<!-- 修改后立即生效,热部署 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>springloaded</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
</dependency>
</dependencies>
</project>
- 代码结构目录
.
├── main
│ ├── java
│ │ └── com
│ │ └── zealzhangz
│ │ ├── UserConsumer8002App.java
│ │ ├── config
│ │ │ └── ConfigBean.java
│ │ └── controller
│ │ └── UserControlerConsumer.java
│ └── resources
│ └── application.yml
└── test
└── java
application.yml
配置文件 主要定义服务端口
server:
port: 8002
- 创建一个ConfigBean类
package com.zealzhangz.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @version Version: 1.0
* @date DateTime: 2018/08/15 20:54:00<br/>
*/
@Configuration
public class ConfigBean {
/**
* RestTemplate提供了多种便捷访问远程Http服务的方法,
* 是一种简单便捷的访问restful服务模板类,是Spring提供的用于访问Rest服务的客户端模板工具集。
*/
@Bean
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
- UserControllerConsumer.java
package com.zealzhangz.controller;
import com.zealzhangz.dto.po.User;
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;
import java.util.List;
/**
* @version Version: 1.0
* @date DateTime: 2018/08/15 20:57:00<br/>
*/
@RestController
@RequestMapping("/consumer/user")
public class UserControllerConsumer {
private static final String REST_URL_PREFIX = "http://localhost:8001";
@Autowired
private RestTemplate restTemplate;
@RequestMapping("/add")
public String add(User user){
return restTemplate.postForObject(REST_URL_PREFIX + "/user/add",user,String.class);
}
@RequestMapping("/get/{name}")
public User get(@PathVariable("name") String name){
return restTemplate.getForObject(REST_URL_PREFIX + "/user/get/" + name,User.class);
}
@RequestMapping("/list")
public List<User> list(){
return restTemplate.getForObject(REST_URL_PREFIX + "/user/list",List.class);
}
}
- 创建启动入口类
package com.zealzhangz;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @version Version: 1.0
* @date DateTime: 2018/08/15 21:17:00<br/>
*/
@SpringBootApplication
public class UserConsumer8002App {
public static void main(String[] args) {
SpringApplication.run(UserConsumer8002App.class,args);
}
}
- 访问接口
http://127.0.0.1:8002/consumer/user/list
[
{
"id": 1,
"name": "zhangsan",
"age": 18,
"gender": 1,
"dbSource": "user_db"
},
{
"id": 2,
"name": "lisi",
"age": 19,
"gender": 0,
"dbSource": "user_db"
}
]
总结
经过上面简单的几个步骤就建立了一个完整微服务示例,后面还会集成更多的SpringCloud
组件,让我们的系统更加健壮
本文由 zealzhangz 创作,采用 知识共享署名4.0 国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为:
2018/08/25 14:26