大数据、Java EE 学习资料请关注 B 站:https://space.bilibili.com/204792350

SpringBoot 有关 Web 静态资源、模板引擎、自动配置相关解析

静态资源

关于静态资源的规则配置,有多种方式可以达成这种目标。

SpringBoot 默认的自动配置位置:*.autoconfigure.web.servlet.WebMvcAutoConfiguration.java 其中的 addResourceHandlers 方法;

可以通过配置文件来配置一些有关于静态资源的配置,配置前缀:spring.resource

@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties {
    // 。。。。。。
}

默认两种方式,一种是 webjars,另外一种是默认目录寻找静态资源。

webjars 方式

以 jar 的方式,来导入前端的一些依赖库。

  • 这种方式在 SpringBoot 有默认的寻址配置。
  • MVC 自动配置路径:*.autoconfigure.web.servlet.WebMvcAutoConfiguration.java
  • 其中有个方法:addResourceHandlers,就是配置了静态资源的规则

实际上,上面的默认规则是从 webjars/** 匹配到实际路径 META-INF/resources/webjars/**

如,可以通过 maven 来添加所需要的组件依赖

<dependency>
    <groupId>org.webjars</groupId>
    <artifactId>jquery</artifactId>
    <version>3.5.1</version>
</dependency>

然后,尝试访问:http://localhost:8080/webjars/jquery/3.5.1/jquery.js,若是没有情况出现,就可以正常访问。

webjars 组件包,可以从 https://www.webjars.org/ 网站下载;

默认静态资源路径

访问网站的 /** 路径下的静态资源,默认会在以下几个路径下寻找:

classpath:/META-INF/resources/
classpath:/resources/
classpath:/static/
classpath:/public/
/

classpath:类路径下,体现在项目中目录,就是默认创建的 resources 目录下。

当然,可以通过在配置文件中设置。

默认首页

SpringBoot 中,设置首页的方法有多种多样,其中可以通过以下几种设置首页。

  • 重写:addViewController 方法
  • 重写:addResourceHandlers 方法
  • 跳转
  • 重定向
  • 放在 /META-INF/resources/、/resources/、/static/、/public/ 会默认加载

addViewController

public class DefaultView extends WebMvcConfigurationSupport {
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/").setViewName("forward:index.html");
        registry.setOrder(Integer.MIN_VALUE);
        super.addViewControllers(registry);
    }
}

addResourceHandlers

@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/templates/**")
        .addResourceLocations("classpath:/templates/");
    super.addResourceHandlers(registry);
}

默认 ico

将 favicon.ico 放置在类路径下的:resourcese、static、public、MATE_INFO/resources 几个位置即可,这些位置是 SpringBoot 默认寻找的目录,可以通过 spring.resources.static-locations 配置项修改寻找位置,这是要给数组元素。

模板引擎

主流的模板引擎:freemaker、thymeleaf;

jsp 已经淘汰,剩下的就是一些老项目在使用。

在 SpringBoot 项目中,推荐使用 Thymeleaf,同时也提供了相应的 starter 场景,使用很简单,只要引入相应 starter 即可。

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

Thymeleaf 使用

该模板引擎本身有默认的配置,所以可以直接拆箱即用。

基础语法

在 HTML 标签上,添加 Thymeleaf 名称空间,方便提示语法;

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    // ......
</html>

thymeleaf 基础语法是从 th: 开头的,后面跟着特定名称。

作用在标签上,任意的属性都可以修改。

表达式

简单的表达式()

  • 变量表达式:${…}
    - 获取对象属性、调用对象方法
    - 使用内置对象
    - 使用内置工具对象

  • 选择变量表达式:*{…}

    • 功能上与 ${…} 重叠,在这基础上,增加了一个特性,如:
    <div th:object="${session.user}">
        <p>Name: <span th:text="*{firstName}">Sebastian</span>.</p>
        <p>Surname: <span th:text="*{lastName}">Pepper</span>.</p>
        <p>Nationality: <span th:text="*{nationality}">Saturn</span>.</p>
    </div>
    
    相当于 ${…} 的:
    
    <div>
        <p>Name: <span th:text="${session.user.firstName}">Sebastian</span>.</p>
        <p>Surname: <span th:text="${session.user.lastName}">Pepper</span>.</p>
        <p>Nationality: <span th:text="${session.user.nationality}">Saturn</span>.</p>
    </div>
    
  • 消息表达式:#{…}

    • 获取国际化
  • 链接URL表达式:@{…}

    • 对链接产生作用,如示例:
    <!-- 'http://localhost:8080/gtvg/order/details?orderId=3'-->
    <a href="details.html"
    th:href="@{http://localhost:8080/gtvg/order/details(orderId=${o.id})}">view</a>
    
    <!-- '/gtvg/order/details?orderId=3' -->
    <a href="details.html" th:href="@{/order/details(orderId=${o.id})}">view</a>
    
    <!-- '/gtvg/order/3/details' -->
    <a href="details.html" th:href="@{/order/{orderId}/details(orderId=${o.id})}">view</a>
    
    • 多个参数可以用 , 分割:@{/order/process(execId=${execId},execType='FAST')}
  • 片段表达式:~{…}

示例

${person.father.name}

${person['father']['name']}

${countriesByCode.ES}
${personsByName['Stephen Zucchini'].age}

${personsArray[0].name}

${person.createCompleteName()}
${person.createCompleteNameWithSeparator('-')}

字面量

  • 文本:'one text', 'Another one!',…
  • 整数:0 , 34 , 3.0 , 12.3 ,…
  • 布尔:true , false
  • null
  • 常量标记:one , sometext , main ,…

文本操作

  • 字符串连接:+
  • 文字替换:|The name is $|

算术运算

  • 二元操作符:+, -, *, /, %
  • 负号(一元运算符):-

布尔操作

  • 二元操作符:and , or
  • 布尔否定(一元运算符):! , not

对比与等式运算

  • 比较:>, <, >=, <=(gt, lt, ge, le)
  • 等式运算符:==, !=(eq, ne)

条件运算符

  • If-then:(if) ? (then)
  • If-then-else:(if) ? (then) : (else)
  • Default:(value) ?: (defaultvalue)

特殊的标记

  • 无操作:_

属性优先级

2020-05-22_163330

WebMvc 自动配置解析

Spring Boot 提供了现成的自动配置,无需另外配置。

自动配置在 Spring 的默认设置之上添加了以下特性:

  • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.

    • ContentNegotiatingViewResolver :组合全部试图解析器,定位到最适合的试图解析器来解析试图。由于该类会组合所有试图解析,所以自定义的试图解析器会被自动加载。
    • 该自动配置,会返回一个试图解析器,然后试图解析器会决定如何渲染试图,resolverViewName 重写该方法,可以定制解析逻辑。
    /**
    自定义试图解析器,会被 ContentNegotiatingViewResolver 自动组合。
    通过打断点,可以从 DispatcherSerlvet 的 doDispatcher 方法中,查看所有的试图解析器 viewResolver。
    */
    @Bean
    public ViewResolver MyResolver() {
        return new MyResolver();
    }
    public class MyResolver implements ViewResolver{
    
        @Override
        public View resolveViewName(String viewName, Locale locale) throws Exception {
            return null;
        }
    }
    
  • 支持为静态资源提供服务,包括支持WebJars (covered later in this document)).

  • Automatic registration of Converter, GenericConverter, and Formatter beans.

    • Converter:类型转换器
    • Formatter:格式化器
    /**
    自定义格式化器
    */
    @Bean
    public FormattingConversionService MyFormatter() {
        return new MyFormatterConversionService();
    }
    class MyFormatterConversionService extends FormattingConversionService {
    	// ......
    }
    
  • 支持 HttpMessageConverters (covered later in this document).

    • Http 请求与响应之间的转换,比如说:对象转 JSON,JSON 转对象。

    • 因为在容器中中所有的消息转换器都会被加载到列表中,所以同样可以自定义这类消息转换器,只要将其添加到容器中即可,例如:

      @Bean
      public HttpMessageConverters customConverters() {
          HttpMessageConverter<?> additional = ...
              HttpMessageConverter<?> another = ...
              return new HttpMessageConverters(additional, another);
      }
      
  • 自动注册 MessageCodesResolver (covered later in this document).

    • 定义校验导致的错误提示规则
  • 支持静态:index.html

  • 支持自定义 favicon.ico (covered later in this document).

  • ConfigurableWebBindingInitializer (covered later in this document).

    • Web 数据绑定,例如说:将请求的数据绑定到 JavaBean 中。

扩展自动配置

SpringBoot 对 SpringMVC 的自动配置的基础上,可以自定义扩展对 SpringMVC 的配置项,要做到这一点,只需要在一个普通类上加上:@Configuration 注解,然后是实现 WebMvcConfigurer 接口即可。

完成这一步,就可以对想要扩展的功能,重写相应的方法即可。

但是,需要注意一点,不需要 @EnableWebMvc,该注解是摒弃 SpringBoot 的自动配置的,交由用户全部自定义配置。

示例:

@SpringBootConfiguration
public class AdminConfiguration extends WebMvcConfigurationSupport {
    @Override
    protected void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/index").setViewName("index");
    }
}

简单的,给项目中添加一个控制器。

原理

SpringBoot 在加载默认的 WebMvc 自动配置的时候,会同时加载一个内部类:WebMvcAutoConfigurationAdapter,主要作用是该类的上面有一个注解:@Import(EnableWebMvcConfiguration.class)。

@Configuration(proxyBeanMethods = false)
@Import(EnableWebMvcConfiguration.class)
@EnableConfigurationProperties({ WebMvcProperties.class, ResourceProperties.class })
@Order(0)
public static class WebMvcAutoConfigurationAdapter implements WebMvcConfigurer {
    // ......
}

这个内部类本身是一个配置类存在,所以会被 SpringBoot 扫描。

通过导入 EnableWebMvcConfiguration 这个组件,该组件继承了一个配置类:DelegatingWebMvcConfiguration,这个类有一个 setConfigurers 方法,该方法会将所有的配置都加载。

/**
EnableWebMvcConfiguration 类
*/
@Configuration(proxyBeanMethods = false)
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
    // ......
}

/**
DelegatingWebMvcConfiguration 类
*/
@Configuration(proxyBeanMethods = false)
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

	private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();

	@Autowired(required = false)
	public void setConfigurers(List<WebMvcConfigurer> configurers) {
		if (!CollectionUtils.isEmpty(configurers)) {
			this.configurers.addWebMvcConfigurers(configurers);
		}
	}
    // 这个类的所有方法,几乎都是对不同的组件添加所有配置。
}

自定义配置(摒弃 SpringBoot 默认配置)

在 SpringBoot 中,提到一点,可以对 SpringBoot 中 SpringMVC 的配置扩展。但是,不能作用 @EnableWebMvc

给一个配置类加上这个注解:@EnableWebMvc,会触发 SpringBoot 中 SpringMVC 配置类的一个条件。

// ...... 省略
@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
// ...... 省略
public class WebMvcAutoConfiguration {
    // ......
}

@ConditionalOnMissingBean(WebMvcConfigurationSupport.class):表示若是容器中没有 WebMvcConfigurer 这个类,那么该配置类才会生效。

而在 @EnableWebMvc 这个注解中,会导入一个组件:DelegatingWebMvcConfiguration,该组件的父类正是:WebMvcConfigurationSupport

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}

所以,一旦加了 @EnableWebMvc,代表着所有的关于 SpringMVC 的配置都需要自己手动配置。

更改SpringBoot 默认自动配置

有两种方式:

  • SpringBoot 会判断容器中是否已有相应的组件,通常这些组件来自于用户自定义。在这种情况下,SpringBoot 会使用用户自定义的组件,而不是加载默认的自动配置。
    • 用户自定义配置的,如:@Bean,@Component,XML等等。
    • SpringBoot 允许多个组件的时候,会加载所有满足条件的组件。

注意

WebMvcConfigurationAdapter 过期替代产品

  • WebMvcConfigurationSupport 类:若是继承该类,代表着 SpringBoot 对 WebMVC 的自动配置全部摒弃。
  • WebMvcConfigurer 接口(推荐)

扩展

# Java   SpringBoot   Thymeleaf  

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×