黑马程序员ssm总结[大全版本,有对应pdf+源码](spring->springmvc-->springboot-->maven高级->cloud微服务)
前言
pdf+源碼(大全),對應(yīng)視頻:https://www.bilibili.com/video/BV1VJ411X7xX?p=20&vd_source=0e4ada3d15f80172cb72c52e0fcabd05
自我感覺黑馬課程比官方文檔好,新手友好,強推!
看文檔必看視頻效率高,理解更透,一遍看不懂,反復(fù)看!
有問題,歡迎與我討論: qq:1657019234
黑馬程序員ssm資料(從spring–>springmvc–>springboot–>maven高級->cloud微服務(wù))
文章目錄
- spring核心容器
- spring注解開發(fā)(正片開始)
- spring整合mybatis
- spring整合Junit
- AOP:用于不改變原代碼基礎(chǔ)上 進(jìn)行功能增強
- Spring事務(wù)
- Maven分模塊開發(fā):
- springboot
- nacos配置中心(cloud-alibaba)
- nacos服務(wù)發(fā)現(xiàn)
- 負(fù)載均衡,引入 服務(wù)發(fā)現(xiàn)的目的
- 沒有nacos服務(wù)注冊中心時,微服務(wù)調(diào)用
- nacos服務(wù)注冊的實現(xiàn)
- 有了nacos服務(wù)注冊中心時,利用feign(ribbon)進(jìn)行微服務(wù)調(diào)用
耦合性可以是低耦合性(或稱為松散耦合),也可以是高耦合性(或稱為緊密耦合)。以下列出一些耦合性的分類,從高到低依序排列:
- 內(nèi)容耦合(content coupling,耦合度最高):也稱為病態(tài)耦合(pathological coupling)當(dāng)一個模塊直接使用另一個模塊的內(nèi)部數(shù)據(jù),或通過非正常入口而轉(zhuǎn)入另一個模塊內(nèi)部。
- 共用耦合/公共耦合(common coupling):也稱為全局耦合(global coupling.)指通過一個公共數(shù)據(jù)環(huán)境相互作用的那些模塊間的耦合。公共耦合的復(fù)雜程序隨耦合模塊的個數(shù)增加而增加。
- 外部耦合(external coupling):發(fā)生在二個模塊共用一個外加的數(shù)據(jù)格式、通信協(xié)議或是設(shè)備界面,基本上和模塊和外部工具及設(shè)備的溝通有關(guān)。
- 控制耦合(control coupling):指一個模塊調(diào)用另一個模塊時,傳遞的是控制變量(如開關(guān)、標(biāo)志等),被調(diào)模塊通過該控制變量的值有選擇地執(zhí)行塊內(nèi)某一功能;
- 特征耦合/標(biāo)記耦合(stamp coupling):也稱為數(shù)據(jù)結(jié)構(gòu)耦合,是指幾個模塊共享一個復(fù)雜的數(shù)據(jù)結(jié)構(gòu),如高級語言中的數(shù)組名、記錄名、文件名等這些名字即標(biāo)記,其實傳遞的是這個數(shù)據(jù)結(jié)構(gòu)的地址;
- 數(shù)據(jù)耦合/數(shù)據(jù)耦合(data coupling):是指模塊借由傳入值共享數(shù)據(jù),每一個數(shù)據(jù)都是最基本的數(shù)據(jù),而且只分享這些數(shù)據(jù)(例如傳遞一個整數(shù)給計算平方根的函數(shù))。
- 消息耦合(message coupling,是無耦合之外,耦合度最低的耦合):可以借由以下二個方式達(dá)成:狀態(tài)的去中心化(例如在對象中),組件間利用傳入值或消息傳遞 (計算機科學(xué))來通信。
- 無耦合:模塊完全不和其他模塊交換信息。
降低耦合度的方法
1、少使用類的繼承,多用接口隱藏實現(xiàn)的細(xì)節(jié)。 java面向?qū)ο缶幊桃虢涌诔酥С侄鄳B(tài)外, 隱藏實現(xiàn)細(xì)節(jié)也是其中一個目的。
2、模塊的功能化分盡可能的單一,道理也很簡單,功能單一的模塊供其它模塊調(diào)用的機會就少。(其實這是高內(nèi)聚的一種說法,高內(nèi)聚低耦合一般同時出現(xiàn),為了限制篇幅,我們將在以后的版期中討論)。
3、遵循一個定義只在一個地方出現(xiàn)。
4、少使用全局變量。
5、類屬性和方法的聲明少用public,多用private關(guān)鍵字,
6、多用設(shè)計模式,比如采用MVC的設(shè)計模式就可以降低界面與業(yè)務(wù)邏輯的耦合度。
7、盡量不用“硬編碼”的方式寫程序,同時也盡量避免直接用SQL語句操作數(shù)據(jù)庫。
8、最后當(dāng)然就是避免直接操作或調(diào)用其它模塊或類(內(nèi)容耦合);如果模塊間必須存在耦合,原則上盡量使用數(shù)據(jù)耦合,少用控制耦合,限制公共耦合的范圍,避免使用內(nèi)容耦合。
緊密耦合的系統(tǒng)在開發(fā)階段有以下的缺點:
spring核心容器
本章是core&bean的原理講解
5min復(fù)習(xí)視頻:核心容器總結(jié)
Spring就提出了一個解決方案:
- 使用對象時,在程序中不要主動使用new產(chǎn)生對象,轉(zhuǎn)換為由外部提供對象
- 即:使用消息耦合(耦合度最低的耦合),去中心化,
(1)什么是控制反轉(zhuǎn)呢?
- 使用對象時,由主動new產(chǎn)生對象轉(zhuǎn)換為由外部提供對象,此過程中對象創(chuàng)建控制權(quán)由程序轉(zhuǎn)移到外部,此思想稱為控制反轉(zhuǎn)。
2.DI的注入方法
-
setter注入(比構(gòu)造器注入更常用,推薦,我們一般只用構(gòu)造器注入)<property>(又分為
-
引用類型注入<property name=“bookDao” ref=“bookDao”>)
-
簡單類型(int…String)注入<property name=“msg” ref=“我的類型是自動檢測的,看要被注入的變量的類型”>)
-
集合類型注入
<property name="names"><list><value>xxx</value><ref bean="dataSource"/><list> </property>
-
-
構(gòu)造器注入<constructor-arg>
IoC基礎(chǔ)上,需要綁定兩個Bean之間的依賴關(guān)系,需要DI進(jìn)行綁定,<property>的形式
3.bean的生命周期scope: <bean id=“bookDao” class=“com.itheima.dao.impl.BookDaoImpl” init-method=“init” destroy-method=“destory”/ …>當(dāng)然,還有很多別的scope生命周期屬性
spring注解開發(fā)(正片開始)
spring3.0升級了
純注釋開發(fā),使用一個添加了 @configuration的config配置類來進(jìn)行配置
spring注解開發(fā)總結(jié)
-
普通配置類注入:
-
第三方配置類注入
spring整合mybatis
看看就行
可以看到,在老師給的項目中,shiro( shiro是apache的是一個分布式權(quán)限管理的框架,實現(xiàn) 用戶認(rèn)證、用戶授權(quán))
和 cors(用于允許跨域請求)
出于安全原因,瀏覽器禁止AJAX調(diào)用當(dāng)前來源之外的資源,跨域資源共享(CORS)是由大多數(shù)瀏覽器實施的W3C規(guī)范,使您可以靈活地指定對哪種跨域請求進(jìn)行授權(quán)。
從Spring Framework 4.2開始,開箱即用地支持CORS。 CORS請求(包括帶有OPTIONS方法的預(yù)檢請求)將自動分派到各種已注冊的HandlerMappings。
二者采取了類似的配置類形式
spring整合Junit
看看就行
AOP:用于不改變原代碼基礎(chǔ)上 進(jìn)行功能增強
- 概念:AOP(Aspect Oriented Programming)面向切面編程,一種編程范式
- 作用:在不驚動原始設(shè)計的基礎(chǔ)上為方法進(jìn)行功能增強
- 核心概念
- 代理(Proxy):SpringAOP的核心本質(zhì)是采用代理模式實現(xiàn)的
- 連接點(JoinPoint):在SpringAOP中,理解為任意方法的執(zhí)行
- 切入點(Pointcut):匹配連接點的式子,也是具有共性功能的方法描述
- 通知(Advice):若干個方法的共性功能,在切入點處執(zhí)行,最終體現(xiàn)為一個方法
- 切面(Aspect):描述通知與切入點的對應(yīng)關(guān)系
- 目標(biāo)對象(Target):被代理的原始對象成為目標(biāo)對象
切入點表達(dá)式:
-
切入點表達(dá)式標(biāo)準(zhǔn)格式:動作關(guān)鍵字(訪問修飾符 返回值 包名.類/接口名.方法名(參數(shù))異常名)
execution(* com.itheima.service.*Service.*(..)) -
切入點表達(dá)式描述通配符:
- 作用:用于快速描述,范圍描述
- *:匹配任意符號(常用)
- .. :匹配多個連續(xù)的任意符號(常用)
- +:匹配子類類型
-
切入點表達(dá)式書寫技巧
1.按標(biāo)準(zhǔn)規(guī)范開發(fā)
2.查詢操作的返回值建議使用*匹配
3.減少使用…的形式描述包
4.對接口進(jìn)行描述,使用*表示模塊名,例如UserService的匹配描述為*Service
5.方法名書寫保留動詞,例如get,使用*表示名詞,例如getById匹配描述為getBy*
6.參數(shù)根據(jù)實際情況靈活調(diào)整
Spring事務(wù)
- 保障一系列的數(shù)據(jù)庫操作同成功同失敗
- Spring事務(wù)作用:在數(shù)據(jù)層或**業(yè)務(wù)層**保障一系列的數(shù)據(jù)庫操作同成功同失敗
- Spring為了管理事務(wù),提供了一個平臺事務(wù)管理器PlatformTransactionManager:
進(jìn)行提交與回滾,事務(wù)(轉(zhuǎn)賬操作中:A錢-,B錢+)作為一個整體,一旦部分執(zhí)行不成功,能夠整個回滾,從而確保若:A-成功,B+失敗后,A,B都將回滾,恢復(fù)原狀態(tài)
(springboot中,連SpringMvcConfig都沒了,使用,@EnableWebMvc也不會用了)
REST風(fēng)格(只是一種風(fēng)格,不是一種規(guī)范,可以不遵守,但由于采用的人多,已經(jīng)接近于一種規(guī)范):
Restful風(fēng)格:基于Rest風(fēng)格,進(jìn)一步簡化:
@ResponseBody
@RestController
@RequestMapping
PostMan請求管理規(guī)范:
使用Restful風(fēng)格進(jìn)行開發(fā)的一個示例:
如果直接訪問前端界面:localhost/pages/books.html,報錯:
瀏覽器:
因:瀏覽器訪問使用get方法,由spring處理,spring認(rèn)為你沒有這一接口.確實,它本來也不是接口,而是一個頁面.
法:spring放行,讓tomcat處理;即:實現(xiàn)一個過濾器(filter)靜態(tài)頁面,tomcat直接處理,動態(tài)請求springMVC處理
攔截器:
攔截器(Intercepter)是一種動態(tài)攔截方法調(diào)用的機制,在springMVC中動態(tài)攔截 控制器 方法的執(zhí)行
- 在指定方法的前后執(zhí)行預(yù)先設(shè)定的代碼
- 阻止原始方法的執(zhí)行
攔截器與過濾器的區(qū)別:
- filter屬于servlet技術(shù),intercepter屬于SpringMVC技術(shù)
- filter對所有訪問進(jìn)行增強,intercepter僅對SpringMVC的訪問進(jìn)行增強
Maven分模塊開發(fā):
idea的maven相關(guān)功能只能確保書寫的時候不報錯,不能保證運行的時候不報錯
通過install,實現(xiàn)本地安裝
pom項目默認(rèn)的打包方式:<packaging>jar</packaging>
pom項目web項目的打包方式:<packaging>war</packaging>
pom項目聚合項目的打包方式:<packaging>pom</packaging>
- maven沖突:
發(fā)生沖突時,maven會有一些規(guī)則來選用依賴
依賴沖突可能會導(dǎo)致某個依賴使用了你不想使用的版本(這個版本可能會導(dǎo)致運行錯誤)
-
可選依賴和排除依賴
<!--可選依賴是隱藏當(dāng)前工程所依賴的資源,隱藏后對應(yīng)資源將不具有依賴傳遞--> <optional>true</optional> <!--排除依賴是隱藏當(dāng)前資源對應(yīng)的依賴關(guān)系--> <exclusions><exclusion><groupId>com.itheima</groupId><artifactId>maven_03_pojo</artifactId></exclusion> </exclusions> -
maven多環(huán)境開發(fā):(profile)
pro,dev,test多環(huán)境不同,如何配置多環(huán)境開發(fā),以供選用?
-
使用聚合統(tǒng)一管理項目
步驟1:創(chuàng)建一個空的maven項目
步驟2:將項目的打包方式改為pom
步驟3:pom.xml添加所要管理的項目
步驟4:使用聚合統(tǒng)一管理項目
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.itheima</groupId><artifactId>maven_01_parent</artifactId><version>1.0-RELEASE</version><packaging>pom</packaging><!--設(shè)置管理的模塊名稱--><modules><module>../maven_02_ssm</module><module>../maven_03_pojo</module><module>../maven_04_dao</module></modules> </project> -
繼承:解決重復(fù)配置問題
<dependencyManagement>標(biāo)簽不真正引入jar包,而是配置可供子項目選擇的jar包依賴
子項目要想使用它所提供的這些jar包,需要自己添加依賴,并且不需要指定<version>
-
屬性:即在pom.xml中配置屬性變量,更改一處時,其他地方跟著更改
定義:
<!--定義屬性--> <properties><spring.version>5.2.10.RELEASE</spring.version><junit.version>4.12</junit.version><mybatis-spring.version>1.3.0</mybatis-spring.version> </properties>使用:
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version> </dependency>文件加載 屬性:配置文件(如jdbc.properties文件)中的屬性,也讓Maven進(jìn)行管理
需要設(shè)置maven過濾文件范圍
詳見 maven高級.md
-
私服
使用nexus能建立私服倉庫(小團(tuán)隊開發(fā)):nexus server端建立私服倉庫–>本地maven setting.xml完成私服地址配置(至此,能訪問私服了)–>項目pom.xml,添加 <distributionManagement> 配置當(dāng)前工程保存(部署)在私服中的具體位置–>maven deploy指令部署
(下載不需要部署)
springboot
(前期都是基礎(chǔ),了解原理;springboot開始進(jìn)入實用)
一個經(jīng)典Controller處理前端請求:
@RestController @RequestMapping("/books") public class BookController {@GetMapping("/{id}")public String getById(@PathVariable Integer id){System.out.println("id ==> "+id);return "hello , spring boot!";} }SpringBoot 程序如何修改呢?SpringBoot 提供了多種屬性配置方式,加載順序由上往下,因而如下三文件,最終:server:port:82
今后統(tǒng)一使用application.yml
-
application.properties
server.port=80 -
application.yml
server:port: 81 -
application.yaml
server:port: 82
注意:SpringBoot 程序的配置文件名必須是 application ,只是后綴名不同而已。
- mybatis
mybatis-plus真的能省很多力,但老師已經(jīng)用了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指令
注意:不需要擔(dān)心 自寫mapper(xml文件)代碼被覆蓋, 高于mybatis1.3.7的版本都不會覆蓋 ,參見自寫mapper(xml文件)代碼被覆蓋
必須盡快弄好,或者想別的方法讓單老師先開始!
(都在mybatis-generator.xml中配置完成,且生成連帶實體類!!!)
Unknown system variable ‘query_cache_size‘ 的解決方法 方法二親測有效!
當(dāng)前,需要解決映射不成功的問題(mybatis理解不深!),以箭頭為 映射成功的標(biāo)志
了解mybatis映射機制,正常來說,不需要mybatis-generator.xml也能生成箭頭(視箭頭為映射成功的標(biāo)志)
嘗試,更改mybatis-generator.xml的dao目錄(覆蓋也沒關(guān)系!)
依舊沒問題
映射機制:
1.引入mybatis依賴(pom.xml)
2.property.yml文件,配置mybatis映射關(guān)系(如果)
使用mybatis-generator.xml生成的都有箭頭
必然不是spring配置錯誤,而是mybatis理解不深刻!
嘗試:刪除某一文件,重配!
依舊沒問題
批量注入過程中,發(fā)現(xiàn)@Repository改為使用@Mapper注入成功了!
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(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總結(jié)
compile
不聲明scope元素的情況下的默認(rèn)值;compile表示被依賴包需要參與當(dāng)前項目的編譯,包括后續(xù)的測試,運行周期也參與其中,是一個比較強的依賴;打包的時候通常需要包含進(jìn)去。
…
runtime
runtime與compile比較相似,區(qū)別在于runtime 跳過了編譯階段,打包的時候通常需要包含進(jìn)去。
…
import
import 只能在pom文件的中使用,從而引入其他的pom文件中引入依賴,如:在Spring boot 項目的POM文件中,我們可以通過在POM文件中繼承 Spring-boot-starter-parent來引用Srping boot默認(rèn)依賴的jar包
…
因而,也難怪,之前依賴使用import出現(xiàn)了不生效的情況!
分析:
當(dāng)前版本:較為合理,pom中的依賴是,結(jié)合:老師原項目+nacos-discover示例項目得到的(雖說去除了哥的那幾個依賴,這是我最擔(dān)心的!如果出現(xiàn)相關(guān)報錯,將刪除哥的文件)
-
fastjson找不到:
依賴沖突:
當(dāng)前fastjson版本無問題!2.1依然足矣!
搜:
1.External Libraries中并未發(fā)現(xiàn)相關(guān)依賴的Jar包–>有,非
-
必然是某些配置錯誤,因此,進(jìn)行了配置文件置零操作,與老師當(dāng)初保持一致(現(xiàn)下所處階段:不如張俊杰當(dāng)初,但他引入了大量不靠譜依賴,我這靠譜)
- spring-boot-starter-web 版本 不一致,有風(fēng)險!(低于)
nacos配置中心(cloud-alibaba)
配置管理的必要性:
同一份程序在不同的環(huán)境(開發(fā),測試,生產(chǎn))、不同的集群(如不同的數(shù)據(jù)中心)經(jīng)常需要有不同的
配置,所以需要有完善的環(huán)境、集群配置管理
在微服務(wù)架構(gòu)中,當(dāng)系統(tǒng)從一個單體應(yīng)用,被拆分成分布式系統(tǒng)上一個個服務(wù)節(jié)點后,配置文件也必須跟著遷移
(分割),這樣配置就分散了,不僅如此,分散中還包含著冗余,如下圖:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-Lp7d1a0R-1656345257365)(SSM(含springboot)]+Maven高級+Mybatis.assets/image-20220627173947910.png)
配置中心的服務(wù)流程如下:
1、用戶在配置中心更新配置信息。
2、服務(wù)A和服務(wù)B及時得到配置更新通知,從配置中心獲取配置。
總得來說,配置中心就是一種統(tǒng)一管理各種應(yīng)用配置的基礎(chǔ)服務(wù)組件。
在系統(tǒng)架構(gòu)中,配置中心是整個微服務(wù)基礎(chǔ)架構(gòu)體系中的一個組件,如下圖,它的功能看上去并不起眼,無非就是
配置的管理和存取,但它是整個微服務(wù)架構(gòu)中不可或缺的一環(huán)。
總而言之,在傳統(tǒng)巨型單體應(yīng)用紛紛轉(zhuǎn)向細(xì)粒度微服務(wù)架構(gòu)的歷史進(jìn)程中,配置中心是微服務(wù)化不可缺少的一個系
統(tǒng)組件,在這種背景下中心化的配置服務(wù)即配置中心應(yīng)運而生
通過配置中心,我們實現(xiàn)了:
- 合格的配置中心需要滿足如下特性:
- 配置項容易讀取和修改
- 分布式環(huán)境下應(yīng)用配置的可管理性,即提供遠(yuǎn)程管理配置的能力
- 支持對配置的修改的檢視以把控風(fēng)險
- 可以查看配置修改的歷史記錄
- 不同部署環(huán)境下應(yīng)用配置的隔離性
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-4f1Y4G9C-1656345257366)(SSM(含springboot)]+Maven高級+Mybatis.assets/image-20220627173914565.png)
問:nacos配置中心的配置是動態(tài)的,我們的微服務(wù)已經(jīng)跑起來后,是如何派上用場的?懂了,只是集中管理,但是需要:重新跑!
示例服務(wù)中,配置只是進(jìn)行打印,如何 將配置派上用場?
一般來說,spring boot的配置將在application.yml(也可以是application.properties)文件中編寫,
由于使用外部 配置中心,必須將原先的application.yml重命名為bootstrap.yml,bootstrap.yml如下所示:
spring.cloud.nacos.confifig.server-addr 指定了Nacos Server的網(wǎng)絡(luò)地址和端口號
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-uMr6Bfog-1656345257367)(SSM(含springboot)]+Maven高級+Mybatis.assets/image-20220627174121228.png)
如此,外部(nacos)配置中心派上了用場
通過自定義擴(kuò)展的 Data Id 配置,既可以解決多個應(yīng)用間配置共享的問題,又可以支持一個應(yīng)用有多個配置文件
結(jié)論:實現(xiàn)簡單,后期可以整,暫時沒必要!!!
nacos服務(wù)發(fā)現(xiàn)
筆記摘自:黑馬程序員 nacos-服務(wù)發(fā)現(xiàn).pdf
負(fù)載均衡,引入 服務(wù)發(fā)現(xiàn)的目的
先導(dǎo): Spring Cloud服務(wù)協(xié)作流程:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-E4rTyo5f-1656345257368)(SSM(含springboot)]+Maven高級+Mybatis.assets/image-20220627183219988.png)
(1)在微服務(wù)啟動時,會向服務(wù)發(fā)現(xiàn)中心上報自身實例信息,這里ServiceB 包含多個實例。
每個實例包括:
IP地址、端口號信息。
北京市昌平區(qū)建材城西路金燕龍辦公樓一層 電話:400-618-9090(2)微服務(wù)會定期從Nacos Server(服務(wù)發(fā)現(xiàn)中心)獲取服務(wù)實例列表。
(3)當(dāng)ServiceA調(diào)用ServiceB時,ribbon組件從本地服務(wù)實例列表中查找ServiceB的實例,如獲取了多個實例如
Instance1、Instance2。這時ribbon會通過用戶所配置的負(fù)載均衡策略從中選擇一個實例。
(4)最終,Feign組件會通過ribbon選取的實例發(fā)送http請求。
采用Feign+Ribbon的整合方式,是由Feign完成遠(yuǎn)程調(diào)用的整個流程。而Feign集成了Ribbon,Feign使用Ribbon
完成調(diào)用實例的負(fù)載均衡。
考察核心:光憑zuul網(wǎng)關(guān)配置,能否實現(xiàn)負(fù)載均衡?(而非在 service微服務(wù)互相調(diào)用過程中,通過feign實現(xiàn)!)
(負(fù)載均衡的兩個環(huán)節(jié):1.通過feign(調(diào)用ribbon組件)微服務(wù)直接互相調(diào)用(客戶端負(fù)載均衡,微服務(wù)是nacos客戶端 nacos server是服務(wù)端) 2.通過zuul 網(wǎng)關(guān)配置,端口轉(zhuǎn)發(fā)(服務(wù)端負(fù)載均衡,通過nginx實現(xiàn)的一樣是服務(wù)端負(fù)載均衡;zuul和nginx往往是一起使用的!) )
ribbon根據(jù)負(fù)載均衡策略負(fù)責(zé)選擇示例,feign會通過ribbon來選擇實例進(jìn)而發(fā)送請求(feign集成來ribbon)
(本文檔,似乎一直在集中闡述 客戶端負(fù)載均衡!)
沒有nacos服務(wù)注冊中心時,微服務(wù)調(diào)用
在微服務(wù)架構(gòu)中,如果沒有nacos服務(wù)注冊中心,如何進(jìn)行微服務(wù)之間互相調(diào)用(通信)?
Service B暴露接口供Service A調(diào)用:
@SpringBootApplication @RestController public class SpringRestProviderBootstrap { public static void main(String[] args) { SpringApplication.run(SpringRestProviderBootstrap.class, args); }@GetMapping(value = "/service") //暴露服務(wù) public String service(){ return "provider invoke"; } }配置文件:
server.port = 56010Service A去調(diào)用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(); //調(diào)用服務(wù) String providerResult = restTemplate.getForObject("http://" + providerAddress + "/service",String.class); return "consumer invoke | " + providerResult; } }RestTemplate工具類,spring提供的一個HTTP請求工具
在服務(wù)的調(diào)用過程中,使用到了一個工具,叫做 RestTemplate,RestTemplate 是由 Spring 提供的一個 HTTP 請求工具。在上文的案例中,開發(fā)者也可以不使用 RestTemplate ,使用 Java 自帶的 HttpUrlConnection 或者經(jīng)典的網(wǎng)絡(luò)訪問框架 HttpClient 也可以完成上文的案例,只是在 Spring 項目中,使用 RestTemplate 顯然更方便一些。在傳統(tǒng)的項目架構(gòu)中,因為不涉及到服務(wù)之間的調(diào)用,大家對 RestTemplate 的使用可能比較少
總結(jié):
關(guān)鍵: application.yml中配置provider.address屬性,拼湊出地址后,使用restTemplate.getForObject方法進(jìn)行調(diào)用!
但是,微服務(wù)可能是部署在云環(huán)境的,服務(wù)實例的網(wǎng)絡(luò)位置或許是動態(tài)分配的。另外,每一個服務(wù)一般會有多個實
例來做負(fù)載均衡,由于宕機或升級,服務(wù)實例網(wǎng)絡(luò)地址會經(jīng)常動態(tài)改變。再者,每一個服務(wù)也可能應(yīng)對臨時訪問壓
力增加新的服務(wù)節(jié)點。正如下圖所示:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-pK72PVE8-1656345257369)(SSM(含springboot)]+Maven高級+Mybatis.assets/image-20220627192149824.png)
nacos服務(wù)注冊的實現(xiàn)
(服務(wù)發(fā)現(xiàn)(讓服務(wù)之間互相感知)與管理問題)
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-9PJda5TR-1656345257369)(SSM(含springboot)]+Maven高級+Mybatis.assets/image-20220627192235974.png)
(1)在每個服務(wù)啟動時會向服務(wù)發(fā)現(xiàn)中心上報自己的網(wǎng)絡(luò)位置。這樣,在服務(wù)發(fā)現(xiàn)中心內(nèi)部會形成一個服務(wù)注冊
表,服務(wù)注冊表是服務(wù)發(fā)現(xiàn)的核心部分,是包含所有服務(wù)實例的網(wǎng)絡(luò)地址的數(shù)據(jù)庫。
(2)服務(wù)發(fā)現(xiàn)客戶端會定期從服務(wù)發(fā)現(xiàn)中心同步服務(wù)注冊表 ,并緩存在客戶端。
(3)當(dāng)需要對某服務(wù)進(jìn)行請求時,服務(wù)實例通過該注冊表,定位目標(biāo)服務(wù)網(wǎng)絡(luò)地址。若目標(biāo)服務(wù)存在多個網(wǎng)絡(luò)地
址,則使用負(fù)載均衡算法從多個服務(wù)實例中選擇出一個,然后發(fā)出請求。
總結(jié)一下,在微服務(wù)環(huán)境中,由于服務(wù)運行實例的網(wǎng)絡(luò)地址是不斷動態(tài)變化的,服務(wù)實例數(shù)量的動態(tài)變化 ,因此無
法使用固定的配置文件來記錄服務(wù)提供方的網(wǎng)絡(luò)地址,必須使用動態(tài)的服務(wù)發(fā)現(xiàn)機制用于實現(xiàn)微服務(wù)間的相互感
知。各服務(wù)實例會上報自己的網(wǎng)絡(luò)地址,這樣服務(wù)中心就形成了一個完整的服務(wù)注冊表,各服務(wù)實例會通過服務(wù)發(fā)
現(xiàn)中心來獲取訪問目標(biāo)服務(wù)的網(wǎng)絡(luò)地址,從而實現(xiàn)服務(wù)發(fā)現(xiàn)的機制。
服務(wù)注冊的實現(xiàn)極其簡單:
(下面這個例子是從 海馬程序員-服務(wù)發(fā)現(xiàn)中,摘出來的部分代碼,像@EnableFeignClients如果僅為實現(xiàn)服務(wù)注冊而不實現(xiàn)feign調(diào)用其他微服務(wù),那它是多余的)
(為了更深刻理解,看源文檔 nacos-服務(wù)發(fā)現(xiàn).pdf (文檔視頻中有,我的博客中也有) or 黑馬nacos-服務(wù)發(fā)現(xiàn) 視頻)
application.yml配置
server: port: 56020 #啟動端口 命令行注入 spring: application: name: quickstart‐consumer cloud: nacos: discovery: server‐addr: 127.0.0.1:88482.Provider(生產(chǎn)者)遠(yuǎn)程代理定義
Note: @EnableDiscoveryClient 在spring cloud項目中表明此項目是一個注冊發(fā)現(xiàn)客戶端,這里注冊服務(wù)發(fā)
現(xiàn)使用的是Nacos
Note: @EnableFeignClients 開啟FeignClient
可以說,實現(xiàn)服務(wù)注冊,只需要: @EnableDiscoveryClient 就行!!!
有了nacos服務(wù)注冊中心時,利用feign(ribbon)進(jìn)行微服務(wù)調(diào)用
spring(boot)使用feign需在pom.xml中加入依賴:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring‐cloud‐starter‐openfeign</artifactId> </dependency>參考前面 沒有nacos服務(wù)注冊中心時,微服務(wù)調(diào)用 的ServiceA調(diào)用ServiceB的例子,我們有了 在服務(wù)注冊后 使用Feign實現(xiàn)這個過程,代碼如下:
Service B暴露"/service"服務(wù)端點,如下:
@SpringBootApplication @RestController public class SpringRestProviderBootstrap { public static void main(String[] args) { SpringApplication.run(SpringRestProviderBootstrap.class, args); } @GetMapping(value = "/service") //暴露服務(wù) public String service(){ return "provider invoke"; } }Service A中,通過Feign調(diào)用Service B方式如下:
(1)聲明Feign客戶端
@FeignClient(value = "serviceB") public interface ServiceBAgent { /** * 根據(jù)用戶名查詢賬號信息 * @param username 用戶名 * @return 賬號信息 */ //Feign英文表意為“假裝,偽裝,變形”,此處正是將HTTP報文請求方式 偽裝為簡單的java接口(內(nèi)部,未通過TTTP)調(diào)用方式 @GetMapping(value = "/service") public String service(); }Feign是Netflflix開發(fā)的聲明式、模板化的HTTP客戶端, Feign可以幫助我們更快捷、優(yōu)雅地調(diào)用HTTP API。Feign
的英文表意為“假裝,偽裝,變形”, 可以理解為將HTTP報文請求方式偽裝為簡單的java接口調(diào)用方式。
(2)業(yè)務(wù)調(diào)用
@Autowired private ServiceBAgent serviceBAgent.; //....略 serviceBAgent.service(); //....略- 在 聲明Feign客戶端 之后,Feign會根據(jù)**@FeignClient注解使用java的動態(tài)代理技術(shù)生成代理類**,在這里我們
指定@FeignClient value為serviceB,則說明這個類的遠(yuǎn)程目標(biāo)為spring cloud的服務(wù)名稱為serviceB的微服
務(wù)。
-
serviceB的具體訪問地址,Feign會交由ribbon獲取,若該服務(wù)有多個實例地址,ribbon會采用指定的負(fù)載均
衡策略選取實例。 (Feign默認(rèn)集成了Ribbon,可以直接使用)
可通過下面方式在spring boot 配置文件中修改默認(rèn)的負(fù)載均衡策略:
account‐service.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRuleaccount-service 是調(diào)用的服務(wù)的名稱,后面的組成部分是固定的。
-
Feign兼容spring的web注解(如:@GetMapping),它會分析聲明Feign客戶端方法中的Spring注解,得出
Http請求method、參數(shù)信息以及返回信息結(jié)構(gòu)。
-
當(dāng)業(yè)務(wù)調(diào)用Feign客戶端方法時,會調(diào)用代理類,根據(jù)以上分析結(jié)果,由代理類完成實際的參數(shù)封裝、遠(yuǎn)程
http請求,返回結(jié)果封裝等操作。
- 綜合架構(gòu)演示:
由于Feign是基于Http Restful的調(diào)用,在高并發(fā)下的性能不夠理想,我們將RPC方案從feign切換為Dubbo, 將Spring Cloud與阿里系的若干組件完美集成()
系統(tǒng)架構(gòu)圖:
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-i5hEqqxd-1656345257370)(SSM(含springboot)]+Maven高級+Mybatis.assets/image-20220627201408150.png)
-
service-api的作用:
優(yōu)劣:
取舍:
-
Service2配置(純生產(chǎn)者):
package com.itheima.microservice.service2.service; @org.apache.dubbo.config.annotation.Service public class ProviderServiceImpl implements ProviderService { @Override public String service() { return "Provider invoke"; } }其中, @org.apache.dubbo.config.annotation.Service 是 Dubbo 服務(wù)注解,僅聲明該 Java 服務(wù)(本地)實現(xiàn)
為 Dubbo 服務(wù)。 因此,下一步需要將其配置 Dubbo 服務(wù)(遠(yuǎn)程)。
配置 Dubbo 服務(wù)
在暴露 Dubbo 服務(wù)方面,推薦開發(fā)人員外部化配置的方式,即指定 Java 服務(wù)實現(xiàn)類的掃描基準(zhǔn)包。
Dubbo Spring Cloud 繼承了 Dubbo Spring Boot 的外部化配置特性,也可以通過標(biāo)注 @DubboComponentScan 來實現(xiàn)基準(zhǔn)包掃描。
同時,Dubbo 遠(yuǎn)程服務(wù)需要暴露網(wǎng)絡(luò)端口,并設(shè)定通訊協(xié)議,完整的 YAML 配置如下所示:
server: port: ${port:56040} #啟動端口 命令行注入 spring: application: name: service2 main: allow‐bean‐definition‐overriding: true # Spring Boot 2.1 需要設(shè)定 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 # 開發(fā)環(huán)境 group: NACOS_MICROSERVICE_GROUP # xx業(yè)務(wù)組 dubbo: scan: # dubbo 服務(wù)掃描基準(zhǔn)包 base‐packages: com.itheima.microservice protocol: # dubbo 協(xié)議 name: dubbo # dubbo 協(xié)議端口( ‐1 表示自增端口,從 20880 開始) port: ${dubbo_port:20891} registry: address: nacos://127.0.0.1:8848 application: qos‐enable: false consumer: check: false核心:
標(biāo)注 @DubboComponentScan 來實現(xiàn)基準(zhǔn)包掃描;Dubbo 遠(yuǎn)程服務(wù)需要暴露網(wǎng)絡(luò)端口
-
dubbo.scan.base-packages : 指定 Dubbo 服務(wù)實現(xiàn)類的掃描基準(zhǔn)包,將@org.apache.dubbo.confifig.annotation.Service注解標(biāo)注的service暴露為dubbo服務(wù)
-
dubbo.protocol : Dubbo 服務(wù)暴露的協(xié)議配置,其中子屬性 name 為協(xié)議名稱, port 為dubbo協(xié)議端口 可以指定多協(xié)議,如:dubbo.protocol.rmi.port=1099
-
dubbo.registry : Dubbo 服務(wù)注冊中心配置,其中子屬性 address 的值 “nacos://127.0.0.1:8848”,說明dubbo服務(wù)注冊到nacos ,相當(dāng)于原生dubbo的xml配置中的 <dubbo:registry address=“10.20.153.10:9090” />
啟動服務(wù)提供方應(yīng)用
Dubbo Spring Cloud 引導(dǎo)類與普通 Spring Cloud 應(yīng)用并無差別,如下所示:
@SpringBootApplication @EnableDiscoveryClient public class Service2Bootstrap { public static void main(String[] args) { SpringApplication.run(Service2Bootstrap.class, args); } } -
-
Service1配置(生產(chǎn)者&消費者):
實現(xiàn)dubbo服務(wù)
package com.itheima.microservice.service1.service; @org.apache.dubbo.config.annotation.Service //能替換成 import org.apache.dubbo.config.annotation @Service public class ConsumerServiceImpl implements ConsumerService { @Overridepublic String service() { return "Consumer invoke " ; } }使用@org.apache.dubbo.confifig.annotation.Service標(biāo)記dubbo服務(wù)
bootstrap.yml配置文件與Service2一致
pom.xml引入 spring-cloud-starter-dubbo依賴,它會根據(jù)接口生成代理對象
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring‐cloud‐starter‐dubbo</artifactId> </dependency>實現(xiàn)Service1調(diào)用Service2
@org.apache.dubbo.config.annotation.Service public class ConsumerServiceImpl implements ConsumerService { @Reference ProviderService providerService; public String service() { return "Consumer invoke | "+providerService.service(); } }關(guān)鍵:
使用@Reference 注入 代理對象! (引入的dubbo依賴只在此處使用,引導(dǎo)類處不會像feign的使用一樣有@EnableFeignClients注釋)
Dubbo Spring Cloud 引導(dǎo)類與普通 Spring Cloud 應(yīng)用并無差別(引導(dǎo)類處不會像feign的使用一樣有@EnableFeignClients注釋)
-
Application1配置:
實現(xiàn) application1調(diào)用Service1
@RestController public class Application1Controller { @org.apache.dubbo.config.annotation.Reference private ConsumerService consumerService; @GetMapping("/service") public String service(){ return "test" + consumerService.service(); } }測試: 請求:http://localhost:56020/application1/service
consumerService正常生成代理對象,service1被調(diào)用。
-
zuul配置:
原來的單體架構(gòu),所有的服務(wù)都是本地的,UI可以直接調(diào)用,現(xiàn)在按功能拆分成獨立的服務(wù),跑在獨立的一般都在
獨立的虛擬機上的 Java進(jìn)程了??蛻舳薝I如何訪問?他的后臺有N個服務(wù),前臺就需要記住管理N個服務(wù),一個服
務(wù)下線/更新/升級,前臺就要重新部署,這明顯不服務(wù)我們拆分的理念,特別當(dāng)前臺是移動應(yīng)用的時候,通常業(yè)務(wù)
變化的節(jié)奏更快。另外,N個小服務(wù)的調(diào)用也是一個不小的網(wǎng)絡(luò)開銷。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VujOFLBE-1656345257371)(SSM(含springboot)]+Maven高級+Mybatis.assets/image-20220627233329623.png)
-
Zuul網(wǎng)關(guān)的作用:
-
提供統(tǒng)一服務(wù)入口,讓微服務(wù)對前臺透明
-
聚合后臺的服務(wù),節(jié)省流量,提升性能
-
提供安全,過濾,流控等API管理功能
Spring Cloud Zuul是整合Netflflix公司的Zuul開源項目實現(xiàn)的微服務(wù)網(wǎng)關(guān),它實現(xiàn)了請求路由、負(fù)載均衡、校驗過
慮等 功能。
- Zuul與Nginx怎么配合使用?
Zuul與Nginx在實際項目中需要配合使用,如下圖,Nginx的作用是反向代理、負(fù)載均衡,Zuul的作用是保障微服
務(wù)的安全訪問,攔截微服務(wù)請求,校驗合法性及負(fù)載均衡。
[外鏈圖片轉(zhuǎn)存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(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 需要設(shè)定 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 # 開發(fā)環(huán)境 group: NACOS_MICROSERVICE_GROUP # xx業(yè)務(wù)組網(wǎng)關(guān)的路由配置采用nacos遠(yuǎn)程配置,在nacos控制臺開發(fā)環(huán)境中新增api-gateway.yaml配置集,配置組為
TEST_GROUP,配置內(nèi)容如下:
zuul: routes: application1: stripPrefix: false path: /application1/**將請求為 /application1/ 開頭的請求路由至 application1 服務(wù),保留請求url中的 /application1/
api-gateway啟動:
注意在啟動類上使用@EnableZuulProxy注解標(biāo)識此工程為Zuul網(wǎng)關(guān),啟動類代碼如下:
@SpringBootApplication @EnableDiscoveryClient @EnableZuulProxy public class ApiGatewayBootstrap { public static void main(String[] args) { SpringApplication.run(ApiGatewayBootstrap.class, args); } }瀏覽器訪問: http://127.0.0.1:56010/application1/service (相當(dāng)于UI 前端 get請求)
通過網(wǎng)關(guān)(api-gateway)請求Application1應(yīng)用,Application1的業(yè)務(wù)實現(xiàn)又貫穿service1、service2
-
使用@org.apache.dubbo.confifig.annotation.Service標(biāo)記dubbo服務(wù)
雜記:
瀏覽器中輸入:
http://127.0.0.1:56020/service
相當(dāng)于前端發(fā)送get請求,請求地址(url)為:http://127.0.0.1:56020/service,即 服務(wù)器:http://127.0.0.1 端口:56020 的service后端接口
但是,還是postman好用,能夠發(fā)出post請求
總結(jié)
以上是生活随笔為你收集整理的黑马程序员ssm总结[大全版本,有对应pdf+源码](spring->springmvc-->springboot-->maven高级->cloud微服务)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 模仿不再受宠若惊
- 下一篇: [html] 写一个布局,当页面滚动一定