Java SpringBoot整合SpringCloud

目录
  • 1. SpringCloud特点
  • 2. 分布式系统的三个指标CAP
  • 3. Eureka
  • 4. SpringCloud Demo
    • 4.1 registry
    • 4.2 api
    • 4.3 provider
    • 4.4 consumer
    • 4.5 POSTMAN一下

1. SpringCloud特点

SpringCloud专注于为典型的用例和扩展机制提供良好的开箱即用体验,以涵盖其他情况:

  • 分布式/版本化配置
  • 服务注册和发现 Eureka
  • 路由 Zuul
  • 服务到服务的呼叫
  • 负载均衡 Ribbon
  • 断路器 Hystrix
  • 分布式消息传递

2. 分布式系统的三个指标CAP

在介绍SpringCloud默认使用的注册中心前,先介绍分布式系统的三个指标,分别是:

  • Consistency:一致性,在分布式系统中,更新操作执行成功后所有的用户的读操作必须返回最新值;client写入,server同步至整个系统;
  • Availability:可用性,只要收到用户的请求,在一定的时间内服务器就必须给出回应,回应的结果可以是成功或是失败;
  • Partition tolerance:分区容错,即区间通信可能失败,在网络中断,消息丢失的情况下,仍对外提供服务;一般无法避免,可以认为CAP中的P总是成立

CAP定律说的是,在一个分布式计算机系统中,一致性C,可用性A,分区容错性P这三种保证无法同时得到满足,最多满足两个:

放弃P:

为了避免分区容错性问题的发生,一种做法是将所有与事务相关的数据都放在一台服务器上,虽然不能保证100%系统不会出错,但是不会碰到由分区带来的负面效果,这样的做法会严重影响系统的扩展性。

放弃A:

放弃可用性,一旦遇到分区容错故障,受到影响的服务器需要等待一定的时间,因此会导致在等待期间系统无法对外提供服务。

放弃C:

这儿说的放弃一致性,并不是完全放弃数据的一致性,而是放弃数据的强一致性,而保留数据的最终一致性。以网络购物为例,对只剩下一件库存的商品,如果同时接受到了两份订单,那么较晚的订单将被告知商品告罄。

文中部分CAP理论摘自: https://www.cnblogs.com/hxsyl/p/4381980.html

3. Eureka

基本介绍:

EurekaSpringCloud官方推荐用于服务注册和发现,一个基于REST的服务

SpringBoot实现了Netflix OSS的集成,使用Eureka的原因之一是因为其可以利用Spring Cloud Netflix的其他组件:智能路由(Zuul)、客户端负载均衡(Ribbon)等

基本组成:

Eureka由多个Instance(服务实例)组成,分为Eureka ServerEureka Client

其中Eureka Client又可细分为:Service Provider、Service Consumer

  • Eureka Server:服务端,提供服务的注册和发现;
  • Eureka Client:客户端
  1. Service Provider:服务提供方,将自身服务注册到Eureka,让消费方找到
  2. Service Consumer:服务消费方,从Eureka获取注册服务列表,从而消费服务

Eureka和Zookeeper:

1)由CAP理论的角度来看

ZookeeperZK保证CP,突出强一致性,但无法保证每次访问服务可用性,比如ZK会出现这样一种情况:当master节点因为网络故障与其他节点失去联系时,剩余节点会重新进行leader选举,在ZK选举leader期间整个ZK集群都是不可用的,这就导致了在选举期间注册服务瘫痪。在云部署的环境下,因网络问题使得ZK集群失去master节点是较大概率会发生的事儿,虽然服务最终会恢复,但是漫长的选举时间导致的注册长期不可用是难以容忍的。

EurekaEureka保证AP,Eureka在设计时就优先保证可用性。对于Eureka中的节点,每个节点都是平等的,几个节点挂掉也不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。但Eureka不保证强一致性,即查到的信息可能不是最新的。此外Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就会认为客户端和注册中心出现了网络故障,但会保证当前节点依然可用,不会像ZK导致整个注册服务瘫痪。

2)由节点分工的角度来看

Zookeeper:ZK集群中节点分为三类,承担不同的任务

  • Leader:事务请求唯一的调度者和处理者(除了查询请求)
  • Follower:处理非事务请求,参与Leader选举投票
  • Observer:处理非事务请求,但不参与Leader选举投票

Eureka:在Eureka集群中每个节点都是平等的,每个节点扮演相同的角色,它们通过相互注册的方式来感知对方的存在,当由注册消息时,它们会同步给集群内的其他节点

4. SpringCloud Demo

Demo整体结构(父子项目)

  • api:Bean、DTO、POJO等以及Service接口
  • controller:服务消费方,前端交互
  • provider:服务提供方,服务实现
  • registry:服务注册中心

4.1 registry

1)pom.xml

关键点在于导入eureka服务端依赖以及SpringCloud依赖

<dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-netflix-eureka-server -->
        <!-- eureka服务端 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR6</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

2)application.properties

进行Eureka服务端的相关配置

spring.application.name=SpringCloudDemoRegistry

# server端口,自己喜欢
server.port=8888

# Eureka Server服务url以及默认zone,结尾必须eureka
eureka.client.service-url.defaultZone= http://127.0.0.1:8888/eureka/

# eureka的自我保护机制,k8s环境下建议false
eureka.server.enable-self-preservation=false

# false表示自己端就是注册中心,我的功能就是维护服务实例,不需要从server获取注册的服务信息
eureka.client.fetch-registry=false

# false表示不将自己注册到Eureka Server
eureka.client.register-with-eureka=false

3)EurekaregistryApplication

使用@EnableEurekaServer激活相关配置,使registry模块作为注册中心Server

@EnableEurekaServer //声明为注册中心服务端
@SpringBootApplication
public class EurekaregistryApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaregistryApplication.class, args);
    }
}

4.2 api

1)entity

实体类以部门和用户信息为例,由于演示使用了Lombok省点代码,用于实现基本的CRUD

Department.class

@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class Department {
    private Long id;
    private Integer dId;
    private String dName;
    private Date updateTime;
}

UserInfo.class

@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class UserInfo {
    private Long id;
    private Integer uId;
    private Integer dId;
    private String uName;
    private String uPhone;
    @Email(message = "非法邮件格式") //Validator格式校验
    private String uEmail;
    private String uAddress;
    private Date updateTime;
    private Department department;
}

2)UserService

UserService为服务接口,声明需要提供和消费的方法,写了几个简单查询

public interface UserService {

    /**
     * 判断用户是否存在,0为不存在,返回值与uId相等则存在
     * @param uId
     * @return
     */
    Integer userExist(Integer uId);

    /**
     * 获取用户个人基本信息
     * @param uId
     * @return
     */
    UserInfo getUserInfo(Integer uId);

    /**
     * 获取用户个人详情信息
     * @param uId
     * @return
     */
    UserInfo getUserDetailsInfo(Integer uId);
}

4.3 provider

1)pom.xml

关键点是引入eureka客户端依赖openfeign依赖SpringCloud依赖

<dependencies>
     <!-- Springboot的依赖省略... -->
  <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

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

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR6</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
</dependencyManagement>

2)application.properties

配置EurekaMybatis以及DataSource数据源等信息

spring.application.name=SpringCloudDemoProvider

# Server端口
server.port=9999

# Eureka服务url
eureka.client.service-url.defaultZone= http://127.0.0.1:8888/eureka/
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true

# Mybatis
mybatis.mapper-locations= classpath:com.maziyao.provider.mapper/*.xml
mybatis.type-aliases-package= com.maziyao.common.entity

# DataSource数据源配置
spring.datasource.type=com.zaxxer.hikari.HikariDataSource

# DataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/boot-demo?serverTimezone=UTC
spring.datasource.username=root
spring.datasource.password=root

3)EurekaproviderApplication

provider启动类使用@EnableEurekaClient声明为EurekaClient客户端,作为ServiceProvider

@EnableEurekaClient
@SpringBootApplication
@EnableAspectJAutoProxy
@MapperScan("com.maziyao.provider.mapper")
@ComponentScan(basePackages = {
        "com.maziyao.provider.rest",
        "com.maziyao.provider.redis",
        "com.maziyao.provider.service",
        "com.maziyao.provider.config"
})
public class EurekaproviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaproviderApplication.class, args);
    }
}

4)service

UserServiceImpl作为UserService接口实现类,@Service用于标注 业务层 组件

自动注入mapper层的mapper接口并调用,mapper的SQL语句下面就略了,很简单

需要注意的是,对于 数据访问层 组件mapper,使用@Repository进行标注

@Service("userService")
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public Integer userExist(Integer uId) {
        return userMapper.userExist(uId);
    }

    @Override
    public UserInfo getUserInfo(Integer uId) {
        return userMapper.getUserInfo(uId);
    }

    @Override
    public UserInfo getUserDetailsInfo(Integer uId) {
        return userMapper.getUserDetailsInfo(uId);
    }
}

5)rest

重点是rest包下的UserServer要知道Eureka是一个基于REST的服务

使用@RestController标注并声明为userServer,这个是SpringBoot注解,用于标注 控制层 组件

@RestController("userServer")
public class UserServer {

    public static final Logger logger = LoggerFactory.getLogger(UserServer.class);

    @Autowired
    private UserService userService;

    @ResponseBody
    @RequestMapping(value = "/exist",method = RequestMethod.GET)
    public Integer existUserByUid(@RequestParam("uId")Integer uId){
        return userService.userExist(uId);
    }

    @ResponseBody
    @RequestMapping(value = "/userInfo",method = RequestMethod.GET)
    public UserInfo getUserInfo(@RequestParam("uId")Integer uId){
        return userService.getUserInfo(uId);
    }

    @ResponseBody
    @RequestMapping(value="/userDetailsInfo",method = RequestMethod.GET)
    public UserInfo getUserDetailsInfo(@RequestParam("uId")Integer uId){
        return userService.getUserDetailsInfo(uId);
    }
}

4.4 consumer

1)pom.xml

Controllerpom.xml中也需要导入EurekaClient的依赖,对于ProviderController都为Client

<dependencies>
     <!-- SpringBoot依赖省略... -->
  <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
            <version>2.2.5.RELEASE</version>
        </dependency>
</dependencies>

2)application.properties

application.properties中配置Eureka相关信息

spring.application.name=springCloudDemoController

# Server端口
server.port=8899

# 注册中心url
eureka.client.service-url.defaultZone= http://127.0.0.1:8888/eureka/
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true

3)EurekacontrollerApplication

Provider的启动类一致,声明启动类为Eureka的客户端

并使用@EnableFeignClients开启Feign,声明性的web服务客户端

@EnableEurekaClient
@EnableFeignClients
@SpringBootApplication
@EnableAspectJAutoProxy
@ComponentScan({
        "com.maziyao.controller.config",
        "com.maziyao.controller.controller",
        "com.maziyao.controller.rest"
})
public class EurekacontrollerApplication {

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

}

4)rest

controller作为前端交互层,即控制层,此处UserClient声明调用方法

使用@FeignClient声明服务提供方在application.properties中配置的spring.application.name

以及绑定服务提供方对应rest包下的UserServer类的@RestController("userServer")

@FeignClient(name = "springCloudDemoProvider",contextId = "userServer")
public interface UserClient {

    @ResponseBody
    @RequestMapping(value = "/exist",method = RequestMethod.GET)
    public Integer existUserByUid(@RequestParam("uId")Integer uId);

    @ResponseBody
    @RequestMapping(value = "/userInfo",method = RequestMethod.GET)
    public UserInfo getUserInfo(@RequestParam("uId")Integer uId);

    @ResponseBody
    @RequestMapping(value="/userDetailsInfo",method = RequestMethod.GET)
    public UserInfo getUserDetailsInfo(@RequestParam("uId")Integer uId);

}

5)UserController

控制层,使用@RestController标注,并注入UserClient进行调用

@RestController
public class UserController {

    private static final Logger logger = LoggerFactory.getLogger(UserController.class);

    @Autowired
    private UserClient userClient;

    @ResponseBody
    @RequestMapping(value = "/exist",method = RequestMethod.GET)
    public Integer existUserByUid(@RequestParam("uId") Integer uId){
        return userClient.existUserByUid(uId);
    }

    @ResponseBody
    @RequestMapping(value = "/userInfo",method = RequestMethod.GET)
    public UserInfo getUserInfoByUid(@RequestParam("uId")Integer uId){
        return userClient.getUserInfo(uId);
    }

    @ResponseBody
    @RequestMapping(value = "/userDetailsInfo",method = RequestMethod.GET)
    public UserInfo getUserDetailsInfoByUid(@RequestParam("uId")Integer uId){
        return userClient.getUserDetailsInfo(uId);
    }

}

4.5 POSTMAN一下

注意:最后记得mvn install,需要先将registry运行起来,再分别运行providercontroller

启动registry:

启动provider:

启动consumer:

result:

到此这篇关于Java-SpringBoot整合SpringCloud的文章就介绍到这了,更多相关SpringBoot整合SpringCloud内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 图解JAVA中Spring Aop作用

    假如没有aop,在做日志处理的时候,我们会在每个方法中添加日志处理,比如 但大多数的日子处理代码是相同的,为了实现代码复用,我们可能把日志处理抽离成一个新的方法.但是这样我们仍然必须手动插入这些方法. 但这样两个方法就是强耦合的,假如此时我们不需要这个功能了,或者想换成其他功能,那么就必须一个个修改. 通过动态代理,可以在指定位置执行对应流程.这样就可以将一些横向的功能抽离出来形成一个独立的模块,然后在指定位置 插入这些功能.这样的思想,被称为面向切面编程,亦即AOP. 为了在指定位置执行这些横

  • 一篇文章教你将JAVA的RabbitMQz与SpringBoot整合

    目录 一.fanout:发布订阅型 二.direct:直连型 三.topic:通配符模式 四.消费者端接收消息 总结 本文主要聊SpringBoot整合RabbitMQ,主要分为生产者和消费者两个工程,目录结构如下: 先简单说一下RabbitMQ的一些核心概念: 1.虚拟主机vhost:vhost是物理隔离的,你可以将vhost看作是一个个小型的RabbitMQ 2.交换机exchange:生产者发送的消息不是直接到达队列的,而是交换机,然后交换机再根据路由key,路由到指定的队列,可以理解为一

  • java Spring AOP详解及简单实例

    一.什么是AOP AOP(Aspect Oriented Programming)面向切面编程不同于OOP(Object Oriented Programming)面向对象编程,AOP是将程序的运行看成一个流程切面,其中可以在切面中的点嵌入程序. 举个例子,有一个People类,也有一个Servant仆人类,在People吃饭之前,Servant会准备饭,在People吃完饭之后,Servant会进行打扫,这就是典型的面向切面编程. 其流程图为: 二.Spring AOP实现: 1.People

  • Java aop面向切面编程(aspectJweaver)案例详解

    面向切面编程的目的就是:在不改变别人的代码的前提下,在别人代码方法执行前或后,执行(切入自己的逻辑) 准备:idea+maven+aspectjweaver-1.8.9.jar 结构图: pom.xml内容 <dependencies> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.8.9&

  • Java JDK动态代理(AOP)的实现原理与使用详析

    本文主要给大家介绍了关于Java JDK动态代理(AOP)实现原理与使用的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍: 一.什么是代理? 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问.代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理. 代理模式UML图: 简单结构示意图: 为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别.通过代理类这中间一层,能有效控制对委托类对

  • Java AOP知识详细介绍

    Java AOP AOP知识整理 AOP(Aspect-Oriented Programming):面向切面的编程.OOP(Object-Oriented Programming)面向对象的编程.对于OOP我们已经再熟悉不过了,对于AOP,可能我们会觉得是一种新特性,其实AOP是对OOP的一种补充,OOP面向的是纵向编程,继承.封装.多态是其三大特性,而AOP是面向横向的编程. 面向切面编程(AOP)通过提供另外一种思考程序结构的途经来弥补面向对象编程(OOP)的不足.在OOP中模块化的关键单元

  • Java JDK动态代理(AOP)用法及实现原理详解

    Java-JDK动态代理(AOP)使用及实现原理分析 第一章:代理的介绍 介绍:我们需要掌握的程度 动态代理(理解) 基于反射机制 掌握的程度: 1.什么是动态代理? 2.动态代理能够做什么? 后面我们在用Spirng和Mybatis的时候,要理解怎么使用的. 1.什么是代理? 代理,在我们日常生活之中就有体现,代购,中介,换ip,商家等等. 比如有一家美国的大学,可以对全世界招生.留学中介(代理 ) 留学中介(代理):帮助这家美国的学校招生,中介是学校的代理中介是代替学校完成招生功能 代理特点

  • Java Spring AOP之PointCut案例详解

    目录 一.PointCut接口 二.ClassFilter接口 三.MethodMatcher接口 总结 一.PointCut接口 /* * Copyright 2002-2012 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with

  • Java SpringBoot启动指定profile的8种方式详解

    目录 配置文件中设置 命令行设置 IDEA中设置 1.program arguments程序参数 2.VM options虚拟机参数 3.Active profiles 参数 遇到的问题 总结 配置文件中设置 通常在公司级别的项目中,我们可能会写多个application- dev/prod.yml ,然后我们通常会在application.yml配置文件中写入 spring: profiles: active: dev 这里会指定激活的profile是application- dev.yml

  • Java SpringBoot在RequestBody中高效的使用枚举参数原理案例详解

    在优雅的使用枚举参数(原理篇)中我们聊过,Spring对于不同的参数形式,会采用不同的处理类处理参数,这种形式,有些类似于策略模式.将针对不同参数形式的处理逻辑,拆分到不同处理类中,减少耦合和各种if-else逻辑.本文就来扒一扒,RequestBody参数中使用枚举参数的原理. 找入口 对 Spring 有一定基础的同学一定知道,请求入口是DispatcherServlet,所有的请求最终都会落到doDispatch方法中的ha.handle(processedRequest, respons

  • Java SpringBoot实现AOP

    目录 1.AOP基本总结 2.常用方法 3.增强类型 4.示例说明 5.结果展示 1.AOP基本总结 连接点(JoinPoint): 连接点是程序运行的某个阶段点,如方法调用.异常抛出等 切入点(Pointcut): 切入点是JoinPoint的集合 是程序中需要注入Advice的位置的集合,即Advice在什么条件下才能被触发 增强(Advisor): 增强是切入点Pointcut和Advice的综合体,即在连接点JoinPoint上执行的行为 通过JDK/CGLIB代理模式实现AOP 切面(

  • Java动态代理和AOP应用示例

    本文实例讲述了Java动态代理和AOP应用.分享给大家供大家参考,具体如下: 一 点睛 动态代理在AOP(Aspect Orient Program,即面向切面编程)里被称为AOP代理,AOP代理可代替目标对象,AOP代理包含了目标对象的全部方法.但AOP代理中的方法与目标对象的方法存在差异:AOP代理里的方法可以在执行目标方法之前.之后插入一些通用处理. 二 代码 Dog.java public interface Dog { // info方法声明 void info(); // run方法

  • Java之Spring AOP 实现用户权限验证

    每个项目都会有权限管理系统 无论你是一个简单的企业站,还是一个复杂到爆的平台级项目,都会涉及到用户登录.权限管理这些必不可少的业务逻辑.有人说,企业站需要什么权限管理阿?那行吧,你那可能叫静态页面,就算这样,但你肯定也会有后台管理及登录功能. 每个项目中都会有这些几乎一样的业务逻辑,我们能不能把他们做成通用的系统呢? AOP 实现用户权限验证 AOP 在实际项目中运用的场景主要有权限管理(Authority Management).事务管理(Transaction Management).安全管

随机推荐