pom.xml配置文件下
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>2.4.5version>
<relativePath/>
parent>
进入spring-boot-started-parent之后,spring-boot-dependencies 核心依赖在父工程中.
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-dependenciesartifactId>
<version>2.4.5version>
parent>
在写或者引入一些SpringBoot依赖的时候,不需要指定版本,核心依赖中有版本仓库
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
SpringBoot 的 启动场景
SpringBoot 会将所有的功能场景变成一个个启动器,需要什么功能,只需找到对应的启动器即可。
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication //标注这个类是一个SpringBoot的应用 不可缺少
public class DemoApplication
{
public static void main(String[] args)
{
SpringApplication.run(DemoApplication.class, args);
}
}
@SpringBootConfiguration //SpringBoot配置
@Configuration //Spring配置类
@Conponent // 说明是Spring的一个组件
@EnableAutoConfiguration //自动装配
@AutoConfigurationPackage //自动配置包
@Import(AutoConfigurationPackages.Register.class) //自动配置 包注册
@Import(AutoConfigurationImportSelector.class) //自动配置 导入选择
//获取所有配置
List<String> configurations = getCandidateConfigurations(annotationMetadata,attributes);
// SpringBoot所有的自动配置都在启动的时候被扫描并加载
// 扫描 META-INF/spring.factotories (自动配置的核心文件)
// 所有的配置类都在spring.factories中,但是不一定生效,需要判断条件是否成立
// 只有加入了对应的start,有了对应的启动器,自动装配才能生效
SpringBoot采用yaml配置文件来代替xml文件
通过 @ConfigurationProperties注解 来实现配置文件映射赋值
通过 @PropertySource注解 来绑定配置文件,并通过@Value注解 来给属性赋值
给字段增加一层过滤器验证,保证字段合法性。
项目 yaml 配置文件优先级
Spring底层注解:根据不同的条件,来判断当前配置或者文件是否生效
XXXAutoConfiguration:默认值 XXXproperties 和 配置文件绑定 , 可以使用自定义的配置
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
//如果有自动配置则退出
if (!this.resourceProperties.isAddMappings()) {
logger.debug("Default resource handling disabled");
return;
}
//在webjars网站上通过maven依赖导入相关jar
addResourceHandler(registry, "/webjars/**", "classpath:/META-INF/resources/webjars/");
//对应下方五个路径下的资源文件
addResourceHandler(registry, this.mvcProperties.getStaticPathPattern(), (registration) -> {
registration.addResourceLocations(this.resourceProperties.getStaticLocations());
if (this.servletContext != null) {
ServletContextResource resource = new ServletContextResource(this.servletContext, SERVLET_LOCATION);
registration.addResourceLocations(resource);
}
});
}
//分别对应resources目录下的resources资源文件夹、public资源文件夹、static资源文件夹
//优先级为 rescoures > static > public
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = { "classpath:/META-INF/resources/",
"classpath:/resources/", "classpath:/static/", "classpath:/public/" };
private String staticPathPattern = "/**";
private Resource getWelcomePage()
{
//通过 CLASSPATH_RESOURCE_LOCATIONS 来获取四个路径下的首页
//注意: 如果已经在配置文件里修改过路径 则 无效
for (String location : this.resourceProperties.getStaticLocations()) {
//通过路径来获取相关资源
Resource indexHtml = getIndexHtml(location);
//如果四个路径下存在首页就返回
if (indexHtml != null) {
return indexHtml;
}
}
//如果在springboot自带的路径下没有找到
ServletContext servletContext = getServletContext();
if (servletContext != null) {
//找到自定义路径并调用下面第一个getIndexHtml方法
return getIndexHtml(new ServletContextResource(servletContext, SERVLET_LOCATION));
}
return null;
}
private Resource getIndexHtml(String location) {
//通过路径参数来获取相关资源并调用第二个getIndexHtml方法
return getIndexHtml(this.resourceLoader.getResource(location));
}
private Resource getIndexHtml(Resource location) {
try {
//获取index.html页面
Resource resource = location.createRelative("index.html");
if (resource.exists() && (resource.getURL() != null)) {
//资源存在并且路径不为空就返回
return resource;
}
}
catch (Exception ex) {
}
return null;
}
模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的HTML文档
JSP、Freemarker、Thymeleaf等都是一些常用的模板引擎
Thymeleaf 官网 : https://www.thymeleaf.org
Github 地址 : https://github.com/thymeleaf/thymeleaf
Thymeleaf 相关依赖
<dependency>
<groupId>org.thymeleafgroupId>
<artifactId>thymeleaf-spring5artifactId>
dependency>
<dependency>
<groupId>org.thymeleaf.extrasgroupId>
<artifactId>thymeleaf-extras-java8timeartifactId>
dependency>
**Thymeleaf 配置文件 **
//默认字符编码
private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
//默认前缀 thymeleaf默认写在templates文件夹下
public static final String DEFAULT_PREFIX = "classpath:/templates/";
//默认后缀
public static final String DEFAULT_SUFFIX = ".html";
//在templates下的所有页面只能通过 controller 跳转
//这个需要模板引擎的支持 而SpringBoot不支持JSP 所以采用Thymeleaf
@Controller
public class IndexController
{
//通过 localhost:8080/index 来跳转到相关页面
@RequestMapping("/index")
public String index()
{
//返回的文件名会被thymeleaf进行拼接
return "test";
}
}
<html lang="en" xmlns:th="http://www.thymeleaf.org">html>
<div th:text="'这里是要替换的文字'+${session.title}+'......'">
前端开发展示所用的内容
div>
<div th:href="@{/eps/**}">div>
<h3 th:each="user:${users}" th:text="${user}">h3>
<h3 th:each="user:${users}">[[ ${user} ]]h3>
<tr th:each="emp:${emps}">
<td th:text="${emp.getId()}">td>
<td th:text="${emp.getLastName()}">td>
<td th:text="${emp.getEmail()}">td>
<td th:text="${emp.getGender()==0?'女':'男'}">td>
<td th:text="${emp.department.getDepartName()}">td>
<td th:text="${#dates.format(emp.getBitrh(),'yyyy-MM-dd HH:mm:ss')}">td>
tr>
<nav class="col-md-2 d-none d-md-block bg-light sidebar" th:fragment="sidebar">nav>
<div th:insert="~{dashboard::sidebar}">div>
<div th:replace="~{dashboard::siderbar}">div>
<div th:replace="~{dashboard::siderbar(active='list')}">div>
div>
扩展装配SpringMVC
@Configuration
public class MyMvcConfig implements WebMvcConfigurer
{
//ViewResolver 实现了视图解析器接口的类 可以看作视图解析器
@Bean
public ViewResolver myViewResolver()
{
return new MyViewResolver();
}
//自定义一个视图解析器 MyViewResolver
public static class MyViewResolver implements ViewResolver
{
@Override
public View resolveViewName(String s, Locale locale) throws Exception
{
return null;
}
}
}
首页跳转
// 1. 首页控制器
// 注意: 需要导入thymeleaf依赖
@Controller
public class IndexController
{
//通过localhost:8080/ 或者 localhost:8080/index.html 皆可访问index主页
@RequestMapping({"/","/index.html"})
public String index()
{
return "index";
}
}
// 2. 扩展MVC
@Configuration
public class MyMvcConfig implements WebMvcConfigurer
{
//视图跳转
@Override
public void addViewControllers(ViewControllerRegistry registry)
{
//跳转主页
//通过localhost:8080/ 或者 localhost:8080/index.html 皆可访问index主页
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
}
国际化
相关源码
//消息自动配置部分源码
@Bean
@ConfigurationProperties(prefix = "spring.messages")
public MessageSourceProperties messageSourceProperties()
{
return new MessageSourceProperties();
}
//本地解析源码
@Bean
@ConditionalOnMissingBean( name = {"localeResolver"} )
public LocaleResolver localeResolver() {
//如果用户配置的有本地区域化信息 则返回用户的配置
if (this.webProperties.getLocaleResolver() == org.springframework.boot.autoconfigure.web.WebProperties.LocaleResolver.FIXED) {
return new FixedLocaleResolver(this.webProperties.getLocale());
} else if (this.mvcProperties.getLocaleResolver() == org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties.LocaleResolver.FIXED) {
return new FixedLocaleResolver(this.mvcProperties.getLocale());
} else {
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
Locale locale = this.webProperties.getLocale() != null ? this.webProperties.getLocale() : this.mvcProperties.getLocale();
localeResolver.setDefaultLocale(locale);
return localeResolver;
}
}
//接收头本地解析
@Override
public Locale resolveLocale(HttpServletRequest request)
{
Locale defaultLocale = getDefaultLocale();
//如果接收的语言为空 则采用默认语言
if (defaultLocale != null && request.getHeader("Accept-Language") == null) {
return defaultLocale;
}
//不为空时接收进行配置并返回
Locale requestLocale = request.getLocale();
List<Locale> supportedLocales = getSupportedLocales();
if (supportedLocales.isEmpty() || supportedLocales.contains(requestLocale)) {
return requestLocale;
}
Locale supportedLocale = findSupportedLocale(request, supportedLocales);
if (supportedLocale != null) {
return supportedLocale;
}
return (defaultLocale != null ? defaultLocale : requestLocale);
}
自定义区域化解析
#默认 login.properties
login.password=密码
login.remember=记住密码
login.sign=登录
login.tip=请登录
login.username=用户名
#中文 login_zh_CN.properties
login.password=密码
login.remember=记住密码
login.sign=登录
login.tip=请登录
login.username=用户名
#英文 login_en_US.properties
login.password=Password
login.remember=Remember me
login.sign=Sign in
login.tip=Please sign in
login.username=Username
public class MyLocalResolver implements LocaleResolver
{
//解析请求
@Override
public Locale resolveLocale(HttpServletRequest request)
{
//获取请求中的语言参数
String language = request.getParameter("language");
//如果参数为空采用默认格式
Locale locale = Locale.getDefault();
//不为空时
if(!StringUtils.isEmpty(language))
{
//分解国际化参数
// zh_CN en_US 国家_地区
String[] languages = language.split("_");
locale = new Locale(languages[0],languages[1]);
}
return locale;
}
}
//将自定义配置类注入Bean
@Configuration
public class MyMvcConfig implements WebMvcConfigurer
{
//视图跳转
@Override
public void addViewControllers(ViewControllerRegistry registry)
{
//跳转主页
registry.addViewController("/").setViewName("index");
registry.addViewController("/index.html").setViewName("index");
}
//注入Bean
@Bean
public LocaleResolver localeResolver()
{
return new MyLocalResolver();
}
}
<a th:href="@{/index.html(language='zh_CN')}">中文a>
<a th:href="@{/index.html(language='en_US')}">Englisha>
页面效果
其他
//通过Controller跳转的页面 URL 可能会很复杂,为了方便我们可以自己配置视图跳转
@Override
public void addViewControllers(ViewControllerRegistry registry)
{
//跳转页面
//需要通过Controller 重定向到/main.html路径并跳转到dashboard页面
// return "redirect:/main.html";
//此时URL为 localhost:8080/main.html(默认配置文件中没有配上下文路径)
registry.addViewController("/main.html").setViewName("dashboard");
}
src="…/AppData/Roaming/Typora/typora-user-images/image-20210730120324009.png" alt=“image-20210730120324009” style=“zoom:50%;” />
其他
//通过Controller跳转的页面 URL 可能会很复杂,为了方便我们可以自己配置视图跳转
@Override
public void addViewControllers(ViewControllerRegistry registry)
{
//跳转页面
//需要通过Controller 重定向到/main.html路径并跳转到dashboard页面
// return "redirect:/main.html";
//此时URL为 localhost:8080/main.html(默认配置文件中没有配上下文路径)
registry.addViewController("/main.html").setViewName("dashboard");
}