如何搭建一個SpringBoot項目

步驟

1尘喝、創(chuàng)建一個普通maven項目:SpringBootDemo

2、在pom.xml文件設置項目打包方式

<packaging>jar</packaging>

3、在pom.xml文件導入SpringBoot父項目

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.3</version>
    <relativePath/>
</parent>

4、在pom.xml文件導入Web項目依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

5玄呛、編寫普通Controller類

/**
 * 控制層
 */
@Controller
public class HelloController {
    @RequestMapping("hello")
    public Object hellp(){
        return "Hello SpringBoot!";
    }
}

6、編寫啟動類和二,啟動SpringBoot項目

/**
 * SpringBoot項目啟動類
 */
@SpringBootApplication
public class SpringBootDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootDemoApplication.class,args);
    }
}

7徘铝、瀏覽器訪問測試: http://localhost:8080/hello

問題

  1. Web打包不應該是war,為什么是jar?

  2. pom.xml文件中繼承的spring-boot-starter-parent有什么用惯吕?

  3. pom.xml文件中導入的依賴spring-boot-starter-web又有什么用惕它?

  4. 啟動類SpringBootDemoApplication頭頂上的@SpringBootApplication注解做了什么?

  5. 沒有配置tomcat废登,沒有設置端口服務器怎么來怠缸,又怎么啟動的?

  6. main方法中SpringApplication.run(..)又是什么情況钳宪?

分析

問題1:Web打包不應該是war,為什么是jar

SpringBoot默認的打包方式就是jar,傳統(tǒng)的外接tomcat或插件式tomcat與web項目是相互獨立,相互對接時必須滿足一定規(guī)則吏颖,war包結構項目就是規(guī)則約定之一搔体。而SpringBoot項目采用的是內嵌式(簡單理解為編碼方式)tomcat,項目與tomcat融為一體半醉,部署疚俱,啟動,運行一體化缩多,就沒有各種條條框框的約束了呆奕。

問題2:pom.xml文件中繼承的spring-boot-starter-parent有啥用

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.3</version>
    <relativePath/>
</parent>

spring-boot-starter-parent其實是SpringBoot提供了工具工程,工程收集了市面上常用各種第三方jar依賴衬吆,并對這些jar依賴進行了版本管理梁钾。當我們的項目繼承這個項目工程,就自動成為SpringBoot項目逊抡,并無償繼承了這些第三方jar依賴姆泻。后續(xù)項目中需要某個第三方依賴,只需要引入依賴坐標即可冒嫡, 不需要關系依賴版本拇勃。比如:

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

一個拓展:

繼承是 Maven 中很強大的一種功能,繼承可以使得子POM可以獲得 parent 中的部分配置(groupId,version,dependencies,build,dependencyManagement等)孝凌,可以對子pom進行統(tǒng)一的配置和依賴管理方咆。

  • parent項目中的dependencyManagement里的聲明的依賴 , 只具有聲明的作用,并不實現(xiàn)引入蟀架,因此子項目需要顯式的聲明需要用的依賴瓣赂。如果不在子項目中聲明依賴,是不會從父項目中繼承下來的辜窑;只有在子項目中寫了該依賴項钩述,可以不指定具體版本,會從父項目中繼承該項穆碎,并且version和scope都讀取自父pom;另外如果子項目中指定了版本號牙勘,那么會使用子項目中指定的jar版本

  • parent項目中的dependencies里聲明的依賴會被所有的子項目繼承

問題3:pom.xml文件中導入的依賴spring-boot-starter-web又有啥用

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

問題2中說了,SpringBoot收集了很多常用的第三方jar依賴所禀,為了進一步提高用戶體驗感方面,SpringBoot根據jar依賴特點,對這些依賴進一步分類色徘,整合恭金,再封裝,形成一個新的依賴工具集褂策, 每個工具集都解決特定領域的依賴問題横腿。SpringBoot將這些依賴工具稱為:啟動器(組件)颓屑,命名規(guī)則: spring-boot-starter-xxx。 如果是非SpringBoot定制的啟動器耿焊, 一般命名規(guī)則:xxx-spring-boot-starter

入門案例中導入的spring-boot-starter-web 就是用于解決web項目依賴的工具集(啟動器)

image

常用的啟動器(starter)還有很多:

spring-boot-starter: 核心啟動器 , 提供了自動配置,日志和YAML配置支持

spring-boot-starter-aop: 支持使用 Spring AOPAspectJ 進行切面編程揪惦。

spring-boot-starter-freemarker: 支持使用 FreeMarker 視圖構建Web 應用

spring-boot-starter-test: 支持使用 JUnit, 測試 Spring Boot 應用

spring-boot-starter-web: 支持使用 Spring MVC 構建 Web 應用罗侯,包括 RESTful 應用器腋,使用 Tomcat 作為默認的嵌入式容器。

spring-boot-starter-actuator: 支持使用 Spring Boot Actuator 提供生產級別的應用程序監(jiān)控和管理功能钩杰。

spring-boot-starter-logging: 提供了對日志的支持 , 默認使用Logback

問題4:啟動類App頭頂上的@SpringBootApplication注解做了什么

要回答這個問題纫塌, 就必須講清楚springboot的自動配置原理(也稱自動裝配)

springboot的精髓就在這個注解里。

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

先回顧一下以前使用SpringMVC搭建web項目時讲弄, 我們是怎么做的

1>導入Web措左, Spring, SpringMVC依賴

2>在web.xml文件配置前端控制器:DispatcherServlet

3>編寫controller類

4>配置controller掃描包路徑

5>部署到tomcat并啟動

從上面步驟上看垂睬,剛剛入門案例不需要我們去做的有幾步媳荒?

1:不需要配置前端控制器

2:不需要配置包掃描路徑

3:不需要部署tomcat這步

這些步驟我們都沒做,項目卻跑起來驹饺,那肯定有人幫我們做了钳枕,那會是誰?所有問題關鍵就是這個:@SpringBootApplication注解赏壹。

@SpringBootApplication源碼解析

點擊進入鱼炒,查看源碼:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = 
               { 
                 @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
                 @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) 
               }
              )
public @interface SpringBootApplication {
    ......
}

注解上面又有一堆注解,核心的有3個:

  • @SpringBootConfiguration

  • @EnableAutoConfiguration

  • @ComponentScan

這里注意:注解頭頂又貼有注解(非元注解)蝌借,表示當前注解為復合注解昔瞧,當前注解也擁有所貼注解功能。

@ComponentScan

功能:spring組件掃描注解菩佑,掃描所貼的類所在包及其子包所有貼有版型注解的類自晰,并創(chuàng)建對象交給spring容器管理。

入門案例中稍坯, 我們將@SpringBootApplication 注解貼在App類里面酬荞,那么它會掃描App類所有包及其子包里面所有貼有版型注解的類,并創(chuàng)建實例瞧哟, 那么controller包下的HelloController類就可以被掃描到混巧。

一個注意點: 一般貼有@SpringBootApplication注解的類稱之為啟動類,建議放置在根包下勤揩。

@SpringBootConfiguration

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
    ....
}

該注解頭頂貼了@Configuration注解咧党, 前面Javaconfig講過貼有@Configuration類為配置類

<pre>@SpringBootApplication 頭頂貼有 @SpringBootConfiguration
@SpringBootConfiguration 頭頂貼有 @Configuration </pre>

根據上面注解關系推導下:入門案例中貼有@SpringBootApplication注解的App類就是一個項目配置類。

一個注意點:一般springboot項目只有唯一一個啟動類陨亡,啟動類都是配置類傍衡。

@EnableAutoConfiguration

@EnableAutoConfiguration的作用深员,告訴SpringBoot基于你所添加的依賴,去“猜測”你想要如何配置Spring蛙埂。比如當我們引入了spring-boot-starter-web這個啟動器辨液,spring會解析這個啟動器,推測當前項目為web項目箱残,根據啟動器默認配置要求自動配置web及SpringMVC相關對象創(chuàng)建與管理。比如:前端控制的創(chuàng)建止吁,比如前端控制的路徑映射等被辑。

SpringBoot對自帶啟動器與第三方啟動器進行了大量的默認配置,這些配置是否生效敬惦,是否加載到spring容器中使用盼理,取決于我們項目是否引入了對啟動器依賴,如果有那么默認配置就會生效俄删。

那么

  • 這些默認配置是在哪里定義的呢宏怔?

  • 為何依賴引入就會觸發(fā)配置生效呢?

看源碼:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    ...
}

@EnableAutoConfiguration注解import導入了一個AutoConfigurationImportSelector自動配置類選擇器畴椰,該類可以實現(xiàn)配置類批量載入 spring容器臊诊。其核心方法是getCandidateConfigurations

protected List<String> getCandidateConfigurations(
    AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
        getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());
    Assert.notEmpty(configurations, 
                    "No auto configuration classes found in META-INF/spring.factories. If you "
                    + "are using a custom packaging, make sure that file is correct.");
    return configurations;
}

getCandidateConfigurations方法作用是委托SpringFactoriesLoader去讀取jar包中的META-INF/spring.factories文件, 并加載里面配置的自動配置對象,其中包括: AOP / PropertyPlaceholder / FreeMarker / HttpMessageConverter / Jackson / DataSource / DataSourceTransactionManager / DispatcherServlet / WebMvc 等等斜脂。

image

一個注意點:不管是spring定制的啟動器抓艳,還是第三方定制的啟動器,都需要編寫META-INF/spring.factories帚戳,里面指定啟動器的自動配置類

接上面分析玷或, spring.factories文件中配置很多自動配置類,哪些會生效(加載到Spring容器并跑起來)呢, 此時需要滿足這些啟動類生效條件才會自動裝配片任。

以我們熟悉SpringMVC為例子:

在spring.factories找WebMvcAutoConfiguration自動配置類

<pre>org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration</pre>

點進去看源碼

@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@AutoConfigureAfter({ 
        DispatcherServletAutoConfiguration.class, 
        TaskExecutionAutoConfiguration.class,
        ValidationAutoConfiguration.class })
public class WebMvcAutoConfiguration {
    ...
}

我們看到這個類上的4個注解:

  • @Configuration:聲明這個類是一個配置類

  • @ConditionalOnWebApplication(type = Type.SERVLET)

    ConditionalOn偏友,翻譯就是在某個條件下,此處就是滿足項目的類是是Type.SERVLET類型对供,我們現(xiàn)在的項目就滿足了, 就是一個web服務(web項目)

  • @ConditionalOnClass({ Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class })

    這里的條件是OnClass位他,也就是滿足以下類存在:Servlet、DispatcherServlet犁钟、WebMvcConfigurer棱诱。這里就是判斷你是否引入了SpringMVC相關依賴,引入依賴后該條件成立涝动,當前類的配置才會生效迈勋!

  • @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)

    這個條件與上面不同,OnMissingBean醋粟,是說環(huán)境中沒有指定的Bean這個才生效靡菇。其實這就是自定義配置的入口重归,也就是說,如果我們自己配置了一個WebMVCConfigurationSupport的bean, 代表容器里已經存在該bean了厦凤,那么這個默認配置就會失效鼻吮!這里允許我們定制自己的bean替換spring默認的。

接著较鼓,我們查看WebMvcAutoConfiguration該類中定義了什么:(如果它生效了椎木,會創(chuàng)建什么對象并載入容器進行管理)

視圖解析器:

@Bean
@ConditionalOnMissingBean
public InternalResourceViewResolver defaultViewResolver() {
   InternalResourceViewResolver resolver = new InternalResourceViewResolver();
   resolver.setPrefix(this.mvcProperties.getView().getPrefix());
   resolver.setSuffix(this.mvcProperties.getView().getSuffix());
   return resolver;
}

@Bean
@ConditionalOnBean(View.class)
@ConditionalOnMissingBean
public BeanNameViewResolver beanNameViewResolver() {
   BeanNameViewResolver resolver = new BeanNameViewResolver();
   resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 10);
   return resolver;
}

WebMvcAutoConfiguration中使用了@AutoConfigureAfter注解, 意為指定的類加載完了后,再加載本類

<pre>@AutoConfigureAfter({ DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class })</pre>

而DispatcherServletAutoConfiguration中又做了很多事情, 比如配置了前端控制器

@Bean(name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet(WebMvcProperties webMvcProperties) {
    DispatcherServlet dispatcherServlet = new DispatcherServlet();
    dispatcherServlet.setDispatchOptionsRequest(webMvcProperties.isDispatchOptionsRequest());
    dispatcherServlet.setDispatchTraceRequest(webMvcProperties.isDispatchTraceRequest());
    dispatcherServlet.setThrowExceptionIfNoHandlerFound(webMvcProperties.
                                                        isThrowExceptionIfNoHandlerFound());
    dispatcherServlet.setPublishEvents(webMvcProperties.isPublishRequestHandledEvents());
    dispatcherServlet.setEnableLoggingRequestDetails(webMvcProperties.isLogRequestDetails());
    return dispatcherServlet;
}

總結:

@SpringBootApplication注解內部是3大注解功能的集成

  • @ComponentScan: 開啟組件掃描

  • @SpringBootConfiguration: 作用等同于@Configuration注解,也是用于標記配置類

  • @EnableAutoConfiguration: 內部導入AutoConfigurationImportSelector,該類中有個getCandidateConfigurations方法, 讀取jar包中META-INF/spring.factories文件中配置類, , 再根據條件進行加載和配置, 比如: AOP / PropertyPlaceholder / FreeMarker / HttpMessageConverter / Jackson / DataSource / DataSourceTransactionManager / DispatcherServlet / WebMvc 等等

問題5:沒有配置tomcat博烂,沒有設置端口服務器怎么來香椎,又怎么啟動的

SpringBoot使用嵌入式tomcat,編程實現(xiàn)禽篱,默認端口是8080畜伐,后續(xù)可以通過application.properties文件進行修改

image

問題6:main方法中SpringApplication.run(..)又是什么情況

SpringApplication.run(..)的作用:

  • 啟動SpringBoot應用

  • 加載自定義的配置類,完成自動配置功能

  • 把當前項目部署到嵌入的Tomcat服務器

  • 啟動Tomcat服務器跑項目

總結

SpringBoot項目完整結構

image

SpringBoot優(yōu)缺點

優(yōu)點:

  1. 創(chuàng)建獨立運行的Spring應用程序 ;

  2. 嵌入的Tomcat,無需部署war文件;

  3. 簡化Maven配置 ;

  4. 自動配置Spring ;

  5. 提供生產就緒型功能,如:日志,健康檢查和外部配置等;

  6. 不要求配置 XML;

  7. 非常容易和第三方框架集成起來。

缺點:

  1. 版本更新較快,可能出現(xiàn)較大變化;

  2. 因為約定大于配置,所以經常會出現(xiàn)一些很難解決的問題躺率。

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末玛界,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子悼吱,更是在濱河造成了極大的恐慌慎框,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件舆绎,死亡現(xiàn)場離奇詭異鲤脏,居然都是意外死亡,警方通過查閱死者的電腦和手機吕朵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門猎醇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人努溃,你說我怎么就攤上這事硫嘶。” “怎么了梧税?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵沦疾,是天一觀的道長。 經常有香客問我第队,道長哮塞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任凳谦,我火速辦了婚禮忆畅,結果婚禮上,老公的妹妹穿的比我還像新娘尸执。我一直安慰自己家凯,他們只是感情好缓醋,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著绊诲,像睡著了一般送粱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上掂之,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天抗俄,我揣著相機與錄音,去河邊找鬼世舰。 笑死橄镜,一個胖子當著我的面吹牛,可吹牛的內容都是我干的冯乘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼晒夹,長吁一口氣:“原來是場噩夢啊……” “哼裆馒!你這毒婦竟也來了?” 一聲冷哼從身側響起丐怯,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤喷好,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后读跷,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體梗搅,經...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年效览,在試婚紗的時候發(fā)現(xiàn)自己被綠了无切。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡丐枉,死狀恐怖哆键,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情瘦锹,我是刑警寧澤籍嘹,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站弯院,受9級特大地震影響辱士,放射性物質發(fā)生泄漏。R本人自食惡果不足惜听绳,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一颂碘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧辫红,春花似錦凭涂、人聲如沸祝辣。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蝙斜。三九已至,卻和暖如春澎胡,著一層夾襖步出監(jiān)牢的瞬間孕荠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工攻谁, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留稚伍,地道東北人。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓戚宦,卻偏偏與公主長得像个曙,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子受楼,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內容