avatar

SpringBoot集成SpriongMVC配置

简单迅速开发

SpringBoot主要的就是零配置,迅速开发,所以编写helloworld是很快的

  • 创建SpringBoot应用,选中我们需要的模块
  • SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置就可以运行起来
  • 自己编写业务逻辑

SpringBoot对静态资源的映射规则

SpringBoot中有一个类叫做WebMvcAutoConfiguration,里面有一个函数,是用来做资源映射规则的

@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties implements ResourceLoaderAware {
//可以设置和资源有关的参数,比如缓存时间等
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
Integer cachePeriod = this.resourceProperties.getCachePeriod();
if (!registry.hasMappingForPattern("/webjars/**")) {
customizeResourceHandlerRegistration(
registry.addResourceHandler("/webjars/**")
.addResourceLocations(
"classpath:/META-INF/resources/webjars/")
.setCachePeriod(cachePeriod));
}//staticPathPattern 是静态资源路径:"/**"
String staticPathPattern = this.mvcProperties.getStaticPathPattern();
if (!registry.hasMappingForPattern(staticPathPattern)) {
customizeResourceHandlerRegistration(
registry.addResourceHandler(staticPathPattern)
.addResourceLocations(
this.resourceProperties.getStaticLocations())
.setCachePeriod(cachePeriod));
}
}
//配置欢迎页映射
@Bean
public WelcomePageHandlerMapping welcomePageHandlerMapping(
ResourceProperties resourceProperties) {
return new WelcomePageHandlerMapping(resourceProperties.getWelcomePage(),
this.mvcProperties.getStaticPathPattern());
}
//配置自己的图标
@Configuration
@ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true)
public static class FaviconConfiguration {
private final ResourceProperties resourceProperties;
public FaviconConfiguration(ResourceProperties resourceProperties) {
this.resourceProperties = resourceProperties;
}
@Bean
public SimpleUrlHandlerMapping faviconHandlerMapping() {
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
//所有 **/favicon.ico与静态文件加做映射
mapping.setUrlMap(Collections.singletonMap("**/favicon.ico",
faviconRequestHandler()));
return mapping;
}
@Bean
public ResourceHttpRequestHandler faviconRequestHandler() {
ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();
requestHandler
.setLocations(this.resourceProperties.getFaviconLocations());
return requestHandler;
}
}
  • 1.所有webjars下面的所有请求都去classpath:/META-INF/resources/webjars/找资源
  • 2.如果要引入自己的静态资源文件,staticPathPattern:/**访问当前项目的任何资源
    • 这这几个文件夹就是静态资源的文件夹,classpath就是resource文件夹的路径.
      >"classpath:/META-INF/resources/",
      >"classpath:/resources/",
      >"classpath:/static/",
      >"classpath:/public/",
      >"/" :当前项目的根路径
  • 3.欢迎页:静态资源文件夹下的所有index.html;被/**映射
    • localhost:8080/ —->就会去静态资源文件夹下去找对应的欢迎页面
  • 4.所有的**/favicon.ico也是在静态文件夹底下去找
  • 5.这些所有的静态文件夹我们可以在配置文件中指定,不指定就去访问默认的配置
spring.resources.static-locations =classpath:/hello/,classpath:/zenshin/

如果在这里配置了,那么默认的配置就不生效了

模板引擎

什么是模板引擎:模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档。–百度百科

SpringBoot推荐的Thymeleaf

语法简单,功能强大

SpringBoot下使用

1.引入thymeleaf

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!--切换版本号-->
<properties>
<thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
<!--布局功能的支持程序 thymeleaf3主程序,适配layout2以上-->
<!--thymeleaf2主程序,适配layout1-->
<thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version>
</properties>

2.Thymeleaf使用&语法

官网有使用文档,文档

Thymeleaf使用

SpringBoot的关于Thymeleaf的配置信息都在ThymeleafProperties底下可以去进行配置

@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {

private static final Charset DEFAULT_ENCODING = Charset.forName("UTF-8");

private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html");

public static final String DEFAULT_PREFIX = "classpath:/templates/";

public static final String DEFAULT_SUFFIX = ".html";
//只要我们把html页面放在类路径下的templates,就能自动渲染了

controller里面应该这样写

@Controller//这里不能写ResponseBody ResponseBody会把返回值写到http的bady里面,这样就读不到返回的"success"找不到模板文件了
public class HelloController {

@RequestMapping("/success")
public String success(Map<String,Object> map)
{
//这里不能用RestController,因为这个会把返回值写到body就读不到值了
map.put("hello","你好");
return "Success";
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"> <!--导入Thymeleaf的名称空间:这样会有语法提示-->
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>成功</h1>
<!--th:text 将div里面的文本内容设置为-->
<div th:text="${hello}"></div>
</body>
</html>

这样在页面上就能返回success.html页面了,这也页面也是经过Thymeleaf渲染过的.
这里的hello就会解析成你好显示在界面上

Thymeleaf语法规则
th:标签

th:test->改变当前元素里面的文本内容
th:任意html属性–>来替换原生属性的值

2.能写哪些表达式
  • Simple expressions: (表达式语法)
    • Variable Expressions: ${…} : 获取变量值;使用OGNL
      1) 获取对象的属性,调用的方法;
      2) 使用内置的基本对象;例子在附录里面
      <img src="https://picture.zlh.giserhub.com/%E5%9F%BA%E6%9C%AC%E5%AF%B9%E8%B1%A1.png">
      3) 内置的工具对象
      <img src="https://picture.zlh.giserhub.com/Utility1.png">
      <img src="https://picture.zlh.giserhub.com/Utility2.png">
    • Selection Variable Expressions: *{…} : 变量的选择表达式
      1) 和${}在功能上是一样的,不过有一个补充功能,*号可以将代替上层变量,配合th:object进行使用的
      <img src="https://picture.zlh.giserhub.com/%E6%98%9F%E5%8F%B7.png">
    • Message Expressions: #{…}:获取国际化内容
    • Link URL Expressions: @{…} : 定义url链接
      @{/order/process(execId=${execId},execType='FAST')}
    • Fragment Expressions: ~{…}
      \<div th:insert="~{commons :: main}">...\</div> 后续会有说明
  • Literals(字面量)
    • Text literals: ‘one text’ , ‘Another one!’ ,…
    • Number literals: 0 , 34 , 3.0 , 12.3 ,…
    • Boolean literals: true , false
    • Null literal: null
    • Literal tokens: one , sometext , main ,…
  • Text operations:(文本操作)
    • String concatenation: +
    • Literal substitutions: |The name is ${name}|
  • Arithmetic operations:(数学运算)
    • Binary operators: + , - , * , / , %
    • Minus sign (unary operator): -
  • Boolean operations:(布尔运算)
    • Binary operators: and , or
    • Boolean negation (unary operator): ! , not
  • Comparisons and equality:(比较运算)
    • Comparators: > , < , >= , <= ( gt , lt , ge , le )
    • Equality operators: == , != ( eq , ne )
  • Conditional operators:(条件运算)支持三元运算符
    • If-then: (if) ? (then)
    • If-then-else: (if) ? (then) : (else)
    • Default: (value) ?: (defaultvalue)
  • Special tokens:(特殊操作)
    • No-Operation: _,表示无操作
  • Inlining
    • [[…]]: 代表 th:text 但是可以在标签对里面写
    • [(…)]: 代表 th:utext
例子
@RequestMapping("/success")
public String success(Map<String,Object> map)
{
map.put("hello","<h1>你好</h1>");
map.put("users", Arrays.asList("zhangsan","lisi","wangwu"));
return "Success";
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>成功</h1>
<!--th:text 将div里面的文本内容设置为-->
<div th:text="${hello}"></div>
<div th:utext="${hello}"></div>
<hr/>
<!--th:each每次遍历都会生成当前这个标签 ,三个h4-->
<h4 th:text="${user}" th:each="user : ${users}"></h4>
<hr/>
<h4>
<span th:each="user:${users}" >[[${user}]]</span>
</h4>
</body>
</html>

这样显示的效果就是进行遍历以及字符串输出

SpringMVC自动配置原理

使用SpringMVC框架

SpringMVC自动配置

SpringBoot已经自动配置好了SpringMVC
以下是SpringBoot对SpringMVC的默认配置:

  • Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
    • 自动配置了ViewResolver(视图解析器:根据方法的返回值得到视图对象(View),视图对象决定如何渲染(转发?重定向?))
    • ContentNegotiatingViewResolver:组合所有的视图解析器
    • 如何定制: 我们可以自己给容器添加一个视图解析器;自动的将其组合进来
  • Support for serving static resources, including support for WebJars (see below).
    • 静态资源文件夹路径,webjars
  • Automatic registration of Converter, GenericConverter, Formatter beans.//自动注册了这三个bean
    • Converter:转换器; 当前端请求进去方法时,会封装前端传过来的数据与方法参数反序列化,这时就会发生类型转换使用Converter
    • Formatter:格式化器;与Converter一样,如果日期类型如2017-01-01需要格式化成日期类型
        @Bean
      @ConditionalOnProperty(prefix = "spring.mvc", name = "date-format")//在配置文件中配置日期格式化规则,才去注册容器
      public Formatter<Date> dateFormatter() {
      return new DateFormatter(this.mvcProperties.getDateFormat());
      }
      @Override //添加转换器,直接从bean工厂找对应的类
      public void addFormatters(FormatterRegistry registry) {
      for (Converter<?, ?> converter : getBeansOfType(Converter.class)) {
      registry.addConverter(converter);
      }
      for (GenericConverter converter : getBeansOfType(GenericConverter.class)) {
      registry.addConverter(converter);
      }
      for (Formatter<?> formatter : getBeansOfType(Formatter.class)) {
      registry.addFormatter(formatter);
      }
      }
    • 自己添加的转换器格式化器,我们只需要放在容器中即可
  • Support for HttpMessageConverters (see below).
    • HttpMessageConverter:SpringMVC用来转换Http请求和相应的;
    • HttpMessageConverters: 是从容器中获取确定的,获取所有的HttpMessageConverter;
    • 自己添加的http消息转换器,我们只需要注册在容器中即可(@Bean,@component)
  • Automatic registration of MessageCodesResolver (see below).
    • 定义错误代码生成规则
  • Static index.html support.
    • 静态首页访问
  • Custom Favicon support (see below).
    • 支持图标
  • Automatic use of a ConfigurableWebBindingInitializer bean (see below).
    • 我们只需要配置一个ConfigurableWebBindingInitializer来替换掉默认的(添加到容器中)
    • 作用就是初始化web数据绑定器的
      @Override
      protected ConfigurableWebBindingInitializer getConfigurableWebBindingInitializer() {
      try {
      return this.beanFactory.getBean(ConfigurableWebBindingInitializer.class);//这里就意味着要从容器中取出ConfigurableWebBindingInitializer
      }
      catch (NoSuchBeanDefinitionException ex) {
      return super.getConfigurableWebBindingInitializer();
      }
      }

      关于SpringBoot集成SpringMVC的配置还有很多,都在org.springframework.boot.autoconfigure.web包中

      扩展SpringMVC

      <mvc:view‐controller path="/hello" viewname="success"/>
      <mvc:interceptors>
          <mvc:interceptor>
             <mvc:mapping path="/hello"/>
               <bean></bean>
          </mvc:interceptor>
      </mvc:interceptors>
      编写一个配置类(@Configuration),是WebMvcConfigurerAdapter类型;不能标注@EnableWebMvc;
      既保留了所有的自动配置,也能用户我们自己的扩展配置
      //使用WebMvcConfigurerAdapter可以扩展SpringMVC的功能
      @Configuration
      public class MyMVCconfig extends WebMvcConfigurerAdapter {
      @Override
      public void addViewControllers(ViewControllerRegistry registry) {
      //super.addViewControllers(registry);
      //浏览器发送/zenshin请求,来到success页面
      registry.addViewController("/zenshin").setViewName("success");
      }
      }

      原理

      • WebMvcAutoConfiguration是SpringMVC的自动配置类
      • 在做其他自动配置的时候会导入@Import(EnableWebMvcConfiguration.class)
      @Configuration
      public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration {


      @Configuration
      public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {

      private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();
      //从容器中获取所有的webMvcConfuigurer
      @Autowired(required = false)
      public void setConfigurers(List<WebMvcConfigurer> configurers) {
      if (!CollectionUtils.isEmpty(configurers)) {
      this.configurers.addWebMvcConfigurers(configurers);
      }
      }
      //一个参考实现;将所有的WebMvcConfigurer相关配置都来一起调用;      
      // public void addViewControllers(ViewControllerRegistry registry) {
      //    for (WebMvcConfigurer delegate : this.delegates) {
      //       delegate.addViewControllers(registry);
      //   }
      • 容器中所有的WebMvcConfigurer都会一起起作用;
      • 我们的配置类也会被调用;
        效果:SpringMVC的自动配置和我们的扩展配置都会起作用;

      全面接管SpringMVC

      SpringBoot对SpringMVC的自动配置不需要了,所有都是我们自己配置;所有的SpringMVC的自动配置都失效了
      ==我们需要在配置类中添加@EnableWebMvc即可;==

      //使用WebMvcConfigurerAdapter可以扩展SpringMVC的功能
      @EnableWebMvc
      @Configuration
      public class MyMVCconfig extends WebMvcConfigurerAdapter {
      @Override
      public void addViewControllers(ViewControllerRegistry registry) {
      //super.addViewControllers(registry);
      //浏览器发送/zenshin请求,来到success页面
      registry.addViewController("/zenshin").setViewName("success");
      }
      }

      原理

      为什么@EnableWebMvc自动配置就失效了;
      • @EnableWebMvc注解的核心就是导入了DelegatingWebMvcConfiguration
      @Import(DelegatingWebMvcConfiguration.class)
      public @interface EnableWebMvc {
      }
      • DelegatingWebMvcConfiguration继承自WebMvcConfigurationSupport
      @Configuration
      public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
      • WebMvcAutoConfiguration自动配置类中有一个ConditionalOnMissingBean注解,WebMvcConfigurationSupport这个类不在容器中自动配置就生效
      @Configuration
      @ConditionalOnWebApplication
      @ConditionalOnClass({ Servlet.class, DispatcherServlet.class,
      WebMvcConfigurerAdapter.class })
      //容器中没有这个组件的时候,自动配置生效
      @ConditionalOnMissingBean(WebMvcConfigurationSupport.class)
      @AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
      @AutoConfigureAfter({ DispatcherServletAutoConfiguration.class,
      ValidationAutoConfiguration.class })
      public class WebMvcAutoConfiguration {
      • @EnableWebMvc将WebMvcConfigurationSupport组件导进来了
      • 导入的WebMvcConfigurationSupport只有基本SpringMVC的基本功能

      如何修改SpringBoot的默认配置

      模式:

      • SpringBoot在自动配置很多组件的时候,先看容器中有没有用户自己配置的(@Bean、@Component)如果有就用用户配置的,如果没有,才自动配置;如果有些组件可以有多个(ViewResolver)将用户配置的和自己默认的组合起来;
      • 在SpringBoot中会有非常多的xxxConfigurer帮助我们进行扩展配置
      • 在SpringBoot中会有很多的xxxCustomizer帮助我们进行定制配置
文章作者: zenshin
文章链接: https://zlh.giserhub.com/2020/03/30/springboot/springmvc/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 zenshin's blog
打赏
  • 微信
    微信
  • 支付宝
    支付宝

评论