前言

今天想要开发一个springcloud项目,使用idea2018.2版本,和maven3.6.0,和jdk1.8,话不多说,直接开干。

操作

1、首先我们要新建一个maven父工程,这个工程用来包装我们所有的微服务model。

搭建springcloud项目——简单明了_spring

搭建springcloud项目——简单明了_eureka_02

搭建springcloud项目——简单明了_java_03

搭建springcloud项目——简单明了_java_04

2、完成后项目如下图,但是由于是父工程,建议删除src文件

搭建springcloud项目——简单明了_eureka_05

然后在pom.xml里面添加配置文件,如图所示

搭建springcloud项目——简单明了_eureka_06

配置文件代码为:

<!--基于springboot开发-->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.6.RELEASE</version>
<relativePath/>
</parent>
<!--父工程引入springcloud配置-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

3、然后右击项目工程选择new,model添加子工程

eureka-server

搭建springcloud项目——简单明了_spring_07

4、前几步与创建父工程一样

搭建springcloud项目——简单明了_spring_08

5、起一个子工程的项目名称,这里我们是要新建一个注册中心eureka

搭建springcloud项目——简单明了_经验分享_09

搭建springcloud项目——简单明了_经验分享_10

搭建springcloud项目——简单明了_eureka_11

6、在eureka工程里面添加配置

搭建springcloud项目——简单明了_spring boot_12

配置文件为:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka-server</artifactId>
</dependency>

7、在eurka中新建java和resource文件夹

搭建springcloud项目——简单明了_spring_13

8、在resource下新建application.yml,并加入如下内容

搭建springcloud项目——简单明了_eureka_14

server:
port: 8761
eureka:
instance:
hostname: localhost
client:
register-with-eureka: false
fetch-registry: false
service-url:
defaultZone:
http://${eureka.instance.hostname}:${server.port}/eureka/

9、我们新建启动类,如图

搭建springcloud项目——简单明了_spring_15

package com.xiaoqi.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String [] args){
SpringApplication.run(EurekaApplication.class, args);
}
}

10、给java文件夹添加属性

搭建springcloud项目——简单明了_eureka_16

然后我们启动就创建完成eureka了

搭建springcloud项目——简单明了_spring boot_17

网页访问http://localhost:8761/ 如下图所示证明成功。

搭建springcloud项目——简单明了_spring_18

eureka-user

1、现在我们来搭建eureka-user服务model,首先还是在父工程下新建一个model

搭建springcloud项目——简单明了_eureka_19

中间步骤跟创建eureka-server相同,我就不再赘述。

搭建springcloud项目——简单明了_java_20

文件夹位置要注意在父目录之下。

pom.xml文件添加如下配置

搭建springcloud项目——简单明了_经验分享_21

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-start-eureka</artifactId>
</dependency>

application.yml配置

搭建springcloud项目——简单明了_经验分享_22

server:
port: 8000
eureka:
instance:
prefer-ip-address: true
client:
service-rul:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: eureka-user

创建Application类

搭建springcloud项目——简单明了_spring_23

@EnableEurekaClient
@RestController
public class Application {
@RequestMapping("/hello")
public String home(){
return "hello world!";
}
public static void main(String [] args){
SpringApplication.run(Application.class, args);
}
}

启动Application

搭建springcloud项目——简单明了_经验分享_24

访问http://localhost:8761/ 页面显示如下图证明成功

搭建springcloud项目——简单明了_spring_25

eureka-order

首先在父工程下创建一个model

搭建springcloud项目——简单明了_eureka_26

搭建springcloud项目——简单明了_eureka_27

搭建springcloud项目——简单明了_spring boot_28

搭建springcloud项目——简单明了_spring_29

pom.xml中添加配置

搭建springcloud项目——简单明了_spring boot_30

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

application.yml配置

搭建springcloud项目——简单明了_经验分享_31

server:
port: 7900
eureka:
instance:
prefer-ip-address: true
client:
service-rul:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: eureka-order

创建Order类

搭建springcloud项目——简单明了_spring_32

package com.xiaoqi.springcloud.po;

public class Order {
private String id;
private Double price;
private String receiverName;
private String receiverAddress;
private String receiverPhone;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public Double getPrice() {
return price;
}

public void setPrice(Double price) {
this.price = price;
}

public String getReceiverName() {
return receiverName;
}

public void setReceiverName(String receiverName) {
this.receiverName = receiverName;
}

public String getReceiverAddress() {
return receiverAddress;
}

public void setReceiverAddress(String receiverAddress) {
this.receiverAddress = receiverAddress;
}

public String getReceiverPhone() {
return receiverPhone;
}

public void setReceiverPhone(String receiverPhone) {
this.receiverPhone = receiverPhone;
}

@Override
public String toString() {
return "Order{" +
"id='" + id + '\'' +
", price=" + price +
", receiverName='" + receiverName + '\'' +
", receiverAddress='" + receiverAddress + '\'' +
", receiverPhone='" + receiverPhone + '\'' +
'}';
}
}

创建Controller

搭建springcloud项目——简单明了_经验分享_33

package com.xiaoqi.springcloud.controller;

import com.xiaoqi.springcloud.po.Order;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {
/*
* 通过id查询订单
* */
@GetMapping("/order/{id}")
public String findOrderById(@PathVariable String id){
Order order = new Order();
order.setId("123");
order.setPrice(23.5);
order.setReceiverAddress("beijing");
order.setReceiverName("xiaoqi");
order.setReceiverPhone("15800000000");
return order.toString();
}
}

在eureka-user启动类中加入如下代码,这是RestTemplate的Spring实例,RestTemplate是Spring提供的用于访问Rest服务的客户端实例,它提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。

搭建springcloud项目——简单明了_经验分享_34

@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}

在eureka-user中编写UserController用户控制器类

搭建springcloud项目——简单明了_eureka_35

由于现在还没有创建数据库,所以不能够成功查询,现在我们创建数据库

搭建springcloud项目——简单明了_spring_36

数据库名称为microservice

搭建springcloud项目——简单明了_eureka_37

添加两条数据

搭建springcloud项目——简单明了_经验分享_38

在eureka-order 的pom.xml中添加如下

搭建springcloud项目——简单明了_经验分享_39

<!--MyBatis启动器-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<!--MySql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>

在eureka-order中新建UserMapper

搭建springcloud项目——简单明了_eureka_40

@Mapper
public interface UserMapper {
//查询所有用户
@Select("select * from tb_user")
List<User> getAllUsers();
//删除用户
@Delete("delete from tb_user where id=#{id}")
void delete(Integer id);
}

建立User类

搭建springcloud项目——简单明了_eureka_41

public class User {
private Integer id;
private String username;
private String address;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}

public String getUsername() {
return username;
}

public void setUsername(String username) {
this.username = username;
}

public String getAddress() {
return address;
}

public void setAddress(String address) {
this.address = address;
}

@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", address='" + address + '\'' +
'}';
}

UserServiceImpl类

搭建springcloud项目——简单明了_java_42

@Service
@Transactional
public class UserServiceImpl implements UserService {

//注入用户Mapper
@Autowired
private UserMapper userMapper;
//查询所有用户
public List<User> getAllUsers() {
return this.userMapper.getAllUsers();
}
//删除用户
public void deleteUser(Integer id) {
System.out.println("删除了id为"+id+"的用户");
this.userMapper.delete(id);
}

UserService接口

public interface UserService {
//查询所有
List<User> getAllUsers();
//删除数据
void deleteUser(Integer id);
}

UserController类

搭建springcloud项目——简单明了_spring_43

@RestController
@RequestMapping("/user")
public class UserController {
//注入用户Service
@Autowired
private UserService userService;
//查询所有用户
@RequestMapping("/userList")
public List<User> getAllUsers(){
List<User> list = this.userService.getAllUsers();
return list;
}
//删除用户
@RequestMapping("/delete/{id}")
public void delete(@PathVariable Integer id){
this.userService.deleteUser(id);
}

然后检查eureka-user的Controller

搭建springcloud项目——简单明了_eureka_44

然后按顺序分别启动eureka-server、eureka-order、eureka-user

然后访问

http://localhost:8000/findOrdersByUser/1

如图

搭建springcloud项目——简单明了_经验分享_45

这样就证明访问成功了

Ribbon

Ribbon是用来实现负载均衡的

首先我们在eureka-user中Application的@Bean下加注解@LoadBalanced

,加了这个注解后RestTemplate就具有了负载均衡能力。

搭建springcloud项目——简单明了_经验分享_46

然后将eureka-user中的UserController进行如下修改

搭建springcloud项目——简单明了_spring boot_47

我们将之前的“主机地址+端口号”变成了实例名称

在order中写一个工具类

搭建springcloud项目——简单明了_eureka_48

@Configuration
public class ServiceInfoUtil implements ApplicationListener<EmbeddedServletContainerInitializedEvent> {
/**
* 声明event对象,该对象用于获取运行服务器的本地端口
*/
private static EmbeddedServletContainerInitializedEvent event;

public void onApplicationEvent(
EmbeddedServletContainerInitializedEvent event){
ServiceInfoUtil.event = event;
}
/**
* 获取端口号
*/
public static int getPort(){
int port = event.getEmbeddedServletContainer().getPort();
return port;
}

然后在userList接口中写一个输出,这是用来输出端口号

搭建springcloud项目——简单明了_spring boot_49

然后将eureka-order先启动一次,再把端口号该为7901再启动一次

搭建springcloud项目——简单明了_经验分享_50

可以看到启动了两个order服务

然后我们访问http://localhost:8000/findOrdersByUser/1

搭建springcloud项目——简单明了_经验分享_51

我们多访问几次,然后看输出

搭建springcloud项目——简单明了_java_52

搭建springcloud项目——简单明了_spring_53

我们可以看到,这两个不同端口的order都访问到了,证明Ribbon实现了负载均衡机制。

eureka-user-hystrix

接下来我们写hystrix模块,简单了来说就是熔断器模块,因为在系统中例如c服务调用b服务,然后b服务调用a服务,假如a服务出现问题,那么会导致b服务出现问题,然后再导致c服务出现问题,最终整个系统全部瘫痪,为了解决这个问题就出现了熔断器。

1、新建eureka-user-hystrix模块,步骤和上面的其他模块一样,pom.xml中添加如下配置。搭建springcloud项目——简单明了_eureka_54

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<!--Hystrix依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

yml文件如下

搭建springcloud项目——简单明了_java_55

server:
port: 8030
eureka:
instance:
prefer-ip-address: true
client:
service-rul:
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: eureka-user-hystrix

新建启动类

搭建springcloud项目——简单明了_eureka_56

@SpringBootApplication
@EnableCircuitBreaker
@EnableEurekaClient
public class Application {

public static void main(String [] args){
SpringApplication.run(Application.class, args);
}

@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}

新建UserController,代码中的fallbackInfo方法就是在指定的服务出现问题不能访问的时候就会走这个方法,当指定的服务问题解决以后又会自动再访问指定的访问,这里是自动熔断与连接的。

搭建springcloud项目——简单明了_经验分享_57

@RestController
public class UserController {
@Autowired
private RestTemplate restTemplate;
/**
* 查找与用户相关的订单
*/
@GetMapping("/findOrdersByUser/{id}")
@HystrixCommand(fallbackMethod = "fallbackInfo")
public String findOrdersByUser(@PathVariable String id){
return this.restTemplate.getForObject("http://eureka-order/user/userList", String.class);
}
/**
* 返回信息方法
*/
public String fallbackInfo(@PathVariable String id){
return "服务不可用,请稍后再试!";
}
}

现在我们来依次启动项目,order启动两个,分别为7900和7901

启动后访问http://localhost:8761/ 如下图证明启动成功

搭建springcloud项目——简单明了_spring boot_58

然后访问http://localhost:8030/findOrdersByUser/1 如下图

搭建springcloud项目——简单明了_eureka_59

然后我们就多访问几次,发现访问正常,而且负载也正常

搭建springcloud项目——简单明了_经验分享_60

搭建springcloud项目——简单明了_经验分享_61

这个时候我们停掉7901的服务

然后我们再次刷新之前的路径,当负载到7901的接口的时候出现下图证明成功

搭建springcloud项目——简单明了_spring boot_62

然后我们再启动7901服务后,再次访问就不会出现上图情况,证明我们熔断器配置成功。

gateway-zuul

接下来我们创建zuul(网关)模块,网关可以用来执行认证、动态路由、安全和动态响应等功能,这里主要讲一下动态路由。

新建gateway-zuul,pom.xml配置如下搭建springcloud项目——简单明了_java_63

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-zuul</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>

yml配置如图

搭建springcloud项目——简单明了_spring boot_64

新建启动类

搭建springcloud项目——简单明了_eureka_65

@EnableZuulProxy
@SpringBootApplication
@EnableEurekaClient
public class Application {
public static void main(String [] args){
SpringApplication.run(Application.class, args);
}
}

然后我们依次启动注册中心(eureka-server)、服务提供者(eureka-order)、网关服务(gateway-zuul)

然后我们访问 http://localhost:7900/order/1

出现下图证明成功

搭建springcloud项目——简单明了_eureka_66

config-server

接下来我们创建配置模块,因为我们以后可能随着业务越来越大,我们会从单体系统升级为分布式系统,但是我们每一个模块都有一个配置文件,这样我们要修改一个模块的配置文件,就需要找到该模块的所有文件,一个一个修改。