黑马程序员ssm总结[大全版本,有对应pdf+源码](spring->springmvc-->springboot-->maven高级->cloud微服务)
前言
pdf+源碼(大全),對應視頻:https://www.bilibili.com/video/BV1VJ411X7xX?p=20&vd_source=0e4ada3d15f80172cb72c52e0fcabd05
自我感覺黑馬課程比官方文檔好,新手友好,強推!
看文檔必看視頻效率高,理解更透,一遍看不懂,反復看!
有問題,歡迎與我討論: qq:1657019234
黑馬程序員ssm資料(從spring–>springmvc–>springboot–>maven高級->cloud微服務)
文章目錄
- spring核心容器
- spring注解開發(正片開始)
- spring整合mybatis
- spring整合Junit
- AOP:用于不改變原代碼基礎上 進行功能增強
- Spring事務
- Maven分模塊開發:
- springboot
- nacos配置中心(cloud-alibaba)
- nacos服務發現
- 負載均衡,引入 服務發現的目的
- 沒有nacos服務注冊中心時,微服務調用
- nacos服務注冊的實現
- 有了nacos服務注冊中心時,利用feign(ribbon)進行微服務調用
耦合性可以是低耦合性(或稱為松散耦合),也可以是高耦合性(或稱為緊密耦合)。以下列出一些耦合性的分類,從高到低依序排列:
- 內容耦合(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、最后當然就是避免直接操作或調用其它模塊或類(內容耦合);如果模塊間必須存在耦合,原則上盡量使用數據耦合,少用控制耦合,限制公共耦合的范圍,避免使用內容耦合。
緊密耦合的系統在開發階段有以下的缺點:
spring核心容器
本章是core&bean的原理講解
5min復習視頻:核心容器總結
Spring就提出了一個解決方案:
- 使用對象時,在程序中不要主動使用new產生對象,轉換為由外部提供對象
- 即:使用消息耦合(耦合度最低的耦合),去中心化,
(1)什么是控制反轉呢?
- 使用對象時,由主動new產生對象轉換為由外部提供對象,此過程中對象創建控制權由程序轉移到外部,此思想稱為控制反轉。
2.DI的注入方法
-
setter注入(比構造器注入更常用,推薦,我們一般只用構造器注入)<property>(又分為
-
引用類型注入<property name=“bookDao” ref=“bookDao”>)
-
簡單類型(int…String)注入<property name=“msg” ref=“我的類型是自動檢測的,看要被注入的變量的類型”>)
-
集合類型注入
<property name="names"><list><value>xxx</value><ref bean="dataSource"/><list> </property>
-
-
構造器注入<constructor-arg>
IoC基礎上,需要綁定兩個Bean之間的依賴關系,需要DI進行綁定,<property>的形式
3.bean的生命周期scope: <bean id=“bookDao” class=“com.itheima.dao.impl.BookDaoImpl” init-method=“init” destroy-method=“destory”/ …>當然,還有很多別的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.按標準規范開發
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項目默認的打包方式:<packaging>jar</packaging>
pom項目web項目的打包方式:<packaging>war</packaging>
pom項目聚合項目的打包方式:<packaging>pom</packaging>
- maven沖突:
發生沖突時,maven會有一些規則來選用依賴
依賴沖突可能會導致某個依賴使用了你不想使用的版本(這個版本可能會導致運行錯誤)
-
可選依賴和排除依賴
<!--可選依賴是隱藏當前工程所依賴的資源,隱藏后對應資源將不具有依賴傳遞--> <optional>true</optional> <!--排除依賴是隱藏當前資源對應的依賴關系--> <exclusions><exclusion><groupId>com.itheima</groupId><artifactId>maven_03_pojo</artifactId></exclusion> </exclusions> -
maven多環境開發:(profile)
pro,dev,test多環境不同,如何配置多環境開發,以供選用?
-
使用聚合統一管理項目
步驟1:創建一個空的maven項目
步驟2:將項目的打包方式改為pom
步驟3:pom.xml添加所要管理的項目
步驟4:使用聚合統一管理項目
<?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><!--設置管理的模塊名稱--><modules><module>../maven_02_ssm</module><module>../maven_03_pojo</module><module>../maven_04_dao</module></modules> </project> -
繼承:解決重復配置問題
<dependencyManagement>標簽不真正引入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進行管理
需要設置maven過濾文件范圍
詳見 maven高級.md
-
私服
使用nexus能建立私服倉庫(小團隊開發):nexus server端建立私服倉庫–>本地maven setting.xml完成私服地址配置(至此,能訪問私服了)–>項目pom.xml,添加 <distributionManagement> 配置當前工程保存(部署)在私服中的具體位置–>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!";} }SpringBoot 程序如何修改呢?SpringBoot 提供了多種屬性配置方式,加載順序由上往下,因而如下三文件,最終:server:port:82
今后統一使用application.yml
-
application.properties
server.port=80 -
application.yml
server:port: 81 -
application.yaml
server:port: 82
注意: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文件)代碼被覆蓋
必須盡快弄好,或者想別的方法讓單老師先開始!
(都在mybatis-generator.xml中配置完成,且生成連帶實體類!!!)
Unknown system variable ‘query_cache_size‘ 的解決方法 方法二親測有效!
當前,需要解決映射不成功的問題(mybatis理解不深!),以箭頭為 映射成功的標志
了解mybatis映射機制,正常來說,不需要mybatis-generator.xml也能生成箭頭(視箭頭為映射成功的標志)
嘗試,更改mybatis-generator.xml的dao目錄(覆蓋也沒關系!)
依舊沒問題
映射機制:
1.引入mybatis依賴(pom.xml)
2.property.yml文件,配置mybatis映射關系(如果)
使用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總結
compile
不聲明scope元素的情況下的默認值;compile表示被依賴包需要參與當前項目的編譯,包括后續的測試,運行周期也參與其中,是一個比較強的依賴;打包的時候通常需要包含進去。
…
runtime
runtime與compile比較相似,區別在于runtime 跳過了編譯階段,打包的時候通常需要包含進去。
…
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"; } }配置文件:
server.port = 56010Service 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; } }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-服務發現 視頻)
application.yml配置
server: port: 56020 #啟動端口 命令行注入 spring: application: name: quickstart‐consumer cloud: nacos: discovery: server‐addr: 127.0.0.1:88482.Provider(生產者)遠程代理定義
Note: @EnableDiscoveryClient 在spring cloud項目中表明此項目是一個注冊發現客戶端,這里注冊服務發
現使用的是Nacos
Note: @EnableFeignClients 開啟FeignClient
可以說,實現服務注冊,只需要: @EnableDiscoveryClient 就行!!!
有了nacos服務注冊中心時,利用feign(ribbon)進行微服務調用
spring(boot)使用feign需在pom.xml中加入依賴:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring‐cloud‐starter‐openfeign</artifactId> </dependency>參考前面 沒有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"; } }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(); }Feign是Netflflix開發的聲明式、模板化的HTTP客戶端, Feign可以幫助我們更快捷、優雅地調用HTTP API。Feign
的英文表意為“假裝,偽裝,變形”, 可以理解為將HTTP報文請求方式偽裝為簡單的java接口調用方式。
(2)業務調用
@Autowired private ServiceBAgent serviceBAgent.; //....略 serviceBAgent.service(); //....略- 在 聲明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.RandomRuleaccount-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"; } }其中, @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核心:
標注 @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:registry address=“10.20.153.10:9090” />
啟動服務提供方應用
Dubbo Spring Cloud 引導類與普通 Spring Cloud 應用并無差別,如下所示:
@SpringBootApplication @EnableDiscoveryClient public class Service2Bootstrap { public static void main(String[] args) { SpringApplication.run(Service2Bootstrap.class, args); } } -
-
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 { @Overridepublic String service() { return "Consumer invoke " ; } }使用@org.apache.dubbo.confifig.annotation.Service標記dubbo服務
bootstrap.yml配置文件與Service2一致
pom.xml引入 spring-cloud-starter-dubbo依賴,它會根據接口生成代理對象
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring‐cloud‐starter‐dubbo</artifactId> </dependency>實現Service1調用Service2
@org.apache.dubbo.config.annotation.Service public class ConsumerServiceImpl implements ConsumerService { @Reference ProviderService providerService; public String service() { return "Consumer invoke | "+providerService.service(); } }關鍵:
使用@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(); } }測試: 請求: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業務組網關的路由配置采用nacos遠程配置,在nacos控制臺開發環境中新增api-gateway.yaml配置集,配置組為
TEST_GROUP,配置內容如下:
zuul: routes: application1: stripPrefix: false path: /application1/**將請求為 /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); } }瀏覽器訪問: 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請求
總結
以上是生活随笔為你收集整理的黑马程序员ssm总结[大全版本,有对应pdf+源码](spring->springmvc-->springboot-->maven高级->cloud微服务)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 模仿不再受宠若惊
- 下一篇: [html] 写一个布局,当页面滚动一定