7.springboot web开发
7.springboot web开发
- xxxxAutoConfiguration:帮我们给容器中自动配置组件
- xxxxProperties:配置类来封装配置文件的内容
7.1静态资源的映射规则
1.加载webjars目录下资源
我们springboot项目打包以<packaging>jar</packaging>
包形式,以前我们是将静态资源保存在webapp
目录下,现在我们以jar
包方式如何引入静态资源呢?
public class WebMvcAutoConfiguration { @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)); } String staticPathPattern = this.mvcProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { customizeResourceHandlerRegistration( registry.addResourceHandler(staticPathPattern) .addResourceLocations( this.resourceProperties.getStaticLocations()) .setCachePeriod(cachePeriod)); } } }
上述web自动配置源码可以看到所有 /webjars/**
,都去 classpath:/META-INF/resources/webjars/
找资源;
webjars
:以jar包的方式引入静态资源;webjars官网
作用:将前端框架以maven依赖的方式交给我们使用,比如引入jquery依赖,使用jquery内部定义好的资源。
<!--引入jquery-webjar--> <dependency> <groupId>org.webjars</groupId> <artifactId>jquery</artifactId> <version>3.3.1</version> </dependency>
我们请求localhost:8080/webjars/jquery/3.3.1/jquery.js
会从jquery中resources目录webjars/jquery/...
访问具体的资源。在访问的时候只需要写webjars下面资源的名称即可。
2.访问当前项目任何资源
"/**" 访问当前项目的任何资源,都去(静态资源的文件夹)找映射
public class WebMvcAutoConfiguration { @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)); } // 静态资源文件夹映射 String staticPathPattern = this.mvcProperties.getStaticPathPattern(); if (!registry.hasMappingForPattern(staticPathPattern)) { customizeResourceHandlerRegistration( registry.addResourceHandler(staticPathPattern) .addResourceLocations( this.resourceProperties.getStaticLocations()) .setCachePeriod(cachePeriod)); } } }
this.mvcProperties.getStaticPathPattern()
方法:
/** * Path pattern used for static resources. */ private String staticPathPattern = "/**";
this.resourceProperties.getStaticLocations()
方法:
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false) public class ResourceProperties implements ResourceLoaderAware { private static final String[] SERVLET_RESOURCE_LOCATIONS = { "/" }; private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" }; private static final String[] RESOURCE_LOCATIONS; static { RESOURCE_LOCATIONS = new String[CLASSPATH_RESOURCE_LOCATIONS.length + SERVLET_RESOURCE_LOCATIONS.length]; System.arraycopy(SERVLET_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS, 0, SERVLET_RESOURCE_LOCATIONS.length); System.arraycopy(CLASSPATH_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS, SERVLET_RESOURCE_LOCATIONS.length, CLASSPATH_RESOURCE_LOCATIONS.length); } /** * Locations of static resources. Defaults to classpath:[/META-INF/resources/, * /resources/, /static/, /public/] plus context:/ (the root of the servlet context). */ private String[] staticLocations = RESOURCE_LOCATIONS; public String[] getStaticLocations() { return this.staticLocations; } }
查看上面两个方法源码可以看到,静态资源都放在这些文件夹中,只要没人处理,就从这些文件夹中找资源
"classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/" "/**":当前项目的根路径
优先级:resources > static(默认) > public
我们访问localhost:8080/abc
,等同于去静态资源文件夹里面找abc,因为默认就是从这些静态资源目录中找资源,所以请求不用写静态资源目录名
3.欢迎页
静态资源文件夹下的所有index.html页面,被"/**"映射;
public class WebMvcAutoConfiguration { // 配置欢迎页映射 @Bean public WelcomePageHandlerMapping welcomePageHandlerMapping( ResourceProperties resourceProperties) { return new WelcomePageHandlerMapping(resourceProperties.getWelcomePage(), // 静态资源路径 /** this.mvcProperties.getStaticPathPattern()); } } @ConfigurationProperties(prefix = "spring.mvc") public class WebMvcProperties { /** * Path pattern used for static resources. */ private String staticPathPattern = "/**"; public String getStaticPathPattern() { return this.staticPathPattern; } }
访问
localhost:8080/
默认路径,请求 找index.html页面
为什么欢迎页是index.html
在哪里配置的?上面源码中可以看到new WelcomePageHandlerMapping
类实例。
它是WebMvcAutoConfiguration类中静态类,指定了视图名叫index.html
。
public class WebMvcAutoConfiguration { static final class WelcomePageHandlerMapping extends AbstractUrlHandlerMapping { private static final Log logger = LogFactory.getLog(WelcomePageHandlerMapping.class); private WelcomePageHandlerMapping(Resource welcomePage, String staticPathPattern) { if (welcomePage != null && "/**".equals(staticPathPattern)) { logger.info("Adding welcome page: " + welcomePage); ParameterizableViewController controller = new ParameterizableViewController(); controller.setViewName("forward:index.html"); setRootHandler(controller); setOrder(0); } } } }
4.网页图标
访问网页每个网站都会有这种属于自己的小图标。
所有的 **/favicon.ico
都是在静态资源文件下找;
public class WebMvcAutoConfiguration { @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; } } }
配置网页标题的图标:
#关闭默认图标,默认是打开的:matchIfMissing = true spring.mvc.favicon.enabled=false
注意🔞:
springboot版本2.1.x版本中,在resources/public目录下放入favicon.ico图片
springboot版本1.x.x版本中,favicon.ico图片可以放在resources目录下的任意静态资源目录中,比如resources/static目录下
5.自定义静态资源存放路径
若自定义静态资源存放路径,可以在配置文件application.properties
文件中指定路径:
# 多个路径以 , 逗号分隔 spring.resources.static-locations=classpath:/mystatic/,classpath:/myresources/
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false) public class ResourceProperties implements ResourceLoaderAware { //可以设置和静态资源有关的参数,缓存时间等
7.2模板引擎
JSP、Velocity、Freemarker、Thymeleaf
SpringBoot推荐的Thymeleaf;语法更简单,功能更强大;
1、引入thymeleaf
前端交给我们的页面是html页面。如果是我们以前开发,我们需要把他们转成jsp页面,jsp好处就是当我们查出一些数据转发到JSP页面以后,我们可以用jsp轻松实现数据的显示及交互等。但是,我们现在的这种情况,SpringBoot这个项目首先是以jar的方式,不是war,第二,我们用的还是嵌入式的Tomcat,所以呢,他现在默认是不支持jsp的。
SpringBoot推荐你可以来使用模板引擎。模板引擎的作用就是我们来写一个页面模板,比如有些值呢,是动态的,我们写一些表达式。而这些值,从哪来呢,我们来组装一些数据,我们把这些数据找到。然后把这个模板和这个数据交给我们模板引擎,模板引擎按照我们这个数据帮你把这表达式解析、填充到我们指定的位置,然后把这个数据最终生成一个我们想要的内容给我们写出去,这就是我们这个模板引擎,不管是jsp还是其他模板引擎,都是这个思想。SpringBoot给我们推荐的Thymeleaf模板引擎。
第一步:引入thymeleaf springboot1.x.x版本 要用2.x.x版本的,springboot2.x.x 要用3.x.x的版本
<!--要切换thymeleaf版本,不适用springboot默认版本,在<properties>标签中进行指定要切换的版本,布局功能支持thymeleaf-layout-dialect.version要适配thymeleaf.version版本,thymeleaf.version 3版本适配2版本的布局功能--> <properties> <thymeleaf.version>3.0.9.RELEASE</thymeleaf.version> <!-- 布局功能的支持程序 thymeleaf3主程序 layout2以上版本 --> <!-- thymeleaf 2 layout 1--> <thymeleaf-layout-dialect.version>2.2.2</thymeleaf-layout-dialect.version> </properties> <!--thymeleaf模板--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
2、Thymeleaf使用
在templates目录下的所有页面,只能通过controller来跳转,需要模板引擎thymeleaf支持。
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; }
可以在其中看到默认的视图名称前缀prefix和后缀suffix,我们只需要把我们的html页面放在类路径下的templates目录下,返回需要的视图名称,thymeleaf就可以帮我们自动渲染了。
测试:
1、html文件导入thymeleaf的名称空间
<html lang="en" xmlns:th="http://www.thymeleaf.org">
2、controller
import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; @Controller // 不能使用@RestController注解,html中msg报错 public class ThymeleafController { @RequestMapping("/test") public String thymeleafTest(Model model){ model.addAttribute("msg", "<h1>thymeleaf模板引擎</h1>"); return "test"; // 跳转的html页面名称 } }
3、html文件
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <!--一定要写:xmlns:th="http://www.thymeleaf.org"否则 th:不能使用--> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div th:text="${msg}"></div> </body> </html>
#关闭模板引擎缓存 spring.thymeleaf.cache=false
3、Thymeleaf语法
th:text;改变当前元素里面的文本内容;
th:任意html属性;来替换原生属性的值
表达式语法:
Simple expressions:(表达式语法) Variable Expressions: ${...}:获取变量值;OGNL; 1)、获取对象的属性、调用方法 2)、使用内置的基本对象: #ctx : the context object. #vars: the context variables. #locale : the context locale. #request : (only in Web Contexts) the HttpServletRequest object. #response : (only in Web Contexts) the HttpServletResponse object. #session : (only in Web Contexts) the HttpSession object. #servletContext : (only in Web Contexts) the ServletContext object. eg:${session.foo} 3)、内置的一些工具对象: #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). Selection Variable Expressions: *{...}:选择表达式:和${}在功能上是一样;配合 th:object="${session.user},这样之后如果使用th:object中的属性就不用${session.user.firstName} 示例: <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> 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: _
测试:
@Controller // 不能使用@RestController注解,html中msg报错 public class ThymeleafController { @RequestMapping("/test") public String thymeleafTest(Model model){ model.addAttribute("msg", "<h1>thymeleaf模板引擎</h1>"); model.addAttribute("job", Arrays.asList("简历", "工作")); // 数组转换为list return "test"; // 返回视图名称 } }
test.html:
<body> <div th:text="${msg}"></div> <!--th:utext将获取的内容进行转义(内容中有可以转义的标签)--> <div th:utext="${msg}"></div> <hr> <!-- 将job取到的值赋给user, user取出循环的到的值--> <div th:each="user:${job}" th:text="${user}"></div> </body>
本文来自博客园,作者:Lz_蚂蚱,转载请注明原文链接:https://www.cnblogs.com/leizia/p/16686938.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步