SpringBoot系列文章
文章目錄
1. 簡介
使用SpringBoot進行Web開發的大致流程
- 創建SpringBoot應用,選中我們需要的模塊
- SpringBoot已經默認將這些場景配置好了,只需要在配置文件中指定少量配置就可以運行起來
- 編寫業務代碼
2. SpringBoot對靜態資源的映射規則
WebMvcAutoConfiguration類的addResourceHandlers方法:(添加資源映射)
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
} else {
Duration cachePeriod = this.resourceProperties.getCache().getPeriod();
CacheControl cacheControl = this.resourceProperties.getCache().getCachecontrol().toHttpCacheControl();
if (!registry.hasMappingForPattern("/webjars/**")) {
this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{"/webjars/**"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/webjars/"}).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
this.customizeResourceHandlerRegistration(registry.addResourceHandler(new String[]{staticPathPattern}).addResourceLocations(WebMvcAutoConfiguration.getResourceLocations(this.resourceProperties.getStaticLocations())).setCachePeriod(this.getSeconds(cachePeriod)).setCacheControl(cacheControl));
}
}
}
2.1 訪問webjars資源
所有 /webjars/**的請求,SpringBoot都去classpath:/META-INF/resources/webjars/
下找資源
webjars:以jar包的形式引入的靜態資源,前端框架可以去webars官網去找對應的maven依賴。
例如:添加jquery的webjars
訪問地址對應就是:http://localhost:8080/webjars/jquery/3.4.1/jquery.js
2.2 訪問自己的靜態資源
@ConfigurationProperties( //說明可以在配置文件中配置相關參數
prefix = "spring.resources",
ignoreUnknownFields = false
)
public class ResourceProperties {
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = new String[]{"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/"};
private String[] staticLocations;
private boolean addMappings;
private final ResourceProperties.Chain chain;
private final ResourceProperties.Cache cache;
public ResourceProperties() {
this.staticLocations = CLASSPATH_RESOURCE_LOCATIONS;
上圖中添加的映射訪問路徑staticPathPattern值是/**,對應的資源文件夾就是上面配置類ResourceProperties中的CLASSPATH_RESOURCE_LOCATIONS數組中的文件夾:
數組中的值 | 對應項目中的位置 |
---|---|
classpath:/META-INF/resources/ | src/main/resources/META-INF/resources/ |
classpath:/resources/ | src/main/resources/resources/ |
classpath:/static/ | src/main/resources/static/ |
classpath:/public/ | src/main/resources/public/ |
如果訪問localhost:8080/abc,SpringBoot就會去這些靜態資源文件夾中找abc的文件,也就是說,當請求地址是/**類型的,如果沒有處理,SpringBoot默認會去上面的那些文件夾中尋找資源。
2.3 歡迎頁映射
location就是靜態資源路徑,所以歡迎頁的頁面就是上面靜態資源文件夾下的index.html,被/**映射,因此直接訪問項目就是訪問歡迎頁。
2.4 網站圖標映射
所有的 favicon.ico 都是在靜態資源文件下找
可以在配置文件中使用spring.resources.staticLocations,來改變靜態資源文件夾的路徑。
3. 模板引擎
常見的模板引擎有JSP、Velocity、Freemarker、Thymeleaf
SpringBoot推薦使用Thymeleaf;
3.1 引入模板引擎thymeleaf
<!--引入模板引擎thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
3.2 thymeleaf 的使用
@ConfigurationProperties(
prefix = "spring.thymeleaf"
)
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
private boolean checkTemplate = true;
private boolean checkTemplateLocation = true;
private String prefix = "classpath:/templates/";
private String suffix = ".html";
private String mode = "HTML";
private Charset encoding;
private boolean cache;
...
只要我們把HTML頁面放在classpath:/templates/
,thymeleaf就能自動渲染
使用:
- 在src/main/resources/temeplates下創建html文件,導入thymeleaf的名稱空間(可以自動提示)
<html lang="en" xmlns:th="http://www.thymeleaf.org">
- 在Controller層設置數據
@Controller
public class HelloController {
@RequestMapping("/success")
public String success(Model model){
model.addAttribute("title","success");
model.addAttribute("info","this is thymeleaf");
return "t";
}
}
- 使用thymeleaf語法(t.html)
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${title}"></h1>
<span th:text="${info}">這裏的文本將會被覆蓋</span>
</body>
</html>
3.3 thymeleaf 語法規則
- th:text :改變當前元素(標籤)裏面的文本內容,如果有特殊字符,不會轉譯,直接輸出,用在標籤裏面。
- th:utext: 也是改變當前標籤裏面的文本內容,如果有特殊字符,會轉譯,不會直接輸出,用在標籤裏面。
- th:任意html屬性,替換原生屬性的值
具體用法可以參考官方文檔attribute-precedence
表達式:
- ${…} 獲取變量值,OGNL
- 獲取對象的屬性、調用方法
- 使用內置的基本對象和工具對象
- {…} 選擇表達式,和${}功能一樣,不一樣的是可以用代替對象
- #{…}:獲取國際化內容
- @{…}:定義URL
具體用法可以 參考官方文檔Standard Expression
4. SpringMVC配置
Spring Boot爲Spring MVC提供了自動配置,可與大多數應用程序完美配合。
想要看SpringBoot中對SpringMvc的默認配置,可以查看官方文檔,也可以看SpringMVC的自動配置類org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
以下是springboot對SpringMVC的默認配置(官方文檔中的介紹)
- 包含ContentNegotiatingViewResolver和BeanNameViewResolver。–> 視圖解析器
- 支持服務靜態資源,包括對WebJars的支持。–> 靜態資源文件夾路徑
- 自動註冊Converter,GenericConverter和Formatterbeans。–> 轉換器,格式化器
- 支持HttpMessageConverters)。–> SpringMVC用來轉換Http請求和響應的;User—Json;
- 自動註冊MessageCodesResolver)。–> 定義錯誤代碼生成規則
- 靜態index.html支持。–> 靜態首頁訪問
- 定製Favicon支持。–> 網站圖標
- 自動使用ConfigurableWebBindingInitializerbean。
4.1 視圖解析器
視圖解析器:根據方法的返回值得到視圖對象(View),視圖對象決定如何渲染(轉發或重定向)
- 自動配置了ViewResolver,ContentNegotiatingViewResolver,組合所有的視圖解析器
視圖解析器從哪裏來的?
所以我們可以自己給容器中添加一個視圖解析器,ContentNegotiatingViewResolver會自動的將其組合進來
使用debug檢驗
4.2 轉換器、格式化器
- Converter:轉換器,比如頁面中的發過來的消息都是String類型的,轉換器可以轉換成java類型。
- Formatter 格式化器; 比如將日期轉換成Date類型,2017.12.17===Date;
@Bean
//在配置文件中配置日期格式化的規則,就會註冊這個日期格式化組件
@ConditionalOnProperty(prefix = "spring.mvc", name = "date-format")
public Formatter<Date> dateFormatter() {
return new DateFormatter(this.mvcProperties.getDateFormat());//日期格式化組件
}
自己添加的格式化器轉換器,我們只需要放在容器中即可
public void addFormatters(FormatterRegistry registry) {
ApplicationConversionService.addBeans(registry, this.beanFactory);
}
4.3 HttpMessageConverters
- HttpMessageConverter:SpringMVC用來轉換Http請求和響應的,比如將數據轉換成json格式。
- HttpMessageConverters 是從容器中確定,獲取所有的HttpMessageConverter;
自己給容器中添加HttpMessageConverter,只需要將自己的組件註冊容器中(@Bean,@Component)
4.4 MessageCodesResolver
定義錯誤代碼生成規則
4.5 ConfigurableWebBindingInitializer
初始化WebDataBinder(Web數據綁定器:將請求數據與javaBean綁定),我們可以配置一個ConfigurableWebBindingInitializer來替換默認的(添加到容器)
上面是SpringBoot中對SpringMVC的自動配置,還有其他的web自動配置,可以在org.springframework.boot.autoconfigure.web
下看SpringBoot對web的其他自動配置。
5. 擴展SpringMVC
如果您想保留 Spring Boot MVC 的功能,並且需要添加其他 MVC 配置(攔截器,格式化程序和視圖控制器等),可以添加自己的 WebMvcConfigurer 類型的 @Configuration 類,但不能帶 @EnableWebMvc 註解。如果您想自定義 RequestMappingHandlerMapping、RequestMappingHandlerAdapter 或者 ExceptionHandlerExceptionResolver 實例,可以聲明一個 WebMvcRegistrationsAdapter 實例來提供這些組件。
如果您想完全掌控 Spring MVC,可以添加自定義註解了 @EnableWebMvc 的 @Configuration 配置類。
以前在SpringMVC中,可以配置
<mvc:view-controller path="/hello" view-name="success"/>
當收到hello請求時,返回success頁面。
現在,編寫一個配置類(使用@Configuration標註),是WebMvcConfigurer類型,不能標註@EnableWebMvc
//使用WebMvcConfigurerAdapter可以來擴展SpringMVC的功能 ,實現WebMvcConfigurer接口
@Configuration
public class MyMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//收到hi請求,返回t頁面,也就是將t.html交給模板引擎渲染
registry.addViewController("/hi").setViewName("t");
}
}
5.1 原理
我們知道WebMvcAutoConfiguration是SpringMVC的自動配置類
下面這個類是WebMvcAutoConfiguration
中的一個內部類
看一下@Import({WebMvcAutoConfiguration.EnableWebMvcConfiguration.class})
中的這個類,
這個類依舊是WebMvcAutoConfiguration中的一個內部類
重點看一下這個類繼承的父類DelegatingWebMvcConfiguration
@Configuration(
proxyBeanMethods = false
)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
public DelegatingWebMvcConfiguration() {
}
@Autowired(required = false) //使用@Autowired,默認從容器中獲取configurers
//將容器中所有的WebMvcConfigurer存到this.configurers中
public void setConfigurers(List<WebMvcConfigurer> configurers) {
if (!CollectionUtils.isEmpty(configurers)) {
this.configurers.addWebMvcConfigurers(configurers);
}
}
...
/* 拿這個類中的addViewControllers方法舉例
this.configurers:也是WebMvcConfigurer接口的一個實現類
*/
protected void addViewControllers(ViewControllerRegistry registry) {
this.configurers.addViewControllers(registry);
}
this.configurers.addViewControllers(registry),遍歷所有的WebMvcConfigurer,並且都執行addViewControllers(registry)
public void addViewControllers(ViewControllerRegistry registry) {
Iterator var2 = this.delegates.iterator();
while(var2.hasNext()) {
WebMvcConfigurer delegate = (WebMvcConfigurer)var2.next();
delegate.addViewControllers(registry);
}
}
delegate.addViewControllers(registry),調用WebMvcConfigurer接口中的 addViewControllers方法,也就是調用WebMvcConfigurer實現類的方法,實現擴展功能。
default void addViewControllers(ViewControllerRegistry registry) {
}
容器中所有的WebMvcConfigurer
都會一起起作用;
我們的配置類也會被調用;
效果:SpringMVC的自動配置和我們的擴展配置都會起作用;
6. 全面接管SpringMVC
我們只需要在配置類中添加 @EnableWebMvc
即可,所有的SpringMVC的自動配置都會失效,都要收動配置。
@Configuration
@EnableWebMvc
public class MyMvcConfig implements WebMvcConfigurer
6.1 原理
爲什麼使用了@EnableWebMvc
註解之後,springMVC的自動配置就失效了
我們看一下EnableWebMvc註解類
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
//主要是註冊了DelegatingWebMvcConfiguration類
@Import({DelegatingWebMvcConfiguration.class})
public @interface EnableWebMvc {
}
重點在於 @Import({DelegatingWebMvcConfiguration.class})
DelegatingWebMvcConfiguration
是WebMvcConfigurationSupport
的子類
我們再來看一下springmvc的自動配置類WebMvcAutoConfiguration
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnWebApplication(
type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
//重點是這個註解,只有容器中沒有WebMvcConfigurationSupport類型的bean時,
//纔會將WebMvcAutoConfiguration 註冊到容器中,自動配置纔會生效
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, TaskExecutionAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {
...
}
@EnableWebMvc
將WebMvcConfigurationSupport
組件導入進來,導入的WebMvcConfigurationSupport只提供SpringMVC最基本的功能。
7. 如何修改SpringBoot的默認配置
SpringBoot在自動配置很多組件的時候,先看容器中有沒有用戶自己配置的(@Bean、@Component),如果有,就使用用戶配置的,如果沒有,才自動配置;如果有些組件可以有多個(如ViewResolver),SpringBoot會將用戶配置的和自己默認的組合起來使用;
- 在SpringBoot中會有非常多的xxxConfigurer幫助我們進行擴展配置
- 在SpringBoot中會有很多的xxxCustomizer幫助我們進行定製配置
參考