有看过我以前的SSM系列的朋友应该有一点印象是很是深入的。前端
那就是须要配置的配置文件很是多,什么
Spring
、mybatis
、redis
、mq
之类的配置文件很是多,而且还存在各类版本,甚至有些版本还互不兼容。其中有不少可能就是刚开始整合的时候须要配置,以后压根就不会再动了。java
鉴于此,Spring
又推出了又一神器SpringBoot.git
它可让咱们更加快速的开发Spring
应用,甚至作到了开箱即用。
因为在实际开发中咱们使用SpringBoot
+SpringCloud
进行了一段时间的持续交付,并在生产环境获得了验证,其中也有很多踩坑的地方,借此机会和你们分享交流一下。github
本篇咱们首先会用利用SpringBoot
构建出一个简单的REST API
.
接着会建立另外一个SpringBoot
项目,基于SpringCloud
部署,并在两个应用之间进行调用。web
SpringBoot
构建REST API
咱们可使用Spring
官方提供的初始化工具帮咱们生成一个基础项目:start.spring.io/,以下图所示:
redis
填入相应信息便可。因为只是要实现REST API
因此这里只须要引用web
依赖便可。spring
将生成好的项目导入IDE
(我使用的是idea
)中,目录结构以下;
后端
SbcUserApplication
是整个应用的入口。resource/application.properties
这里是存放整个应用的配置文件。static
和templates
是存放静态资源以及前端模板的地方,因为咱们采用了先后端分离,因此这些目录基本上用不上了。经过运行SbcUserApplication
类的main
方法能够启动SpringBoot
项目。api
接着在PostMan
中进行调用,看到如下结果代表启动成功了:springboot
这样一看是否是要比以前用Spring+SpringMVC
来整合要方便快捷不少。
SpringBoot
项目当咱们的项目采用微服务构建以后天然就会被拆分红N多个独立的应用。好比上文中的sbc-user
用于用户管理。这里再建立一个sbc-order
用户生成订单。
为了方便以后的代码复用,我将
common
包中的一些枚举值、工具类单独提到sbc-common
应用中了,这样有其余应用要使用这些基础类直接引入这个依赖便可。
<dependency>
<groupId>com.crossoverJie</groupId>
<artifactId>sbc-common</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>复制代码
建立步骤和上文差很少,这里就再也不赘述了。
其中有一个order/getOrderNo
的服务,调用结果以下:
以后会利用SpringCloud
来将两个服务关联起来,并能够互相调用。
SpringCloud
进行分布式调用eureka
注册中心既然是要搭建微服务那天然少不了注册中心了,以前讲的dubbo
采用的是zookeeper
做为注册中心,SpringCloud
则采用的是Netflix Eureka
来作服务的注册与发现。
新建一个项目sbc-service
,目录结构以下:
核心的pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.1</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Brixton.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>复制代码
很是easy,只须要引入eureka
的依赖便可。
而后在入口类加入一个注解@EnableEurekaServer
,便可将该项目做为服务注册中心:
package com.crossoverJie.service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
private final static Logger logger = LoggerFactory.getLogger(EurekaApplication.class);
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
logger.info("SpringBoot Start Success");
}
}复制代码
接着修改配置文件application.properties
:
server.port=8888
# 不向注册中心注册本身
eureka.client.register-with-eureka=false
# 不须要检索服务
eureka.client.fetch-registry=false
eureka.client.serviceUrl.defaultZone=http://localhost:${server.port}/eureka/复制代码
配置一下端口以及注册中心的地址便可。
而后按照正常启动springBoot
项目同样启动便可。
在地址栏输入http://localhost:8888看到一下界面:
固然如今在注册中心还看不到任何一个应用,下面须要将上文的sbc-user,sbc-order
注册进来。
只须要在application.properties
配置文件中加上注册中心的配置:
eureka.client.serviceUrl.defaultZone=http://localhost:8888/eureka/复制代码
并在sbc-order
的主类中加入@EnableDiscoveryClient
注解便可完成注册服务。
启动注册中心以及应用,在注册中心看到一下界面则成功注册:
服务是注册上去了,天然是须要消费了,这里就简单模拟了在调用http://localhost:8080/user/getUser
这个接口的时候getUser
接口会去调用order
的getOrder
服务。
这里会用到另外一个依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>复制代码
他能够帮咱们作到客户端负载,具体使用以下:
@LoadBalanced
客户端负载。restTemplate
类的实例@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}复制代码
restTemplate
调用远程服务:@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/getUser",method = RequestMethod.POST)
public UserRes getUser(@RequestBody UserReq userReq){
OrderNoReq req = new OrderNoReq() ;
req.setReqNo("1213");
//调用远程服务
ResponseEntity<Object> res = restTemplate.postForEntity("http://sbc-order/order/getOrderNo", req, Object.class);
logger.info("res="+JSON.toJSONString(res));
logger.debug("入参="+ JSON.toJSONString(userReq));
UserRes userRes = new UserRes() ;
userRes.setUserId(123);
userRes.setUserName("张三");
userRes.setReqNo(userReq.getReqNo());
userRes.setCode(StatusEnum.SUCCESS.getCode());
userRes.setMessage("成功");
return userRes ;
}复制代码
因为个人远程接口是post
,因此使用了postForEntity()
方法,若是是get
就换成getForEntity()
便可。
注意这里是使用应用名
sbc-order(配置于sbc-order的application.properties中)
来进行调用的,并非一个IP地址。
启动注册中心、两个应用。
用PostMan
调用getUser
接口时控制台打印:
2017-06-27 00:18:04.534 INFO 63252 --- [nio-8080-exec-3] c.c.sbcuser.controller.UserController : res={"body":{"code":"4000","message":"appID不能为空","reqNo":"1213"},"headers":{"X-Application-Context":["sbc-order:8181"],"Content-Type":["application/xml;charset=UTF-8"],"Transfer-Encoding":["chunked"],"Date":["Mon, 26 Jun 2017 16:18:04 GMT"]},"statusCode":"OK","statusCodeValue":200}复制代码
因为并无传递appId
因此order
服务返回了一个错误,也正说明是远程调用到了该服务。
ps:这里只是简单使用了
ribbon
来进行服务调用,但在实际的开发中仍是比较少的使用这种方式来调用远程服务,而是使用Feign
进行声明式调用,能够简化客户端代码,具体使用方式请持续关注。
本次算是springBoot+springCloud
的入门,还有不少东西没有讲到,以后我将会根据实际使用的一些经验继续分享SpringCloud
这个新兴框架。
我的博客地址:crossoverjie.top。