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,帮助我们进行扩展配置.