SpringBoot(四)——Web開發

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就能自動渲染

使用:

  1. 在src/main/resources/temeplates下創建html文件,導入thymeleaf的名稱空間(可以自動提示)
<html lang="en" xmlns:th="http://www.thymeleaf.org">
  1. 在Controller層設置數據
@Controller
public class HelloController {

    @RequestMapping("/success")
    public String success(Model model){
        model.addAttribute("title","success");
        model.addAttribute("info","this is thymeleaf");
        return "t";
    }
}

  1. 使用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})

DelegatingWebMvcConfigurationWebMvcConfigurationSupport的子類

我們再來看一下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 {
	...
}

@EnableWebMvcWebMvcConfigurationSupport組件導入進來,導入的WebMvcConfigurationSupport只提供SpringMVC最基本的功能。

7. 如何修改SpringBoot的默認配置

SpringBoot在自動配置很多組件的時候,先看容器中有沒有用戶自己配置的(@Bean、@Component),如果有,就使用用戶配置的,如果沒有,才自動配置;如果有些組件可以有多個(如ViewResolver),SpringBoot會將用戶配置的和自己默認的組合起來使用;

  • 在SpringBoot中會有非常多的xxxConfigurer幫助我們進行擴展配置
  • 在SpringBoot中會有很多的xxxCustomizer幫助我們進行定製配置

參考

SpringBoot 權威教程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章