SpringBoot(四) -- SpringBoot与Web开发

一.发开前准备
  1.创建一个SpringBoot应用,引入我们需要的模块
  2.SpringBoot已经默认将这些场景配置好了,只需要在配置文件中指定少量配置,就能运行起来
  3.编写业务代码

二.静态资源映射规则
  在WebMvcAutoConfiguration中有着如下的配置:

 1      @Override
 2         public void addResourceHandlers(ResourceHandlerRegistry registry) {
 3             if (!this.resourceProperties.isAddMappings()) {
 4                 logger.debug("Default resource handling disabled");
 5                 return;
 6             }
 7             Integer cachePeriod = this.resourceProperties.getCachePeriod();
 8             if (!registry.hasMappingForPattern("/webjars/**")) {
 9                 customizeResourceHandlerRegistration(
10                         registry.addResourceHandler("/webjars/**")
11                                 .addResourceLocations(
12                                         "classpath:/META-INF/resources/webjars/")
13                         .setCachePeriod(cachePeriod));
14             }
15             String staticPathPattern = this.mvcProperties.getStaticPathPattern();
16             if (!registry.hasMappingForPattern(staticPathPattern)) {
17                 customizeResourceHandlerRegistration(
18                         registry.addResourceHandler(staticPathPattern)
19                                 .addResourceLocations(
20                                         this.resourceProperties.getStaticLocations())
21                         .setCachePeriod(cachePeriod));
22             }
23         }

  1.webjars:以jar包的方式引入静态资源,可以将JQuery等前端框架使用maven依赖的形式引入进来
  2.webjars中的资源访问都去如下路径:  classpath:/META-INF/resources/webjars/
  --例如可以在该地址中找到JQuery: localhost:8080/webjars/jquery/3.3.1/jquery.js

 

1         <!--前端框架-->
2         <dependency>
3             <groupId>org.webjars</groupId>
4             <artifactId>jquery</artifactId>
5             <version>3.3.1</version>
6         </dependency>

  --在访问的时候只要写webjars下面资源的地址即可
  3.我们可以发现在addResourceHandlers()方法只,还为这些静态资源设置了缓存时间,而我们在ResourceProperties中设置缓存时间:

1 @ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
2 public class ResourceProperties implements ResourceLoaderAware {
3 }

  4.在spring.resources中我们可以设置静态资源相关的参数,例如缓存时间,回到方法中我们在 registry.addResourceHandler(staticPathPattern) 中设置了资源映射:private String staticPathPattern = "/**";而如果我们不进行配置,则会默认去如下地址中寻找:
    "classpath:/META-INF/resources/"
    "classpath:/static/"
    "classpath:/static/"
    "/**":当前项目的根路径.
  5.欢迎页的映射

1         @Bean
2         public WelcomePageHandlerMapping welcomePageHandlerMapping(
3                 ResourceProperties resourceProperties) {
4             return new WelcomePageHandlerMapping(resourceProperties.getWelcomePage(),
5                     this.mvcProperties.getStaticPathPattern());
6         }
 1     private String[] getStaticWelcomePageLocations() {
 2         String[] result = new String[this.staticLocations.length];
 3         for (int i = 0; i < result.length; i++) {
 4             String location = this.staticLocations[i];
 5             if (!location.endsWith("/")) {
 6                 location = location + "/";
 7             }
 8             result[i] = location + "index.html";
 9         }
10         return result;
11     }  

  --即所有静态目录下的index.html页面
  6.设置我们的首页图标

 1         @ConditionalOnProperty(value = "spring.mvc.favicon.enabled", matchIfMissing = true)
 2         public static class FaviconConfiguration {
 3 
 4             private final ResourceProperties resourceProperties;
 5 
 6             public FaviconConfiguration(ResourceProperties resourceProperties) {
 7                 this.resourceProperties = resourceProperties;
 8             }
 9 
10             @Bean
11             public SimpleUrlHandlerMapping faviconHandlerMapping() {
12                 SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
13                 mapping.setOrder(Ordered.HIGHEST_PRECEDENCE + 1);
14                 mapping.setUrlMap(Collections.singletonMap("**/favicon.ico",
15                         faviconRequestHandler()));
16                 return mapping;
17             }
18 
19             @Bean
20             public ResourceHttpRequestHandler faviconRequestHandler() {
21                 ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler();
22                 requestHandler
23                         .setLocations(this.resourceProperties.getFaviconLocations());
24                 return requestHandler;
25             }
26 
27         }

  在静态资源文件夹中寻找favicon.ico

三.引入thymeleaf
  在我们传统的网页开发中,通常我们会将静态网站资源修改为.jsp文件,但是我们使用springBoot默认的打包方式是jar包,我们使用的还是嵌入式的tomcat,因此默认是不支持JSP的页面的.如果我们使用纯静态的方式给我们开发会带来很大的麻烦,因此我们可以使用模板引擎例如JSP,Velocity,Freemarker,Thymeleaf;Spring推荐我们使用thymeleaf:
  1.引入ThymeLeaf:

1         <!--引入Thymeleaf-->
2         <dependency>
3             <groupId>org.springframework.boot</groupId>
4             <artifactId>spring-boot-starter-thymeleaf</artifactId>
5         </dependency>

   2.其默认使用的2.1.6版本,其功能较少,因此我们可以使用替换较高的版本:

1     <properties>
2         <java.version>1.8</java.version>
3         <!--设置thymeleaf版本-->
4         <thymeleaf.version>3.0.2.RELEASE</thymeleaf.version>
5         <!--thymeleaf布局功能的支持程序  thymeleaf3 主程序 适配layout2 以上版本-->
6         <thymeleag-layout-dialect.version>2.1.1</thymeleag-layout-dialect.version>
7     </properties>

 

四.Thymeleaf使用&语法

 1 @ConfigurationProperties(prefix = "spring.thymeleaf")
 2 public class ThymeleafProperties {
 3 
 4     private static final Charset DEFAULT_ENCODING = Charset.forName("UTF-8");
 5 
 6     private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html");
 7 
 8     public static final String DEFAULT_PREFIX = "classpath:/templates/";
 9 
10     public static final String DEFAULT_SUFFIX = ".html";

  可以发现我们只需要将html页面放置在类路径的templates下,就可以被顺利解析扩展.
  1.访问success页面:

1     @RequestMapping("/success")
2     public String success(Map<String, Object> map) {
3         map.put("hello", "你好");
4         return "success";
5     }
 1 <!DOCTYPE html>
 2 <html lang="en">
 3     <head>
 4         <meta charset="UTF-8">
 5         <title>Title</title>
 6     </head>
 7     <body>
 8         <h1>成功!!!</h1>
 9     </body>
10 </html>

  2.在success中引入Thymeleaf模板引擎--导入名称空间:<html lang="en" xmlns:th="http://www.thymeleaf.org">
  3.Themeleaf语法:

 1 <!DOCTYPE html>
 2 <html lang="en" xmlns:th="http://www.thymeleaf.org">
 3     <head>
 4         <meta charset="UTF-8">
 5         <title>Title</title>
 6     </head>
 7     <body>
 8         <h1>成功!!!</h1>
 9         <!--获取Hello的值 th:text="${hello}"
10         如果模板引擎解析时效,或者hello的值获取失败,那么将显示当前自行填充的默认值-->
11         <div th:text="${hello}">这是显示欢迎信息</div>
12     </body>
13 </html>

  (1) th:text:改变当前元素里面的文本内容
    th:任意html标签属性: 我们可以用任何属性替换掉原生的值
  (2)th:insert th:replace: 片段包含,类似于jsp:include
  (3)th:each :遍历
  (4)th: if | unless | switch | case:判断
  (5)th:object th:with: 设置变量
  (6)th: attr | attrprepend | attrappend : 任意属性修改,支持在前方和后方追加内容
  (7)th: value | href | src | ...:修改指定属性的默认值
  (8)th: text | utext | fragment | remove: 文本转义特殊字符 | 文本不转义特殊字符 | 声明片段 | 移除片段
  4.Thymeleaf表达式语法:
  (1)${...} :获取变量值,获取对象的属性,调用方法; 使用内置的基本对象:  
      #ctx: 当前的上下文对象
      #vars: 当前上下文的变量
      #locale: 获取上下文的区域信息
      #request | response | session | servletContext: 应用于web环境
      内置工具对象(详情可以参看文档):
      #execInfo: information about the template being processed.
      #messages: methods for obtaining externalized messages inside variables expressions, in the same way as they would be obtained using #{…} syntax.
      #uris: methods for escaping parts of URLs/URIs

      #conversions: methods for executing the configured conversion service (if any).
      #dates: methods for java.util.Date objects: formatting, component extraction, etc.
      #calendars: analogous to #dates, but for java.util.Calendar objects.
      #numbers: methods for formatting numeric objects.
      #strings: methods for String objects: contains, startsWith, prepending/appending, etc.
      #objects: methods for objects in general.
      #bools: methods for boolean evaluation.
      #arrays: methods for arrays.
      #lists: methods for lists.
      #sets: methods for sets.
      #maps: methods for maps.
      #aggregates: methods for creating aggregates on arrays or collections.
      #ids: methods for dealing with id attributes that might be repeated (for example, as a result of an iteration).

  (2)*{...}: 和${...}在功能上是一样的   th:object 进行使用,在子标签中可以省略object的前缀

  (3) #{...}: 获取国际化命名

  (4)@{...}:定义URL  可以免去拼串 https:localhost/hello/hi(order=${order},item=${item})
  (5)~{...}: 片段引用表达式 (后文将会介绍使用方法)
  5.场景应用示例

1     @RequestMapping("/success")
2     public String success(Map<String, Object> map) {
3         map.put("hello", "<h1>你好</hi>");
4         map.put("users", Arrays.asList("张三","李四","王五"));
5         return "success";
6     }
 1 <!DOCTYPE html>
 2 <html lang="en" xmlns:th="http://www.thymeleaf.org">
 3     <head>
 4         <meta charset="UTF-8">
 5         <title>Title</title>
 6     </head>
 7     <body>
 8         <h1>成功!!!</h1>
 9         <!--获取Hello的值 th:text="${hello}"
10         如果模板引擎解析时效,或者hello的值获取失败,那么将显示当前自行填充的默认值-->
11         <div th:text="${hello}">这是显示欢迎信息</div>
12         <hr/>
13         <div th:utext="${hello}">默认显示的内容</div>
14         <hr/>
15         <!--遍历获取数组数据
16         th:each 所在的标签,每次遍历都是生成一个-->
17         <h4 th:each="user:${users}" th:text="${user}"></h4>
18         <hr/>
19         <h4>
20             <!--行内写法[[ text ]]   [( utext )]-->
21             <span th:each="user:${users}" >[[ ${user} ]]</span>
22         </h4>
23     </body>
24 </html>

 五.SpringMVC的自动配置
  SpringBoot自动配置好了SpringMVC,以下是SpringBoot对SpringMVC的自动配置

   1.自动配置了视图解析器:根据方法的返回值,得到视图对象,视图对象决定如何渲染界面(转发?重定向?)

    ContentNegotiatingViewResolver:组合所有的视图解析器
    如何定制:可以自己给容器中添加视图解析器,而后ContentNegotiatingViewResolver将会自动的将其组合进来
  2.静态首页访问
  3.自动注册了Converter(转化器): 主要完成类型转化
   formatter(格式化器):页面带来的数据例如为 2019-12-1 ==> Date类型

1 @Bean
2         @ConditionalOnProperty(prefix = "spring.mvc", name = "date-format")
3         public Formatter<Date> dateFormatter() {
4             return new DateFormatter(this.mvcProperties.getDateFormat());
5         }

   --需要在配置文件中配置日期格式化的规则
  4.HttpMessageConverter:SpringMVC中用来转化HTTP请求及响应,User-JSON
   HttpMessageConverters:是从容器中确定的;自己给容器中添加HttpMessageConverter,只需自己在容器中注册
  5.MessageCodesResolver:定义错误代码的生成规则
  6.ConfigurableWebBindingInitializer:我们可以配置自己的来替原有的,用来初始化Web数据绑定器的
  7.修改SpringBoot的默认配置:SpringBoot在自动配置很多组件的时候,都有一个模式,先看容器中有没有用户自己配置的(@Bean,@Component)如果有就用用户配置的,如果没有才自动配置;如果有些组件可以有多个(ViewResolver)将用户配置的和自己默认的组合起来;

六.扩展和全面接管SpringMVC
  仅仅依赖SpringBoot对SpringMVC的默认配置,是不够使用的,例如我们在SpringMVC的配置文件中可以如下使用:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
 4        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
 5 
 6     <!--将Hello请求也映射到success-->
 7     <mvc:view-controller path="/hello" view-name="success"/>
 8     <!--配置拦截器-->
 9     <mvc:interceptors>
10         <!--拦截hello请求-->
11         <mvc:interceptor>
12             <mvc:mapping path="/hello"/>
13             <bean></bean>
14         </mvc:interceptor>
15     </mvc:interceptors>
16 </beans>

   --如果我们想要保持SpringBoot对SpringMVC的默认配置,仅仅是想额外添加一些功能,我们可以添加一个自定义的Configuration配置类:

   1.编写一个配置类(@Configuration),是WebMvcConfigurerAdapter类型,不能标注@EnableWebMvc:

 1 package com.zhiyun.springboot.web_restfulcrud.config;
 2 
 3 import org.springframework.context.annotation.Configuration;
 4 import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
 5 import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
 6 
 7 /**
 8  * @author : S K Y
 9  * @version :0.0.1
10  * 扩展SpringMVC的功能
11  */
12 @Configuration
13 public class MyMvcConfig extends WebMvcConfigurerAdapter {
14     @Override
15     public void addViewControllers(ViewControllerRegistry registry) {
16         //浏览器发送hello请求也来到success页面
17         registry.addViewController("/hello").setViewName("success");
18     }
19 }

  --即保留了所有的自动配置,也能使用我们扩展的自定义配置,查看其原理:
  (1)WebMvcAutoConfiguration是SpringMVC的自动配置类;
  (2)内部有一个静态类也继承了WebMvcConfigurerAdapter ,在该类上有着注解@Import(EnableWebMvcConfiguration.class)
  (3)EnableWebMvcConfiguration类继承了DelegatingWebMvcConfiguration类,在父类中存在如下代码:

1     @Autowired(required = false)
2     public void setConfigurers(List<WebMvcConfigurer> configurers) {
3         if (!CollectionUtils.isEmpty(configurers)) {
4             this.configurers.addWebMvcConfigurers(configurers);
5         }
6     }

   (4)表示了从容器中获取所有的WebMvnConfigurer.在进行配置将所有的WebMVC相关的配置都调用了一下,这样一来就可以实现一起配置.所有的容器中所有的WebMvcConfige都会一起起作用,我们的配置类也会被调用.SpringMVC的自动配置和我们的扩展配置都回起作用.
  (5)全面接管SpringMVC:SpringBoot对SpringBoot的自动配置将不再生效,我们使用@EnableWebMVC注解来标注我们自己的配置类即可.此时所有SpringMVC的自动配置都失效.  
  (6)EnableWebMVC注解导入了一个DelegatingWebMvcConfiguration类该是WebMvcConfigurationSupport的子类,而在WebMvcAutoConfiguration类中使用了@ConditionalOnMissingBean(WebMvcConfigurationSupport.class)注解,表示当容器中没有这个组件的时候,这样一来自动配置类才生效.
  (7)在SpringBoot中会有许多的XXXConfigurer,帮助我们进行扩展配置.

posted @ 2019-12-01 13:06  灰色天空_graySky  阅读(268)  评论(0编辑  收藏  举报