Spring

Spring&Spring Boot

Spring 自帶 IOC(Inverse of Control:控制反轉(zhuǎn)) 和 AOP(Aspect-Oriented Programming:面向切面編程)栽连、可以很方便地對(duì)數(shù)據(jù)庫(kù)進(jìn)行訪問(wèn)儒鹿、可以很方便地集成第三方組件(電子郵件,任務(wù)交排,調(diào)度也切,緩存等等)屎飘、對(duì)單元測(cè)試支持比較好妥曲、支持 RESTful Java 應(yīng)用程序的開(kāi)發(fā)。

Spring 提供的核心功能主要是 IoC 和 AOP钦购。

Spring Boot 通過(guò)@EnableAutoConfiguration開(kāi)啟自動(dòng)裝配,通過(guò) SpringFactoriesLoader 最終加載META-INF/spring.factories中的自動(dòng)配置類實(shí)現(xiàn)自動(dòng)裝配褂萧,自動(dòng)配置類其實(shí)就是通過(guò)@Conditional按需加載的配置類押桃,想要其生效必須引入spring-boot-starter-xxx包實(shí)現(xiàn)起步依賴

Q:Spring,Spring MVC,Spring Boot 之間什么關(guān)系?

Spring 包含了多個(gè)功能模塊,其中最重要的是 Spring-Core(主要提供 IoC 依賴注入功能的支持) 模塊导犹,唱凯。

Spring MVC 是 Spring 中的一個(gè)很重要的模塊,主要賦予 Spring 快速構(gòu)建 MVC 架構(gòu)的 Web 程序的能力谎痢。MVC 是模型(Model)磕昼、視圖(View)、控制器(Controller)的簡(jiǎn)寫节猿,其核心思想是通過(guò)將業(yè)務(wù)邏輯票从、數(shù)據(jù)、顯示分離來(lái)組織代碼滨嘱。

(使用 Spring 進(jìn)行開(kāi)發(fā)各種配置過(guò)于麻煩比如開(kāi)啟某些 Spring 特性時(shí)峰鄙,需要用 XML 或 Java 進(jìn)行顯式配置。于是太雨,Spring Boot 誕生了)

Spring 旨在簡(jiǎn)化 J2EE 企業(yè)應(yīng)用程序開(kāi)發(fā)吟榴。Spring Boot 旨在簡(jiǎn)化 Spring 開(kāi)發(fā)(減少配置文件,開(kāi)箱即用D野狻)吩翻。

Spring Boot 只是簡(jiǎn)化了配置,如果你需要構(gòu)建 MVC 架構(gòu)的 Web 程序锥咸,你還是需要使用 Spring MVC 作為 MVC 框架狭瞎,只是說(shuō) Spring Boot 幫你簡(jiǎn)化了 Spring MVC 的很多配置,真正做到開(kāi)箱即用

Spring IOC & AOP

  • IOC

    IoC(Inverse of Control:控制反轉(zhuǎn)) 是一種設(shè)計(jì)思想她君,而不是一個(gè)具體的技術(shù)實(shí)現(xiàn)脚作。IoC 的思想就是將原本在程序中手動(dòng)創(chuàng)建對(duì)象的控制權(quán),交由 Spring 框架來(lái)管理缔刹。不過(guò)球涛, IoC 并非 Spring 特有,在其他語(yǔ)言中也有應(yīng)用校镐。

    為什么叫控制反轉(zhuǎn)亿扁?

    • 控制 :指的是對(duì)象創(chuàng)建(實(shí)例化、管理)的權(quán)力

    • 反轉(zhuǎn) :控制權(quán)交給外部環(huán)境(Spring 框架鸟廓、IoC 容器)

將對(duì)象之間的相互依賴關(guān)系交給 IoC 容器來(lái)管理从祝,并由 IoC 容器完成對(duì)象的注入襟己。這樣可以很大程度上簡(jiǎn)化應(yīng)用的開(kāi)發(fā),把應(yīng)用從復(fù)雜的依賴關(guān)系中解放出來(lái)牍陌。 IoC 容器就像是一個(gè)工廠一樣擎浴,當(dāng)我們需要?jiǎng)?chuàng)建一個(gè)對(duì)象的時(shí)候,只需要配置好配置文件/注解即可毒涧,完全不用考慮對(duì)象是如何被創(chuàng)建出來(lái)的贮预。

在實(shí)際項(xiàng)目中一個(gè) Service 類可能依賴了很多其他的類,假如我們需要實(shí)例化這個(gè) Service契讲,你可能要每次都要搞清這個(gè) Service 所有底層類的構(gòu)造函數(shù)仿吞,這可能會(huì)把人逼瘋。如果利用 IoC 的話捡偏,你只需要配置好唤冈,然后在需要的地方引用就行了,這大大增加了項(xiàng)目的可維護(hù)性且降低了開(kāi)發(fā)難度银伟。

在 Spring 中你虹, IoC 容器是 Spring 用來(lái)實(shí)現(xiàn) IoC 的載體, IoC 容器實(shí)際上就是個(gè) Map(key枣申,value)售葡,Map 中存放的是各種對(duì)象。

  • AOP

    AOP(Aspect-Oriented Programming:面向切面編程)能夠?qū)⒛切┡c業(yè)務(wù)無(wú)關(guān)忠藤,卻為業(yè)務(wù)模塊所共同調(diào)用的邏輯或責(zé)任(例如事務(wù)處理挟伙、日志管理、權(quán)限控制等)封裝起來(lái)模孩,便于減少系統(tǒng)的重復(fù)代碼尖阔,降低模塊間的耦合度,并有利于未來(lái)的可拓展性和可維護(hù)性榨咐。

    Spring AOP 就是基于動(dòng)態(tài)代理的介却,如果要代理的對(duì)象,實(shí)現(xiàn)了某個(gè)接口块茁,那么 Spring AOP 會(huì)使用 JDK Proxy齿坷,去創(chuàng)建代理對(duì)象,而對(duì)于沒(méi)有實(shí)現(xiàn)接口的對(duì)象数焊,就無(wú)法使用 JDK Proxy 去進(jìn)行代理了永淌,這時(shí)候 Spring AOP 會(huì)使用 Cglib 生成一個(gè)被代理對(duì)象的子類來(lái)作為代理。

  • DI

    DI(Dependecy Inject,依賴注入)是實(shí)現(xiàn)控制反轉(zhuǎn)的一種設(shè)計(jì)模式佩耳,依賴注入就是將實(shí)例變量傳入到一個(gè)對(duì)象中去遂蛀。

Spring AOP 和 AspectJ AOP 有什么區(qū)別?

Spring AOP 屬于運(yùn)行時(shí)增強(qiáng)干厚,而 AspectJ 是編譯時(shí)增強(qiáng)李滴。 Spring AOP 基于代理(Proxying)螃宙,而 AspectJ 基于字節(jié)碼操作(Bytecode Manipulation)。

Spring AOP 已經(jīng)集成了 AspectJ 所坯,AspectJ 應(yīng)該算的上是 Java 生態(tài)系統(tǒng)中最完整的 AOP 框架了谆扎。AspectJ 相比于 Spring AOP 功能更加強(qiáng)大,但是 Spring AOP 相對(duì)來(lái)說(shuō)更簡(jiǎn)單芹助,

如果我們的切面比較少燕酷,那么兩者性能差異不大。但是周瞎,當(dāng)切面太多的話,最好選擇 AspectJ 饵蒂,它比 Spring AOP 快很多声诸。

Spring Bean

Bean 代指的就是那些被 IoC 容器所管理的對(duì)象。

我們需要告訴 IoC 容器幫助我們管理哪些對(duì)象退盯,這個(gè)是通過(guò)配置元數(shù)據(jù)來(lái)定義的彼乌。配置元數(shù)據(jù)可以是 XML 文件、注解或者 Java 配置類渊迁。

將一個(gè)類聲明為 Bean 的注解有:

  • @Component :通用的注解慰照,可標(biāo)注任意類為 Spring 組件。如果一個(gè) Bean 不知道屬于哪個(gè)層琉朽,可以使用@Component 注解標(biāo)注毒租。

  • @Repository : 對(duì)應(yīng)持久層即 Dao 層,主要用于數(shù)據(jù)庫(kù)相關(guān)操作箱叁。

  • @Service : 對(duì)應(yīng)服務(wù)層墅垮,主要涉及一些復(fù)雜的邏輯,需要用到 Dao 層耕漱。

  • @Controller : 對(duì)應(yīng) Spring MVC 控制層算色,主要用戶接受用戶請(qǐng)求并調(diào)用 Service 層返回?cái)?shù)據(jù)給前端頁(yè)面。

@Component 和 @Bean 的區(qū)別是什么螟够?

  • @Component 注解作用于類灾梦,而@Bean注解作用于方法。

  • @Component通常是通過(guò)類路徑掃描來(lái)自動(dòng)偵測(cè)以及自動(dòng)裝配到 Spring 容器中(我們可以使用 @ComponentScan 注解定義要掃描的路徑從中找出標(biāo)識(shí)了需要裝配的類自動(dòng)裝配到 Spring 的 bean 容器中)妓笙。

  • @Bean 注解通常是我們?cè)跇?biāo)有該注解的方法中定義產(chǎn)生這個(gè) bean,@Bean告訴了 Spring 這是某個(gè)類的實(shí)例若河,當(dāng)我需要用它的時(shí)候還給我。

  • @Bean 注解比 @Component 注解的自定義性更強(qiáng)给郊,而且很多地方我們只能通過(guò) @Bean 注解來(lái)注冊(cè) bean牡肉。比如當(dāng)我們引用第三方庫(kù)中的類需要裝配到 Spring容器時(shí),則只能通過(guò) @Bean來(lái)實(shí)現(xiàn)淆九。

注入 Bean 的注解有哪些统锤?

Spring 內(nèi)置的 @Autowired 以及 JDK 內(nèi)置的 @Resource@Inject 都可以用于注入 Bean毛俏。

Annotaion Package Source
@Autowired org.springframework.bean.factory Spring 2.5+
@Resource javax.annotation Java JSR-250
@Inject javax.inject Java JSR-330

@Autowired@Resource使用的比較多一些。

@Autowired 和 @Resource 的區(qū)別是什么饲窿?

  • Autowired 屬于 Spring 內(nèi)置的注解煌寇,默認(rèn)的注入方式為byType(根據(jù)類型進(jìn)行匹配),也就是說(shuō)會(huì)優(yōu)先根據(jù)接口類型去匹配并注入 Bean (接口的實(shí)現(xiàn)類)逾雄。

    存在的問(wèn)題:

    當(dāng)一個(gè)接口存在多個(gè)實(shí)現(xiàn)類的話阀溶,byType這種方式就無(wú)法正確注入對(duì)象了,因?yàn)檫@個(gè)時(shí)候 Spring 會(huì)同時(shí)找到多個(gè)滿足條件的選擇鸦泳,默認(rèn)情況下它自己不知道選擇哪一個(gè)银锻。這種情況下,注入方式會(huì)變?yōu)?byName(根據(jù)名稱進(jìn)行匹配)做鹰,這個(gè)名稱通常就是類名(首字母小寫)击纬。不過(guò)建議通過(guò) @Qualifier 注解來(lái)顯示指定名稱而不是依賴變量的名稱。

@Autowired
@Qualifier(value = "smsServiceImpl1")
private SmsService smsService;
  • @Resource屬于 JDK 提供的注解钾麸,默認(rèn)注入方式為 byName更振。如果無(wú)法通過(guò)名稱匹配到對(duì)應(yīng)的 Bean 的話,注入方式會(huì)變?yōu)?code>byType饭尝。

    @Resource 有兩個(gè)比較重要且日常開(kāi)發(fā)常用的屬性:name(名稱)肯腕、type(類型)。

    如果僅指定 name 屬性則注入方式為byName钥平,如果僅指定type屬性則注入方式為byType实撒,如果同時(shí)指定nametype屬性(不建議這么做)則注入方式為byType+byName

// 正確注入 SmsServiceImpl1 對(duì)象對(duì)應(yīng)的 bean
@Resource
private SmsService smsServiceImpl1;
// 正確注入 SmsServiceImpl1 對(duì)象對(duì)應(yīng)的 bean(比較推薦這種方式)
@Resource(name = "smsServiceImpl1")
private SmsService smsService;

總結(jié):

  • @Autowired 是 Spring 提供的注解帖池,@Resource 是 JDK 提供的注解奈惑。

  • Autowired 默認(rèn)的注入方式為byType(根據(jù)類型進(jìn)行匹配),@Resource默認(rèn)注入方式為 byName(根據(jù)名稱進(jìn)行匹配)睡汹。

  • 當(dāng)一個(gè)接口存在多個(gè)實(shí)現(xiàn)類的情況下肴甸,@Autowired@Resource都需要通過(guò)名稱才能正確匹配到對(duì)應(yīng)的 Bean。Autowired 可以通過(guò) @Qualifier 注解來(lái)顯示指定名稱囚巴,@Resource可以通過(guò) name 屬性來(lái)顯示指定名稱原在。

Bean的作用域有哪些?

Spring 中 Bean 的作用域通常有下面幾種:

  • singleton : 唯一 bean 實(shí)例彤叉,Spring 中的 bean 默認(rèn)都是單例的庶柿,對(duì)單例設(shè)計(jì)模式的應(yīng)用。

  • prototype : 每次請(qǐng)求都會(huì)創(chuàng)建一個(gè)新的 bean 實(shí)例秽浇。

  • request : 每一次 HTTP 請(qǐng)求都會(huì)產(chǎn)生一個(gè)新的 bean浮庐,該 bean 僅在當(dāng)前 HTTP request 內(nèi)有效。

  • session : 每一次來(lái)自新 session 的 HTTP 請(qǐng)求都會(huì)產(chǎn)生一個(gè)新的 bean柬焕,該 bean 僅在當(dāng)前 HTTP session 內(nèi)有效审残。

  • global-session : 全局 session 作用域梭域,僅僅在基于 portlet 的 web 應(yīng)用中才有意義,Spring5 已經(jīng)沒(méi)有了搅轿。Portlet 是能夠生成語(yǔ)義代碼(例如:HTML)片段的小型 Java Web 插件病涨。它們基于 portlet 容器,可以像 servlet 一樣處理 HTTP 請(qǐng)求璧坟。但是既穆,與 servlet 不同,每個(gè) portlet 都有不同的會(huì)話雀鹃。

單例 Bean 的線程安全問(wèn)題

單例 Bean 存在線程問(wèn)題幻工,主要是因?yàn)楫?dāng)多個(gè)線程操作同一個(gè)對(duì)象的時(shí)候是存在資源競(jìng)爭(zhēng)的。

常見(jiàn)的有兩種解決辦法:

  1. 在 Bean 中盡量避免定義可變的成員變量黎茎。

  2. 在類中定義一個(gè) ThreadLocal 成員變量会钝,將需要的可變成員變量保存在 ThreadLocal 中(推薦的一種方式)。

不過(guò)工三,大部分 Bean 實(shí)際都是無(wú)狀態(tài)(沒(méi)有實(shí)例變量)的(比如 Dao、Service)先鱼,這種情況下俭正, Bean 是線程安全的。

Bean的生命周期

  • Bean 容器找到配置文件中 Spring Bean 的定義焙畔。

  • Bean 容器利用 Java Reflection API 創(chuàng)建一個(gè) Bean 的實(shí)例掸读。

  • 如果涉及到一些屬性值 利用 set()方法設(shè)置一些屬性值。

  • 如果 Bean 實(shí)現(xiàn)了 BeanNameAware 接口宏多,調(diào)用 setBeanName()方法儿惫,傳入 Bean 的名字。

  • 如果 Bean 實(shí)現(xiàn)了 BeanClassLoaderAware 接口伸但,調(diào)用 setBeanClassLoader()方法肾请,傳入 ClassLoader對(duì)象的實(shí)例。

  • 如果 Bean 實(shí)現(xiàn)了 BeanFactoryAware 接口更胖,調(diào)用 setBeanFactory()方法铛铁,傳入 BeanFactory對(duì)象的實(shí)例。

  • 與上面的類似却妨,如果實(shí)現(xiàn)了其他 *.Aware接口饵逐,就調(diào)用相應(yīng)的方法。

  • 如果有和加載這個(gè) Bean 的 Spring 容器相關(guān)的 BeanPostProcessor 對(duì)象彪标,執(zhí)行postProcessBeforeInitialization() 方法

  • 如果 Bean 實(shí)現(xiàn)了InitializingBean接口倍权,執(zhí)行afterPropertiesSet()方法。

  • 如果 Bean 在配置文件中的定義包含 init-method 屬性捞烟,執(zhí)行指定的方法薄声。

  • 如果有和加載這個(gè) Bean 的 Spring 容器相關(guān)的 BeanPostProcessor 對(duì)象当船,執(zhí)行postProcessAfterInitialization() 方法

  • 當(dāng)要銷毀 Bean 的時(shí)候,如果 Bean 實(shí)現(xiàn)了 DisposableBean 接口奸柬,執(zhí)行 destroy() 方法生年。

  • 當(dāng)要銷毀 Bean 的時(shí)候,如果 Bean 在配置文件中的定義包含 destroy-method 屬性廓奕,執(zhí)行指定的方法抱婉。

Spring MVC

MVC 是模型(Model)、視圖(View)桌粉、控制器(Controller)的簡(jiǎn)寫蒸绩,其核心思想是通過(guò)將業(yè)務(wù)邏輯、數(shù)據(jù)铃肯、顯示分離來(lái)組織代碼患亿。

Spring MVC 是當(dāng)前最優(yōu)秀的 MVC 框架。相比于 Struts2 押逼, Spring MVC 使用更加簡(jiǎn)單和方便步藕,開(kāi)發(fā)效率更高,并且 Spring MVC 運(yùn)行速度更快挑格。

MVC 是一種設(shè)計(jì)模式咙冗,Spring MVC 是一款很優(yōu)秀的 MVC 框架。Spring MVC 可以幫助我們進(jìn)行更簡(jiǎn)潔的 Web 層的開(kāi)發(fā)漂彤,并且它天生與 Spring 框架集成雾消。Spring MVC 下我們一般把后端項(xiàng)目分為 Service 層(處理業(yè)務(wù))、Dao 層(數(shù)據(jù)庫(kù)操作)挫望、Entity 層(實(shí)體類)立润、Controller 層(控制層,返回?cái)?shù)據(jù)給前臺(tái)頁(yè)面)媳板。

Spring MVC工作原理

[圖片上傳失敗...(image-5bcdcb-1655719034780)]

  1. 客戶端(瀏覽器)發(fā)送請(qǐng)求桑腮,直接請(qǐng)求到 DispatcherServlet

  2. DispatcherServlet 根據(jù)請(qǐng)求信息調(diào)用 HandlerMapping蛉幸,解析請(qǐng)求對(duì)應(yīng)的 Handler到旦。

  3. 解析到對(duì)應(yīng)的 Handler(也就是我們平常說(shuō)的 Controller 控制器)后,開(kāi)始由 HandlerAdapter 適配器處理巨缘。

  4. HandlerAdapter 會(huì)根據(jù) Handler來(lái)調(diào)用真正的處理器開(kāi)處理請(qǐng)求添忘,并處理相應(yīng)的業(yè)務(wù)邏輯。

  5. 處理器處理完業(yè)務(wù)后若锁,會(huì)返回一個(gè) ModelAndView 對(duì)象搁骑,Model 是返回的數(shù)據(jù)對(duì)象,View 是個(gè)邏輯上的 View

  6. ViewResolver 會(huì)根據(jù)邏輯 View 查找實(shí)際的 View仲器。

  7. DispaterServlet 把返回的 Model 傳給 View(視圖渲染)煤率。

  8. View 返回給請(qǐng)求者(瀏覽器)

Spring框架 -- 設(shè)計(jì)模式

Spring框架中用到了哪些設(shè)計(jì)模式

  • 工廠設(shè)計(jì)模式 : Spring 使用工廠模式通過(guò) BeanFactoryApplicationContext 創(chuàng)建 bean 對(duì)象乏冀。

  • 代理設(shè)計(jì)模式 : Spring AOP 功能的實(shí)現(xiàn)蝶糯。

  • 單例設(shè)計(jì)模式 : Spring 中的 Bean 默認(rèn)都是單例的。注解:@Scope(value = "singleton")

  • 模板方法模式 : Spring 中 jdbcTemplate辆沦、hibernateTemplate 等以 Template 結(jié)尾的對(duì)數(shù)據(jù)庫(kù)操作的類昼捍,它們就使用到了模板模式。

  • 包裝器設(shè)計(jì)模式 : 我們的項(xiàng)目需要連接多個(gè)數(shù)據(jù)庫(kù)肢扯,而且不同的客戶在每次訪問(wèn)中根據(jù)需要會(huì)去訪問(wèn)不同的數(shù)據(jù)庫(kù)妒茬。這種模式讓我們可以根據(jù)客戶的需求能夠動(dòng)態(tài)切換不同的數(shù)據(jù)源。

  • 觀察者模式: Spring 事件驅(qū)動(dòng)模型就是觀察者模式很經(jīng)典的一個(gè)應(yīng)用蔚晨。

  • 適配器模式 : Spring AOP 的增強(qiáng)或通知(Advice)使用到了適配器模式乍钻、spring MVC 中也是用到了適配器模式適配Controller

  • ......

使用單例模式的好處:

  • 對(duì)于頻繁使用的對(duì)象银择,可以省略創(chuàng)建對(duì)象所花費(fèi)的時(shí)間,這對(duì)于那些重量級(jí)對(duì)象而言累舷,是非常可觀的一筆系統(tǒng)開(kāi)銷笋粟;

  • 由于 new 操作的次數(shù)減少,因而對(duì)系統(tǒng)內(nèi)存的使用頻率也會(huì)降低害捕,這將減輕 GC 壓力,縮短 GC 停頓時(shí)間闷畸。

Spring事務(wù)

Spring 管理事務(wù)的方式有幾種?

  • 編程式事務(wù) : 在代碼中硬編碼(不推薦使用) : 通過(guò) TransactionTemplate或者 TransactionManager 手動(dòng)管理事務(wù)佑菩,實(shí)際應(yīng)用中很少使用,但是對(duì)于你理解 Spring 事務(wù)管理原理有幫助殿漠。

  • 聲明式事務(wù) : 在 XML 配置文件中配置或者直接基于注解(推薦使用) : 實(shí)際是通過(guò) AOP 實(shí)現(xiàn)(基于@Transactional 的全注解方式使用最多)

@Transactional(rollbackFor = Exception.class)注解

Exception 分為運(yùn)行時(shí)異常 RuntimeException 和非運(yùn)行時(shí)異常。事務(wù)管理對(duì)于企業(yè)應(yīng)用來(lái)說(shuō)是至關(guān)重要的绞幌,即使出現(xiàn)異常情況蕾哟,它也可以保證數(shù)據(jù)的一致性。

當(dāng) @Transactional 注解作用于類上時(shí)帘营,該類的所有 public 方法將都具有該類型的事務(wù)屬性,同時(shí)逐哈,我們也可以在方法級(jí)別使用該標(biāo)注來(lái)覆蓋類級(jí)別的定義。如果類或者方法加了這個(gè)注解昂秃,那么這個(gè)類里面的方法拋出異常禀梳,就會(huì)回滾,數(shù)據(jù)庫(kù)里面的數(shù)據(jù)也會(huì)回滾械蹋。

@Transactional 注解中如果不配置rollbackFor屬性,那么事務(wù)只會(huì)在遇到RuntimeException的時(shí)候才會(huì)回滾出皇,加上 rollbackFor=Exception.class,可以讓事務(wù)在遇到非運(yùn)行時(shí)異常時(shí)也回滾。

Spring注解小結(jié)

  • @EnableAutoConfiguration:?jiǎn)⒂?SpringBoot 的自動(dòng)配置機(jī)制

  • @ComponentScan: 掃描被@Component (@Repository,@Service,@Controller)注解的 bean哗戈,注解默認(rèn)會(huì)掃描該類所在的包下所有的類郊艘。

  • @Configuration:允許在 Spring 上下文中注冊(cè)額外的 bean 或?qū)肫渌渲妙?/p>

Spring Bean 相關(guān)

@Autowired

自動(dòng)導(dǎo)入對(duì)象到類中,被注入進(jìn)的類同樣要被 Spring 容器管理比如:Service 類注入到 Controller 類中唯咬。

@Component,@Repository,@Service, @Controller

我們一般使用 @Autowired 注解讓 Spring 容器幫我們自動(dòng)裝配 bean纱注。要想把類標(biāo)識(shí)成可用于 @Autowired 注解自動(dòng)裝配的 bean 的類,可以采用以下注解實(shí)現(xiàn):

  • @Component :通用的注解,可標(biāo)注任意類為 Spring 組件胆胰。如果一個(gè) Bean 不知道屬于哪個(gè)層狞贱,可以使用@Component 注解標(biāo)注。

  • @Repository : 對(duì)應(yīng)持久層即 Dao 層蜀涨,主要用于數(shù)據(jù)庫(kù)相關(guān)操作瞎嬉。

  • @Service : 對(duì)應(yīng)服務(wù)層,主要涉及一些復(fù)雜的邏輯厚柳,需要用到 Dao 層氧枣。

  • @Controller : 對(duì)應(yīng) Spring MVC 控制層,主要用于接受用戶請(qǐng)求并調(diào)用 Service 層返回?cái)?shù)據(jù)給前端頁(yè)面别垮。

@RestController

@RestController注解是@Controller@ResponseBody的合集,表示這是個(gè)控制器 bean,并且是將函數(shù)的返回值直接填入 HTTP 響應(yīng)體中,是 REST 風(fēng)格的控制器便监。

單獨(dú)使用 @Controller 不加 @ResponseBody的話一般是用在要返回一個(gè)視圖的情況,這種情況屬于比較傳統(tǒng)的 Spring MVC 的應(yīng)用碳想,對(duì)應(yīng)于前后端不分離的情況烧董。@Controller +@ResponseBody 返回 JSON 或 XML 形式數(shù)據(jù)

@Scope

聲明 Spring Bean 的作用域

@Configuration

一般用來(lái)聲明配置類,可以使用 @Component注解替代胧奔,不過(guò)使用@Configuration注解聲明配置類更加語(yǔ)義化逊移。

處理常見(jiàn)的 HTTP 請(qǐng)求類型

5 種常見(jiàn)的請(qǐng)求類型:

  • GET :請(qǐng)求從服務(wù)器獲取特定資源。

  • POST :在服務(wù)器上創(chuàng)建一個(gè)新的資源龙填。

  • PUT :更新服務(wù)器上的資源(客戶端提供更新后的整個(gè)資源)螟左。

  • DELETE :從服務(wù)器刪除特定的資源。

  • PATCH :更新服務(wù)器上的資源(客戶端提供更改的屬性胶背,可以看做作是部分更新),使用的比較少

@GetMapping("users") 等價(jià)于@RequestMapping(value="/users",method=RequestMethod.GET)
@PostMapping("users") 等價(jià)于@RequestMapping(value="/users",method=RequestMethod.POST)
@PutMapping("/users/{userId}") 等價(jià)于@RequestMapping(value="/users/{userId}",method=RequestMethod.PUT)
@DeleteMapping("/users/{userId}")等價(jià)于@RequestMapping(value="/users/{userId}",method=RequestMethod.DELETE)

前后端傳值

@PathVariable@RequestParam

@PathVariable用于獲取路徑參數(shù)钳吟,@RequestParam用于獲取查詢參數(shù)。

eg:

@GetMapping("/klasses/{klassId}/teachers")
public List<Teacher> getKlassRelatedTeachers(
         @PathVariable("klassId") Long klassId,
         @RequestParam(value = "type", required = false) String type ) {
...
}

如果我們請(qǐng)求的 url 是:/klasses/123456/teachers?type=web

那么我們服務(wù)獲取到的數(shù)據(jù)就是:klassId=123456,type=web坝茎。

@RequestBody

用于讀取 Request 請(qǐng)求(可能是 POST,PUT,DELETE,GET 請(qǐng)求)的 body 部分并且Content-Type 為 application/json 格式的數(shù)據(jù),接收到數(shù)據(jù)之后會(huì)自動(dòng)將數(shù)據(jù)綁定到 Java 對(duì)象上去嗤放。系統(tǒng)會(huì)使用HttpMessageConverter或者自定義的HttpMessageConverter將請(qǐng)求的 body 中的 json 字符串轉(zhuǎn)換為 java 對(duì)象。

需要注意的是:一個(gè)請(qǐng)求方法只可以有一個(gè)@RequestBody次酌,但是可以有多個(gè)@RequestParam@PathVariable。 如果你的方法必須要用兩個(gè) @RequestBody來(lái)接受數(shù)據(jù)的話岳服,大概率是你的數(shù)據(jù)庫(kù)設(shè)計(jì)或者系統(tǒng)設(shè)計(jì)出問(wèn)題了希俩!

JPA相關(guān)

@Entity聲明一個(gè)類對(duì)應(yīng)一個(gè)數(shù)據(jù)庫(kù)實(shí)體。

@Table 設(shè)置表名

@Id :聲明一個(gè)字段為主鍵颜武。

使用@Id聲明之后,我們還需要定義主鍵的生成策略鳞上。我們可以使用 @GeneratedValue 指定主鍵生成策略。@GeneratedValue(strategy = GenerationType.IDENTITY)

@GeneratedValue注解默認(rèn)使用的策略是GenerationType.AUTO

一般使用 MySQL 數(shù)據(jù)庫(kù)的話因块,使用GenerationType.IDENTITY策略比較普遍一點(diǎn)(分布式系統(tǒng)的話需要另外考慮使用分布式 ID)籍铁。

@Column 聲明字段。

@Transient :聲明不需要與數(shù)據(jù)庫(kù)映射的字段吩愧,在保存的時(shí)候不需要保存進(jìn)數(shù)據(jù)庫(kù) 。

如果我們想讓secrect 這個(gè)字段不被持久化雁佳,可以使用 @Transient關(guān)鍵字聲明脐帝。

@Entity(name="USER")
public class User {
    ......
    @Transient
    private String secrect; // not persistent because of @Transient

}

@JsonIgnoreProperties 作用在類上用于過(guò)濾掉特定字段不返回或者不解析堵腹。

@JsonIgnore一般用于類的屬性上,作用和@JsonIgnoreProperties 一樣疚顷。

@JsonFormat一般用來(lái)格式化 json 數(shù)據(jù)。

@Test聲明一個(gè)方法為測(cè)試方法

@Transactional被聲明的測(cè)試方法的數(shù)據(jù)會(huì)回滾腿堤,避免污染測(cè)試數(shù)據(jù)。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末笆檀,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子酗洒,更是在濱河造成了極大的恐慌,老刑警劉巖寝蹈,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件登淘,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡黔州,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門流妻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人绅这,你說(shuō)我怎么就攤上這事≈ま保” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵寇窑,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我甩骏,道長(zhǎng)窗市,這世上最難降的妖魔是什么饮笛? 我笑而不...
    開(kāi)封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮扎拣,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘二蓝。我一直安慰自己,他們只是感情好刊愚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著鸥诽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪牡借。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天荐虐,我揣著相機(jī)與錄音干毅,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛涛菠,可吹牛的內(nèi)容都是我干的劳秋。 我是一名探鬼主播绢馍,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼睡互,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了就珠?” 一聲冷哼從身側(cè)響起寇壳,我...
    開(kāi)封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嗓违,失蹤者是張志新(化名)和其女友劉穎九巡,沒(méi)想到半個(gè)月后蹂季,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體冕广,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡偿洁,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了涕滋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片睬辐。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡宾肺,死狀恐怖溯饵,靈堂內(nèi)的尸體忽然破棺而出锨用,到底是詐尸還是另有隱情,我是刑警寧澤增拥,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布啄巧,位于F島的核電站掌栅,受9級(jí)特大地震影響秩仆,放射性物質(zhì)發(fā)生泄漏猾封。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一忘衍、第九天 我趴在偏房一處隱蔽的房頂上張望逾苫。 院中可真熱鬧枚钓,春花似錦铅搓、人聲如沸搀捷。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)氢烘。三九已至家厌,卻和暖如春播玖,著一層夾襖步出監(jiān)牢的瞬間饭于,已是汗流浹背维蒙。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留果覆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓局待,卻偏偏與公主長(zhǎng)得像斑响,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子舰罚,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容