Spring Cloud 是在 Spring Boot 基础上构建的,用于快速构建分布式系统的通用模式的工具集。
别的理论、使用场景、历史之类的也不说了,直接切入主题。
这里,我就来架构一个简单 Spring Cloud 的应用。
既然要用,当然要与时俱进,我这里选择的是基于Spring Boot 2.0.x 的Spring Cloud Finchley。
开发工具: IDEA
JDK version: 1.8
具体的框架版本号: Spring Boot 2.0.5 RELEASE、Spring Cloud Finchley.SR3
项目管理工具: gradle ( 9102年了,maven这xml配置实在是够恶心的了
目前只是最原始的初版,使用RestTemplate简单的调用一下别的服务接口。 至于服务注册、发现、跟踪、容错、微服务网关、负载均衡之类的。之后也会慢慢写出文章的。
先把项目给搭起来。之后再要添加新的依赖增加新的功能就就简单许多了。
build.gradle文件:
group 'com.skypyb.sc'
version = '0.0.1-SNAPSHOT'
apply plugin: 'java'
sourceCompatibility = 1.8
targetCompatibility = 1.8
buildscript {
ext {
springBootVersion = '2.0.5.RELEASE'
springCloudVersion = 'Finchley.SR3'
}
repositories {
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
jcenter()
mavenCentral()
}
dependencies {//用来打包
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
allprojects {
repositories {
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
jcenter()
mavenCentral()
}
//指定编码格式
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
}
//设定子模块的通用配置
subprojects {
apply plugin: 'java'
apply plugin: 'idea'
//spring boot 插件
apply plugin: 'org.springframework.boot'
//Gradle插件,提供类似Maven的依赖关系管理功能
apply plugin: 'io.spring.dependency-management'
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
//Actuator提供服务监控与管理的功能,路径: /actuator/{端点}
compile('org.springframework.boot:spring-boot-starter-actuator')
compile('org.mybatis.spring.boot:mybatis-spring-boot-starter:1.3.2')
compile('mysql:mysql-connector-java')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
dependencyManagement {
imports {
//spring bom帮助我们在不指定版本号的情况下声明依赖项。
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
}
}
jar {
manifest.attributes provider: 'gradle'
}
}
可以看到我给所有的子模块添加了web、mysql、mybatis、Actuator的依赖。
Actuator这个东西是用于服务监控和管理的,这里不表,具体的可以看这个文章
gradle加载完毕后这个父模块就创建好了。gradle会自动给你生成一个src文件夹,删掉就行,也可以不删。反正父模块里边是不会放代码的。
然后就是建立子 module 了,子module 的创建是直接在父 module 上边右键 –> new Module 来进行创建的。当然,也是Gradle项目。
建好后将子 module 的 build.gradle文件里的东西全删掉
只留这个:
dependencies {
}
这个是用来添加该模块独有的依赖的。我这暂时为空。
我创建了一个用户微服务、一个电影微服务。里边都有具体的Dao、Service、Entity,这里就不贴了,太占位置。
我这里实现的RPC是通过Spring提供的RestTemplate,链接都是写死的,之后当然会优化。这里只是把项目运转起来。
两边的Controller层:
用户:
package com.skypyb.sc.controller;
import com.skypyb.sc.entity.User;
import com.skypyb.sc.service.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/user")
public class UserController {
private Logger logger = LoggerFactory.getLogger(UserController.class);
@Autowired
private UserService userService;
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
logger.info("access getUser method.");
return userService.getUser(id);
}
}
电影:
package com.skypyb.sc.controller;
import com.skypyb.sc.entity.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@RequestMapping("/movie")
public class MovieController {
private Logger logger = LoggerFactory.getLogger(MovieController.class);
@Autowired
private RestTemplate restTemplate;
@GetMapping("/{id}")
public User getUser(@PathVariable Long id) {
logger.info("access getUser method.");
return restTemplate.getForObject("http://localhost:8088/user/" + id, User.class);
}
}
这样子配好,启动服务时先启动 User 服务,然后启动 Movie 服务,然后通过浏览器输入 Movie 服务的接口获得数据。
最后结果是如愿以偿的得到了数据。而这份数据是 Movie 服务通过 rest 请求 User 服务所得来的。
yml文件都一样的所以只放了一个
server:
port: 8089
spring:
application:
name: sc-demo-microservice-movie #这个名字会注册到 Eureka 里去
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://192.168.8.113:3306/scdemo?serverTimezone=Asia/Shanghai
username: root
password: 614
#mybatis实体类名
mybatis:
type-aliases-package: com.skypyb.sc.entity
configuration:
#到下划线的表字段自动映射成驼峰命名法
map-underscore-to-camel-case: true
mapper-locations: classpath:mybatis/mapper/*.xml
#Actuato 配置
management:
endpoint:
# 暴露shutdown功能
# shutdown:
# enabled: true
endpoints:
web:
exposure:
include: '*' #暴露哪些端点
exclude: #隐藏哪些端点
#Eureka client端配置
eureka:
client:
service-url:
defaultZone: http://localhost:8080/eureka/
instance:
prefer-ip-address: true #将自己ip注册到Eureka Server