• 黑马程序员ssm总结[大全版本,有对应pdf+源码](spring->springmvc-->springboot-->maven高级->cloud微服务)


    前言

    pdf+源码(大全),对应视频:https://www.bilibili.com/video/BV1VJ411X7xXp=20&vd_source=0e4ada3d15f80172cb72c52e0fcabd05
    自我感觉黑马课程比官方文档好,新手友好,强推!
    看文档必看视频效率高,理解更透,一遍看不懂,反复看!
    有问题,欢迎与我讨论: qq:1657019234
    黑马程序员ssm资料(从spring–>springmvc–>springboot–>maven高级->cloud微服务)

    文章目录

    耦合性可以是低耦合性(或称为松散耦合),也可以是高耦合性(或称为紧密耦合)。以下列出一些耦合性的分类,从高到低依序排列:

    • 内容耦合(content coupling,耦合度最高):也称为病态耦合(pathological coupling)当一个模块直接使用另一个模块的内部数据,或通过非正常入口而转入另一个模块内部。
    • 共用耦合/公共耦合(common coupling):也称为全局耦合(global coupling.)指通过一个公共数据环境相互作用的那些模块间的耦合。公共耦合的复杂程序随耦合模块的个数增加而增加。
    • 外部耦合(external coupling):发生在二个模块共用一个外加的数据格式、通信协议或是设备界面,基本上和模块和外部工具及设备的沟通有关。
    • 控制耦合(control coupling):指一个模块调用另一个模块时,传递的是控制变量(如开关、标志等),被调模块通过该控制变量的值有选择地执行块内某一功能;
    • 特征耦合/标记耦合(stamp coupling):也称为数据结构耦合,是指几个模块共享一个复杂的数据结构,如高级语言中的数组名、记录名、文件名等这些名字即标记,其实传递的是这个数据结构的地址;
    • 数据耦合/数据耦合(data coupling):是指模块借由传入值共享数据,每一个数据都是最基本的数据,而且只分享这些数据(例如传递一个整数给计算平方根的函数)。
    • 消息耦合(message coupling,是无耦合之外,耦合度最低的耦合):可以借由以下二个方式达成:状态的去中心化(例如在对象中),组件间利用传入值或消息传递 (计算机科学)来通信。
    • 无耦合:模块完全不和其他模块交换信息。

    降低耦合度的方法

    1、少使用类的继承,多用接口隐藏实现的细节。 java面向对象编程引入接口除了支持多态外, 隐藏实现细节也是其中一个目的。
      2、模块的功能化分尽可能的单一,道理也很简单,功能单一的模块供其它模块调用的机会就少。(其实这是高内聚的一种说法,高内聚低耦合一般同时出现,为了限制篇幅,我们将在以后的版期中讨论)。
      3、遵循一个定义只在一个地方出现。
      4、少使用全局变量。
      5、类属性和方法的声明少用public,多用private关键字,
      6、多用设计模式,比如采用MVC的设计模式就可以降低界面与业务逻辑的耦合度。
      7、尽量不用“硬编码”的方式写程序,同时也尽量避免直接用SQL语句操作数据库。
      8、最后当然就是避免直接操作或调用其它模块或类(内容耦合);如果模块间必须存在耦合,原则上尽量使用数据耦合,少用控制耦合,限制公共耦合的范围,避免使用内容耦合。

    紧密耦合的系统在开发阶段有以下的缺点:

    1. 一个模块的修改会产生涟漪效应,其他模块也需随之修改。
    2. 由于模块之间的相依性,模块的组合会需要更多的精力及时间。
    3. 由于一个模块有许多的相依模块,模块的可复用性低。 [2]

    spring核心容器

    本章是core&bean的原理讲解

    5min复习视频:核心容器总结

    在这里插入图片描述

    Spring就提出了一个解决方案:

    • 使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象
    • 即:使用消息耦合(耦合度最低的耦合),去中心化,
    1. IOC(Inversion of Control)控制反转

    (1)什么是控制反转呢?

    • 使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部,此思想称为控制反转。

    2.DI的注入方法

    • setter注入(比构造器注入更常用,推荐,我们一般只用构造器注入)(又分为

      • 引用类型注入)

      • 简单类型(int…String)注入)

      • 集合类型注入

        
            
                xxx
                
            
        
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
    • 构造器注入

    IoC基础上,需要绑定两个Bean之间的依赖关系,需要DI进行绑定,的形式

    3.bean的生命周期scope: 当然,还有很多别的scope生命周期属性

    在这里插入图片描述


    spring注解开发(正片开始)

    spring3.0升级了

    纯注释开发,使用一个添加了 @configuration的config配置类来进行配置

    spring注解开发总结

    • 普通配置类注入:在这里插入图片描述

    • 第三方配置类注入

    在这里插入图片描述

    在这里插入图片描述


    spring整合mybatis

    看看就行

    可以看到,在老师给的项目中,shiro( shiro是apache的是一个分布式权限管理的框架,实现 用户认证、用户授权)

    和 cors(用于允许跨域请求)

    出于安全原因,浏览器禁止AJAX调用当前来源之外的资源,跨域资源共享(CORS)是由大多数浏览器实施的W3C规范,使您可以灵活地指定对哪种跨域请求进行授权。
    从Spring Framework 4.2开始,开箱即用地支持CORS。 CORS请求(包括带有OPTIONS方法的预检请求)将自动分派到各种已注册的HandlerMappings。

    二者采取了类似的配置类形式

    spring整合Junit

    看看就行

    在这里插入图片描述


    AOP:用于不改变原代码基础上 进行功能增强

    • 概念:AOP(Aspect Oriented Programming)面向切面编程,一种编程范式
    • 作用:在不惊动原始设计的基础上为方法进行功能增强
    • 核心概念
      • 代理(Proxy):SpringAOP的核心本质是采用代理模式实现的
      • 连接点(JoinPoint):在SpringAOP中,理解为任意方法的执行
      • 切入点(Pointcut):匹配连接点的式子,也是具有共性功能的方法描述
      • 通知(Advice):若干个方法的共性功能,在切入点处执行,最终体现为一个方法
      • 切面(Aspect):描述通知与切入点的对应关系
      • 目标对象(Target):被代理的原始对象成为目标对象

    切入点表达式:

    • 切入点表达式标准格式:动作关键字(访问修饰符 返回值 包名.类/接口名.方法名(参数)异常名)

      execution(* com.itheima.service.*Service.*(..))
      
      • 1
    • 切入点表达式描述通配符:

      • 作用:用于快速描述,范围描述
      • *:匹配任意符号(常用)
      • .. :匹配多个连续的任意符号(常用)
      • +:匹配子类类型
    • 切入点表达式书写技巧

      1.按标准规范开发
      2.查询操作的返回值建议使用*匹配
      3.减少使用…的形式描述包
      4.对接口进行描述,使用*表示模块名,例如UserService的匹配描述为*Service
      5.方法名书写保留动词,例如get,使用*表示名词,例如getById匹配描述为getBy*
      6.参数根据实际情况灵活调整


    Spring事务

    • 保障一系列的数据库操作同成功同失败
    • Spring事务作用:在数据层或**业务层**保障一系列的数据库操作同成功同失败
    • Spring为了管理事务,提供了一个平台事务管理器PlatformTransactionManager:

    在这里插入图片描述

    进行提交与回滚,事务(转账操作中:A钱-,B钱+)作为一个整体,一旦部分执行不成功,能够整个回滚,从而确保若:A-成功,B+失败后,A,B都将回滚,恢复原状态

    在这里插入图片描述

    在这里插入图片描述

    (springboot中,连SpringMvcConfig都没了,使用,@EnableWebMvc也不会用了)

    REST风格(只是一种风格,不是一种规范,可以不遵守,但由于采用的人多,已经接近于一种规范):

    在这里插入图片描述

    Restful风格:基于Rest风格,进一步简化:

    @ResponseBody

    @RestController

    @RequestMapping

    在这里插入图片描述

    PostMan请求管理规范:

    在这里插入图片描述

    使用Restful风格进行开发的一个示例:

    在这里插入图片描述

    如果直接访问前端界面:localhost/pages/books.html,报错:

    在这里插入图片描述

    浏览器:

    因:浏览器访问使用get方法,由spring处理,spring认为你没有这一接口.确实,它本来也不是接口,而是一个页面.

    法:spring放行,让tomcat处理;即:实现一个过滤器(filter)静态页面,tomcat直接处理,动态请求springMVC处理

    拦截器

    在这里插入图片描述

    拦截器(Intercepter)是一种动态拦截方法调用的机制,在springMVC中动态拦截 控制器 方法的执行

    • 在指定方法的前后执行预先设定的代码
    • 阻止原始方法的执行

    拦截器与过滤器的区别:

    • filter属于servlet技术,intercepter属于SpringMVC技术
    • filter对所有访问进行增强,intercepter仅对SpringMVC的访问进行增强

    Maven分模块开发:

    idea的maven相关功能只能确保书写的时候不报错,不能保证运行的时候不报错

    通过install,实现本地安装

    pom项目默认的打包方式:jar

    pom项目web项目的打包方式:war

    pom项目聚合项目的打包方式:pom

    • maven冲突:

    在这里插入图片描述

    发生冲突时,maven会有一些规则来选用依赖

    依赖冲突可能会导致某个依赖使用了你不想使用的版本(这个版本可能会导致运行错误)

    • 可选依赖和排除依赖

      
      true
      
      • 1
      • 2
      
      
          
              com.itheima
              maven_03_pojo
          
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • maven多环境开发:(profile)

    在这里插入图片描述

    pro,dev,test多环境不同,如何配置多环境开发,以供选用

    • 使用聚合统一管理项目

      步骤1:创建一个空的maven项目

      步骤2:将项目的打包方式改为pom

      步骤3:pom.xml添加所要管理的项目

      步骤4:使用聚合统一管理项目

      
      
          4.0.0
      
          com.itheima
          maven_01_parent
          1.0-RELEASE
          pom
          
          
          
              ../maven_02_ssm
              ../maven_03_pojo
              ../maven_04_dao
          
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
    • 继承:解决重复配置问题

      com.itheima maven_01_parent 1.0-RELEASE ../maven_01_parent/pom.xml

    标签不真正引入jar包,而是配置可供子项目选择的jar包依赖

    子项目要想使用它所提供的这些jar包,需要自己添加依赖,并且不需要指定

    • 属性:即在pom.xml中配置属性变量,更改一处时,其他地方跟着更改

      定义:

      
      
          5.2.10.RELEASE
          4.12
          1.3.0
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6

      使用:

      
          org.springframework
          spring-jdbc
          ${spring.version}
      
      
      • 1
      • 2
      • 3
      • 4
      • 5

      文件加载 属性:配置文件(如jdbc.properties文件)中的属性,也让Maven进行管理

      需要设置maven过滤文件范围

      详见 maven高级.md

    • 私服

    使用nexus能建立私服仓库(小团队开发):nexus server端建立私服仓库–>本地maven setting.xml完成私服地址配置(至此,能访问私服了)–>项目pom.xml,添加 配置当前工程保存(部署)在私服中的具体位置–>maven deploy指令部署

    (下载不需要部署)


    springboot

    (前期都是基础,了解原理;springboot开始进入实用)

    一个经典Controller处理前端请求:

    @RestController
    @RequestMapping("/books")
    public class BookController {
    
        @GetMapping("/{id}")
        public String getById(@PathVariable Integer id){
            System.out.println("id ==> "+id);
            return "hello , spring boot!";
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    SpringBoot 程序如何修改呢?SpringBoot 提供了多种属性配置方式,加载顺序由上往下,因而如下三文件,最终:server:port:82

    今后统一使用application.yml

    • application.properties

      server.port=80
      
      • 1
    • application.yml

      server:
      	port: 81
      
      • 1
      • 2
    • application.yaml

      server:
      	port: 82
      
      • 1
      • 2

    注意:SpringBoot 程序的配置文件名必须是 application ,只是后缀名不同而已。


    • mybatis

    mybatis-plus真的能省很多力,但老师已经用了mybatis了,那算了!

    mybatis也有了自动代码生成器(毕竟国外uu们不使用mp(mybatis-plus),用不到这么好的代码生成器[笑]),老师就用了,参照:

    MyBatis代码自动生成器Mybatis-Generator使用教程

    核心:

    1.mybatis-generator.xml文件(文章中为mybatis-generator-cfg.xml,老师项目中为:mybatis-generator.xml)

    2.pom里面添加mybatis-generator的plugin配置。加载plugins

    3.添加运行配置、运行文件(对了记得吧application.properties后缀改为yml

    3是为了使用maven运行maven插件 mybatis-generator:generate -e指令

    注意:不需要担心 自写mapper(xml文件)代码被覆盖, 高于mybatis1.3.7的版本都不会覆盖 ,参见自写mapper(xml文件)代码被覆盖

    必须尽快弄好,或者想别的方法让单老师先开始!

    1. 新建springboot+mybatis项目(pom)(此时pom插件已经配好)
    2. 新建bean,entity,dao–>mapper自动生成–>controller(老师为了实现登录,使用了一些别的插件)
    3. 不需要配置跨域请求(来自不同端口的请求)(没有使用vue,vue是动态应用,而我们目前页面是static!请求来自同一端口!)
    4. 过程中,application.yml文件配置(项目配置,mysql配置,mybatis的数据源),mybatis-generator文件配置
    5. 不断添加插件,不断添加pom.xml

    在这里插入图片描述

    (都在mybatis-generator.xml中配置完成,且生成连带实体类!!!)


    Unknown system variable ‘query_cache_size‘ 的解决方法 方法二亲测有效!

    当前,需要解决映射不成功的问题(mybatis理解不深!),以箭头为 映射成功的标志

    1. 了解mybatis映射机制,正常来说,不需要mybatis-generator.xml也能生成箭头(视箭头为映射成功的标志)

      尝试,更改mybatis-generator.xml的dao目录(覆盖也没关系!)

      依旧没问题

      映射机制:

      1.引入mybatis依赖(pom.xml)

      2.property.yml文件,配置mybatis映射关系(如果)

    2. 使用mybatis-generator.xml生成的都有箭头

      必然不是spring配置错误,而是mybatis理解不深刻!

      尝试:删除某一文件,重配!

      依旧没问题

    批量注入过程中,发现@Repository改为使用@Mapper注入成功了!

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xBg2o0NB-1656345257363)(SSM(含springboot)]+Maven高级+Mybatis.assets/image-20220626155525255.png)

    o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task.

    java.lang.NoClassDefFoundError: com/alibaba/fastjson/util/IdentityHashMap

    Maven中的scope总结

    1. compile
      不声明scope元素的情况下的默认值;compile表示被依赖包需要参与当前项目的编译,包括后续的测试,运行周期也参与其中,是一个比较强的依赖;打包的时候通常需要包含进去。

    2. runtime
      runtimecompile比较相似,区别在于runtime 跳过了编译阶段,打包的时候通常需要包含进去。

    3. import
      import 只能在pom文件的中使用,从而引入其他的pom文件中引入依赖,如:在Spring boot 项目的POM文件中,我们可以通过在POM文件中继承 Spring-boot-starter-parent来引用Srping boot默认依赖的jar包

    因而,也难怪,之前依赖使用import出现了不生效的情况!

    在这里插入图片描述


    分析:

    当前版本:较为合理,pom中的依赖是,结合:老师原项目+nacos-discover示例项目得到的(虽说去除了哥的那几个依赖,这是我最担心的!如果出现相关报错,将删除哥的文件)

    • fastjson找不到:

      依赖冲突:

      当前fastjson版本无问题!2.1依然足矣!

      搜:

      1.External Libraries中并未发现相关依赖的Jar包–>有,非

    • 必然是某些配置错误,因此,进行了配置文件置零操作,与老师当初保持一致(现下所处阶段:不如张俊杰当初,但他引入了大量不靠谱依赖,我这靠谱)

      • spring-boot-starter-web 版本 不一致,有风险!(低于)

    nacos配置中心(cloud-alibaba)

    配置管理的必要性:

    同一份程序在不同的环境(开发,测试,生产)、不同的集群(如不同的数据中心)经常需要有不同的

    配置,所以需要有完善的环境、集群配置管理

    在微服务架构中,当系统从一个单体应用,被拆分成分布式系统上一个个服务节点后,配置文件也必须跟着迁移

    (分割),这样配置就分散了,不仅如此,分散中还包含着冗余,如下图:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lp7d1a0R-1656345257365)(SSM(含springboot)]+Maven高级+Mybatis.assets/image-20220627173947910.png)

    配置中心的服务流程如下:

    1、用户在配置中心更新配置信息。

    2、服务A和服务B及时得到配置更新通知,从配置中心获取配置。

    总得来说,配置中心就是一种统一管理各种应用配置的基础服务组件。

    在系统架构中,配置中心是整个微服务基础架构体系中的一个组件,如下图,它的功能看上去并不起眼,无非就是

    配置的管理和存取,但它是整个微服务架构中不可或缺的一环

    总而言之,在传统巨型单体应用纷纷转向细粒度微服务架构的历史进程中,配置中心是微服务化不可缺少的一个系

    统组件,在这种背景下中心化的配置服务即配置中心应运而生

    通过配置中心,我们实现了:

    • 合格的配置中心需要满足如下特性:
    • 配置项容易读取和修改
    • 分布式环境下应用配置的可管理性,即提供远程管理配置的能力
    • 支持对配置的修改的检视以把控风险
    • 可以查看配置修改的历史记录
    • 不同部署环境下应用配置的隔离性

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4f1Y4G9C-1656345257366)(SSM(含springboot)]+Maven高级+Mybatis.assets/image-20220627173914565.png)

    问:nacos配置中心的配置是动态的,我们的微服务已经跑起来后,是如何派上用场的懂了,只是集中管理,但是需要:重新跑!

    示例服务中,配置只是进行打印,如何 将配置派上用场

    一般来说,spring boot的配置将在application.yml(也可以是application.properties)文件中编写,

    由于使用外部 配置中心,必须将原先的application.yml重命名为bootstrap.yml,bootstrap.yml如下所示:

    spring.cloud.nacos.confifig.server-addr 指定了Nacos Server的网络地址和端口号

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uMr6Bfog-1656345257367)(SSM(含springboot)]+Maven高级+Mybatis.assets/image-20220627174121228.png)

    如此,外部(nacos)配置中心派上了用场

    通过自定义扩展的 Data Id 配置,既可以解决多个应用间配置共享的问题,又可以支持一个应用有多个配置文件

    结论:实现简单,后期可以整,暂时没必要!!!


    nacos服务发现

    笔记摘自:黑马程序员 nacos-服务发现.pdf

    负载均衡,引入 服务发现的目的

    先导: Spring Cloud服务协作流程:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E4rTyo5f-1656345257368)(SSM(含springboot)]+Maven高级+Mybatis.assets/image-20220627183219988.png)

    (1)在微服务启动时,会向服务发现中心上报自身实例信息,这里ServiceB 包含多个实例。

    每个实例包括:

    IP地址、端口号信息。

    北京市昌平区建材城西路金燕龙办公楼一层 电话:400-618-9090(2)微服务会定期从Nacos Server(服务发现中心)获取服务实例列表。

    (3)当ServiceA调用ServiceB时,ribbon组件从本地服务实例列表中查找ServiceB的实例,如获取了多个实例如

    Instance1、Instance2。这时ribbon会通过用户所配置的负载均衡策略从中选择一个实例。

    (4)最终,Feign组件会通过ribbon选取的实例发送http请求。

    采用Feign+Ribbon的整合方式,是由Feign完成远程调用的整个流程。而Feign集成了Ribbon,Feign使用Ribbon

    完成调用实例的负载均衡。

    考察核心:光凭zuul网关配置,能否实现负载均衡(而非在 service微服务互相调用过程中,通过feign实现!)

    (负载均衡的两个环节:1.通过feign(调用ribbon组件)微服务直接互相调用(客户端负载均衡,微服务是nacos客户端 nacos server是服务端) 2.通过zuul 网关配置,端口转发(服务端负载均衡,通过nginx实现的一样是服务端负载均衡;zuul和nginx往往是一起使用的!) )

    ribbon根据负载均衡策略负责选择示例,feign会通过ribbon来选择实例进而发送请求(feign集成来ribbon)

    (本文档,似乎一直在集中阐述 客户端负载均衡!)


    没有nacos服务注册中心时,微服务调用

    在微服务架构中,如果没有nacos服务注册中心,如何进行微服务之间互相调用(通信)

    Service B暴露接口供Service A调用:

    @SpringBootApplication 
    @RestController 
    public class SpringRestProviderBootstrap { 
        public static void main(String[] args) { 
            SpringApplication.run(SpringRestProviderBootstrap.class, args); 
        }
        
    @GetMapping(value = "/service") //暴露服务 
    public String service(){ 
        return "provider invoke"; 
    } 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    配置文件:

    server.port = 56010
    
    • 1

    Service A去调用Service B

    @SpringBootApplication 
    @RestController 
    public class SpringRestConsumerBootstrap 
    { public static void main(String[] args) {
        SpringApplication.run(SpringRestConsumerBootstrap.class, args); 
    }
     
    @Value("${provider.address}") 
    private String providerAddress; 
     
    @GetMapping(value = "/service") 
    public String service(){ 
        RestTemplate restTemplate = new RestTemplate(); //调用服务 
        String providerResult = restTemplate.getForObject("http://" + providerAddress + 				   "/service",String.class); return "consumer invoke | " + providerResult; 
    } 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    RestTemplate工具类,spring提供的一个HTTP请求工具

    在服务的调用过程中,使用到了一个工具,叫做 RestTemplate,RestTemplate 是由 Spring 提供的一个 HTTP 请求工具。在上文的案例中,开发者也可以不使用 RestTemplate ,使用 Java 自带的 HttpUrlConnection 或者经典的网络访问框架 HttpClient 也可以完成上文的案例,只是在 Spring 项目中,使用 RestTemplate 显然更方便一些。在传统的项目架构中,因为不涉及到服务之间的调用,大家对 RestTemplate 的使用可能比较少

    总结:

    关键: application.yml中配置provider.address属性,拼凑出地址后,使用restTemplate.getForObject方法进行调用!

    但是,微服务可能是部署在云环境的,服务实例的网络位置或许是动态分配的。另外,每一个服务一般会有多个实

    例来做负载均衡,由于宕机或升级,服务实例网络地址会经常动态改变。再者,每一个服务也可能应对临时访问压

    力增加新的服务节点。正如下图所示:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pK72PVE8-1656345257369)(SSM(含springboot)]+Maven高级+Mybatis.assets/image-20220627192149824.png)


    nacos服务注册的实现

    (服务发现(让服务之间互相感知)与管理问题)

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9PJda5TR-1656345257369)(SSM(含springboot)]+Maven高级+Mybatis.assets/image-20220627192235974.png)

    (1)在每个服务启动时会向服务发现中心上报自己的网络位置。这样,在服务发现中心内部会形成一个服务注册

    服务注册表是服务发现的核心部分,是包含所有服务实例的网络地址的数据库。

    (2)服务发现客户端会定期从服务发现中心同步服务注册表 ,并缓存在客户端。

    (3)当需要对某服务进行请求时,服务实例通过该注册表,定位目标服务网络地址。若目标服务存在多个网络地

    址,则使用负载均衡算法从多个服务实例中选择出一个,然后发出请求。

    总结一下,在微服务环境中,由于服务运行实例的网络地址是不断动态变化的,服务实例数量的动态变化 ,因此无

    法使用固定的配置文件来记录服务提供方的网络地址,必须使用动态的服务发现机制用于实现微服务间的相互感

    。各服务实例会上报自己的网络地址,这样服务中心就形成了一个完整的服务注册表,各服务实例会通过服务发

    现中心来获取访问目标服务的网络地址,从而实现服务发现的机制。

    服务注册的实现极其简单:

    (下面这个例子是从 海马程序员-服务发现中,摘出来的部分代码,像@EnableFeignClients如果仅为实现服务注册而不实现feign调用其他微服务,那它是多余的)

    (为了更深刻理解,看源文档 nacos-服务发现.pdf (文档视频中有,我的博客中也有) or 黑马nacos-服务发现 视频)

    1. application.yml配置

      server: 
      	port: 56020 #启动端口 命令行注入 
      	
      spring: 
      	application: 
      		name: quickstart‐consumer 
      	cloud: 
      		nacos: 
      			discovery: 
      				server‐addr: 127.0.0.1:8848
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

      2.Provider(生产者)远程代理定义

      @SpringBootApplication
      @EnableDiscoveryClient
      @EnableFeignClients #开启FeignClient,如果只是实现服务注册,不使用feign调用其他微服务的话,就没必要了
      public class NacosConsumerApp {
      public static void main(String[] args) {
      SpringApplication.run(NacosConsumerApp.class, args);
      }
      }

    Note: @EnableDiscoveryClient 在spring cloud项目中表明此项目是一个注册发现客户端,这里注册服务发

    现使用的是Nacos

    Note: @EnableFeignClients 开启FeignClient

    可以说,实现服务注册,只需要: @EnableDiscoveryClient 就行!!!


    有了nacos服务注册中心时,利用feign(ribbon)进行微服务调用

    spring(boot)使用feign需在pom.xml中加入依赖:

     
    	org.springframework.cloud 
    	spring‐cloud‐starter‐openfeign 
    
    
    • 1
    • 2
    • 3
    • 4

    参考前面 没有nacos服务注册中心时,微服务调用 的ServiceA调用ServiceB的例子,我们有了 在服务注册后 使用Feign实现这个过程,代码如下:

    Service B暴露"/service"服务端点,如下:

    @SpringBootApplication 
    @RestController
    public class SpringRestProviderBootstrap { 
        public static void main(String[] args) 
        { 
            SpringApplication.run(SpringRestProviderBootstrap.class, args); 
        }
    @GetMapping(value = "/service") 
    
    //暴露服务 
    public String service(){ return "provider invoke"; } }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Service A中,通过Feign调用Service B方式如下:

    (1)声明Feign客户端

    @FeignClient(value = "serviceB") 
    public interface ServiceBAgent { 
    
        /** 
        * 根据用户名查询账号信息 
        * @param username 用户名 
        * @return 账号信息 
        */ 
    //Feign英文表意为“假装,伪装,变形”,此处正是将HTTP报文请求方式 伪装为简单的java接口(内部,未通过TTTP)调用方式
    @GetMapping(value = "/service") 
    public String service(); }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Feign是Netflflix开发的声明式、模板化的HTTP客户端, Feign可以帮助我们更快捷、优雅地调用HTTP API。Feign

    的英文表意为“假装,伪装,变形”, 可以理解为将HTTP报文请求方式伪装为简单的java接口调用方式。

    (2)业务调用

    @Autowired 
    private ServiceBAgent serviceBAgent.; 
    //....略 
    serviceBAgent.service();
    //....略
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 在 声明Feign客户端 之后,Feign会根据**@FeignClient注解使用java的动态代理技术生成代理类**,在这里我们

    指定@FeignClient value为serviceB,则说明这个类的远程目标为spring cloud的服务名称为serviceB的微服

    务。

    • serviceB的具体访问地址,Feign会交由ribbon获取,若该服务有多个实例地址,ribbon会采用指定的负载均

      衡策略选取实例。 (Feign默认集成了Ribbon,可以直接使用)

      可通过下面方式在spring boot 配置文件中修改默认的负载均衡策略:

      account‐service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
      
      • 1

      account-service 是调用的服务的名称,后面的组成部分是固定的。

    • Feign兼容spring的web注解(如:@GetMapping),它会分析声明Feign客户端方法中的Spring注解,得出

      Http请求method、参数信息以及返回信息结构。

    • 当业务调用Feign客户端方法时,会调用代理类,根据以上分析结果,由代理类完成实际的参数封装、远程

      http请求,返回结果封装等操作。


    • 综合架构演示:

    由于Feign是基于Http Restful的调用,在高并发下的性能不够理想,我们将RPC方案从feign切换为Dubbo, 将Spring Cloud与阿里系的若干组件完美集成()

    系统架构图:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-i5hEqqxd-1656345257370)(SSM(含springboot)]+Maven高级+Mybatis.assets/image-20220627201408150.png)

    • service-api的作用:

      优劣:

      取舍:

    • Service2配置(纯生产者):

      package com.itheima.microservice.service2.service; 
      @org.apache.dubbo.config.annotation.Service 
      public class ProviderServiceImpl implements ProviderService { 
         @Override 
         public String service() { 
             return "Provider invoke"; 
         } 
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      其中, @org.apache.dubbo.config.annotation.Service 是 Dubbo 服务注解,仅声明该 Java 服务(本地)实现

      为 Dubbo 服务。 因此,下一步需要将其配置 Dubbo 服务(远程)。

      配置 Dubbo 服务

      在暴露 Dubbo 服务方面,推荐开发人员外部化配置的方式,即指定 Java 服务实现类的扫描基准包

      Dubbo Spring Cloud 继承了 Dubbo Spring Boot 的外部化配置特性,也可以通过标注 @DubboComponentScan 来实现基准包扫描。

      同时,Dubbo 远程服务需要暴露网络端口,并设定通讯协议,完整的 YAML 配置如下所示:

      server: port: ${port:56040} #启动端口 命令行注入 
      spring: application: 
      	name: service2 
      	main: 
      		allow‐bean‐definition‐overriding: true # Spring Boot 2.1 需要设定 
      	cloud: 
      		nacos: 
      			discovery: 
      				server‐addr: 127.0.0.1:8848 
      				namespace: c67e4a97‐a698‐4d6d‐9bb1‐cfac5f5b51c4 
      				cluster‐name: DEFAULT 
      			config: server‐addr: 127.0.0.1:8848 # 配置中心地址 
      				file‐extension: yaml 
      				namespace: c67e4a97‐a698‐4d6d‐9bb1‐cfac5f5b51c4 # 开发环境 
      				group: NACOS_MICROSERVICE_GROUP # xx业务组 
      				dubbo: 
      					scan: # dubbo 服务扫描基准包 
      					base‐packages: com.itheima.microservice protocol: # dubbo 协议 
      					name: dubbo # dubbo 协议端口( ‐1 表示自增端口,从 20880 开始) 
      					port: ${dubbo_port:20891} 
      			registry: 
      				address: nacos://127.0.0.1:8848 
      			application: 
      				qos‐enable: false 
      			consumer: 
      				check: false
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26

      核心:

      标注 @DubboComponentScan 来实现基准包扫描;Dubbo 远程服务需要暴露网络端口

      • dubbo.scan.base-packages : 指定 Dubbo 服务实现类的扫描基准包,将@org.apache.dubbo.confifig.annotation.Service注解标注的service暴露为dubbo服务

      • dubbo.protocol : Dubbo 服务暴露的协议配置,其中子属性 name 为协议名称, port 为dubbo协议端口 可以指定多协议,如:dubbo.protocol.rmi.port=1099

      • dubbo.registry : Dubbo 服务注册中心配置,其中子属性 address 的值 “nacos://127.0.0.1:8848”,说明dubbo服务注册到nacos ,相当于原生dubbo的xml配置中的

      启动服务提供方应用

      Dubbo Spring Cloud 引导类与普通 Spring Cloud 应用并无差别,如下所示:

      @SpringBootApplication 
      @EnableDiscoveryClient 
      public class Service2Bootstrap { 
      	public static void main(String[] args) { 
              SpringApplication.run(Service2Bootstrap.class, args); 
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
    • Service1配置(生产者&消费者):

      实现dubbo服务

      package com.itheima.microservice.service1.service; 
      @org.apache.dubbo.config.annotation.Service  
      //能替换成 import org.apache.dubbo.config.annotation   @Service
      public class ConsumerServiceImpl implements ConsumerService { 
          @Override
          public String service() { 
              return "Consumer invoke " ; 
          } 
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9

      使用@org.apache.dubbo.confifig.annotation.Service标记dubbo服务

      bootstrap.yml配置文件与Service2一致

      pom.xml引入 spring-cloud-starter-dubbo依赖,它会根据接口生成代理对象

       
      	com.alibaba.cloud 
      	spring‐cloud‐starter‐dubbo 
      
      
      • 1
      • 2
      • 3
      • 4

      实现Service1调用Service2

      @org.apache.dubbo.config.annotation.Service 
      public class ConsumerServiceImpl implements ConsumerService { 
          @Reference 
          ProviderService providerService; 
          public String service() { 
              return "Consumer invoke | "+providerService.service(); 
          } 
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      关键:

      使用@Reference 注入 代理对象! (引入的dubbo依赖只在此处使用,引导类处不会像feign的使用一样有@EnableFeignClients注释)

      Dubbo Spring Cloud 引导类与普通 Spring Cloud 应用并无差别(引导类处不会像feign的使用一样有@EnableFeignClients注释)

    • Application1配置:

      实现 application1调用Service1

      @RestController 
      public class Application1Controller { 
          @org.apache.dubbo.config.annotation.Reference 
          private ConsumerService consumerService; 
          
          @GetMapping("/service") 
          public String service(){ 
              return "test" + consumerService.service(); 
          } 
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

      测试: 请求:http://localhost:56020/application1/service

      consumerService正常生成代理对象,service1被调用。

    • zuul配置:

      原来的单体架构,所有的服务都是本地的,UI可以直接调用,现在按功能拆分成独立的服务,跑在独立的一般都在

      独立的虚拟机上的 Java进程了。客户端UI如何访问?他的后台有N个服务,前台就需要记住管理N个服务,一个服

      务下线/更新/升级,前台就要重新部署,这明显不服务我们拆分的理念,特别当前台是移动应用的时候,通常业务

      变化的节奏更快。另外,N个小服务的调用也是一个不小的网络开销。

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VujOFLBE-1656345257371)(SSM(含springboot)]+Maven高级+Mybatis.assets/image-20220627233329623.png)

      • Zuul网关的作用:

      • 提供统一服务入口,让微服务对前台透明

      • 聚合后台的服务,节省流量,提升性能

      • 提供安全,过滤,流控等API管理功能

      Spring Cloud Zuul是整合Netflflix公司的Zuul开源项目实现的微服务网关,它实现了请求路由、负载均衡、校验过

      等 功能。

      • Zuul与Nginx怎么配合使用?

      Zuul与Nginx在实际项目中需要配合使用,如下图,Nginx的作用是反向代理、负载均衡,Zuul的作用是保障微服

      务的安全访问,拦截微服务请求,校验合法性及负载均衡。

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hKW870pZ-1656345257372)(SSM(含springboot)]+Maven高级+Mybatis.assets/image-20220627233539020.png)

      api-gateway配置

      server: 
      	port: 56010 #启动端口 命令行注入 
      spring: 
      	application: 
      		name: api‐gateway 
      	main: 
      		allow‐bean‐definition‐overriding: true # Spring Boot 2.1 需要设定 
      	cloud: 
      		nacos: 
      			discovery: 
      				server‐addr: 127.0.0.1:8848 
      				namespace: c67e4a97‐a698‐4d6d‐9bb1‐cfac5f5b51c4 
      				cluster‐name: DEFAULT 
      			config: 
      				server‐addr: 127.0.0.1:8848 # 配置中心地址 
      				file‐extension: yaml 
      				namespace: c67e4a97‐a698‐4d6d‐9bb1‐cfac5f5b51c4 # 开发环境 
      				group: NACOS_MICROSERVICE_GROUP # xx业务组
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18

      网关的路由配置采用nacos远程配置,在nacos控制台开发环境中新增api-gateway.yaml配置集,配置组为

      TEST_GROUP,配置内容如下:

      zuul: 
      	routes: 
      		application1: 
      			stripPrefix: false 
      			path: /application1/**
      
      • 1
      • 2
      • 3
      • 4
      • 5

      将请求为 /application1/ 开头的请求路由至 application1 服务,保留请求url中的 /application1/

      api-gateway启动:

      注意在启动类上使用@EnableZuulProxy注解标识此工程为Zuul网关,启动类代码如下:

      @SpringBootApplication 
      @EnableDiscoveryClient 
      @EnableZuulProxy 
      public class ApiGatewayBootstrap { 
          public static void main(String[] args) { 
              SpringApplication.run(ApiGatewayBootstrap.class, args); 
          } 
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8

      浏览器访问: http://127.0.0.1:56010/application1/service (相当于UI 前端 get请求)

      通过网关(api-gateway)请求Application1应用,Application1的业务实现又贯穿service1、service2

    使用@org.apache.dubbo.confifig.annotation.Service标记dubbo服务


    杂记:

    浏览器中输入:

    http://127.0.0.1:56020/service

    相当于前端发送get请求,请求地址(url)为:http://127.0.0.1:56020/service,即 服务器:http://127.0.0.1 端口:56020 的service后端接口

    但是,还是postman好用,能够发出post请求

    先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  • 相关阅读:
    selenium爬虫如何绕过反爬,看这一篇文章就足够了
    基于Springboot2.x+vue3.x整合实现微信扫码登录
    JavaSE---栈和队列
    Dubbo实现RPC
    企业级springboot项目架构模板V5.0,开箱即用(针对中小型项目架构,免去重复造轮的操作,强烈推荐)
    组合类替换嵌套内置类型实现多层嵌套业务
    实现α-β剪枝的算法实例
    QT+OSG/osgEarth编译之二十一:FreeXL+Qt编译(一套代码、一套框架,跨平台编译,版本:FreeXL-1.0.6)
    分库分表一:ShardingSphere介绍和入门实战
    iText实战--Table、cell 和 page event
  • 原文地址:https://blog.csdn.net/m0_67402125/article/details/126066987