終於,咱們的教程來到了SpringBoot核心功能的介紹。對於本章,各位讀者至少具有如下的知識:前端
對於一個簡單的maven結構的項目來講,如下結構:java
${basedir} |-- pom.xml |-- src |-- main |-- java || com.xxx.xxx 項目源碼 |-- resources || 項目配置文件 .xml等 |-- test |-- java |-- resources
在咱們前面的教程中,咱們都是在編寫着代碼,從未關注過maven的pom.xml到底是如何配置的,由於項目腳手架已經配置完成了,也許有細心的同窗已經看過了pom.xml文件的內容了:git
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- ... 省略了當前項目自己信息的配置,若有須要,請讀者查看源碼 --> <!-- 當前pom的父級 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.3</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <!-- springboot框架web功能starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- springboot框架的測試依賴starter --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <!-- 構建流程使用SpringBoot的maven插件 --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
對於一個普通的maven項目,其實核心的就是dependencies節點-dependency節點
了。經過dependency
節點,咱們能夠GAV座標(Group-Artifact-Version)引入不一樣的庫jar包,便於咱們的項目使用這些庫。github
那麼爲何在上面的pom出現了一個parent節點呢?實際上,pom容許所謂的繼承:咱們能夠把一堆的pom依賴和配置,放到一個公共的pom裏面,而後各個項目經過parent節點去引用這個公共的pom文件。因爲SpringBoot並非一個單一的jar包構成的框架,它的內部其實依賴了下面的核心庫:web
spring-core spring-beans spring-context ...還有不少
若是手動一項又一項編寫dependency來使用Spring框架,不只僅容易遺漏,並且十分不方便進行這些依賴庫的版本管理。基於此,SpringBoot官方提供了父級pom:spring
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.3</version> <!-- 2021/08/09最新 --> <relativePath/> <!-- lookup parent from repository --> </parent>
那麼再看咱們的pom文件中,還依賴了spring-boot-starter-web
,這又是什麼呢?難道有一個jar包叫作spring-boot-starter-web
嗎?其實否則。咱們上面提到了parent POM,可是Spring框架下的依賴包特別多,而且有些包是核心的包,有些包則是在某些功能須要的狀況下才依賴的包。若是一股腦的所有經過parent引入會讓你的項目依賴十分臃腫,因此Spring官方再次按照包的功能進行了必定的組合,造成了所謂的starter,若是你只是想作web API的服務開發,用spring-boot-starter-web
就能夠了,要是須要使用AOP(面向切面編程,做切面開發),加上spring-boot-starter-aop
依賴便可。apache
// 使用註解 @RestController,代表當前類是一個基於REST 規範的HTTP API Controller @RestController // @RequestMapping 註解放在Controller上,用於標記 HTTP url的路徑入口, // 例如 http://localhost:8080/hello/xxx 纔會進入當前Controller @RequestMapping("hello") public class HelloController { // @RequestMapping 註解放在Controller的裏面的方法上, // 將會與Controller上的RequestMapping組合成:"/hello/say" // method用於指示經過何種HTTP方法訪問 // 在程序啓動後,咱們可使用GET方法訪問:http://localhost:8080/hello/say @RequestMapping(value = "say", method = RequestMethod.GET) public String say() { return "hello, world"; } }
編寫啓動類,啓動咱們的SpringBoot程序:編程
@SpringBootApplication public class Chapter03App { public static void main(String[] args) { SpringApplication.run(Chapter03App.class, args); } }
啓動成功後,經過HTTP訪問:瀏覽器
http://localhost:8080/hello/say # 輸出:hello, world
上面的例子中,咱們使用註解@RestController
來標記了咱們的Controller類,會有初學者使用@Controller
來標記Controller,讓咱們改爲它試試:
@Controller // 改爲使用 @Controller註解,其餘不變,再次訪問,看看有什麼問題 @RequestMapping("hello") public class HelloController { // ... }
重啓啓動應用後再次訪問對應地址。若是是在瀏覽器中,你會看到:
Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback. Mon Aug 09 10:16:59 CST 2021 There was an unexpected error (type=Not Found, status=404).
type=Not Found, status=404
,404!爲何會這樣呢?
@Controller
標記,那麼將使用SpringMVC架構(自行了解),若是對應的方法返回的是字符串,則這個字符串代表須要查找對應的視圖(View)名稱,並將對應的視圖經過視圖解析器(InternalResourceViewResolver)解析修改成前端web頁面。@RestController
註解Controller,則Controller中的方法沒法返回jsp頁面,或者html,配置的視圖解析器不起做用,返回的內容就是return裏的內容。針對狀況1,解決方法就是在方法的返回上加上註解:@ResponseBody
:
@ResponseBody // 若是當前Controller被@Controller註解,又想返回字符串或其餘原始數據 @RequestMapping(value = "say", method = RequestMethod.GET) public String say() { return "hello, world"; }
在以前的文章,咱們已經介紹了SpringBoot是如何初始化Bean而且將其放在IOC容器的。咱們提到了三種方式:一、@Component
;二、Java配置類;三、XML配置。對於第二、3點,好像目前咱們的樣例中並無作手動配置的事情。那麼是否是咱們的Controller已經被@Component
標記了呢?
查看@RestController的定義:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Controller // 原來你RestController也是一個Controller註解啊! @ResponseBody // 而且,已經添加了@ResponseBody public @interface RestController { @AliasFor( annotation = Controller.class ) String value() default ""; }
@RestController
其實組合了@Controller
和@ResponseBody
兩個註解了。咱們再看看@Controller
的定義:
@Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component // 原來你Controller註解也組合了Component註解 public @interface Controller { @AliasFor( annotation = Component.class ) String value() default ""; }
原來@Controller
也已經組合了@Component
註解啊,難怪咱們的定義的Controller能被加載。
要回答這個問題,須要你有必定的關於Java Tomcat Web容器的知識。本系列主要是對SpringBoot的快速入門,不便於講的過細。簡單一點就是: