Springboot框架技术总结(四)

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!
从 Spring-boot-dependencies 底层源文件可以看出,该文件通过 properties 标签对一些常用的技术框架依赖进行了统一版本号的管理,例如 activemq、spring、tomcat 等,都有于 Spring Boot 2.3.4 想匹配的版本,这也是 pom.xml 引入依赖文件不需要指定依赖文件版本号的原因。核心依赖都在父工程版本仓库中,这就是我们引入依赖时不用写版本号的原因。

需要注意的是,如果 pom.xml 文件引入依赖文件不是 spring-boot-starter-parent 管理的,那么在 pom.xml 引入依赖文件时,需要使用 <version> 标签指定依赖文件的版本号

总结:SpringBoot 依靠父项目中的版本锁定和starter机制让我们能更轻松的实现对依赖的管理。

1.1.2、spring-boot-starter-web依赖

spring-boot-starter-parent 父依赖启动器的主要作用是进行版本统一管理,那么项目运行依赖的 jar 包从何而来,又是怎样管理的呢?

查看 spring-boot-starter-web 依赖源文件,关键代码如下:

org.springframework.boot

spring-boot-starter

2.5.4

compile

org.springframework.boot

spring-boot-starter-json

2.5.4

compile

org.springframework.boot

spring-boot-starter-tomcat

2.5.4

compile

org.springframework

spring-web

5.3.9

compile

org.springframework

spring-webmvc

5.3.9

compile

从上述代码中可以发现, spring-boot-starter-web 依赖启动器的主要作用是提供 Web 开发场景所需要的底层所有依赖文件,它对 Web 开发场景所需的依赖文件进行了统一管理。

正是如此,在 pom.xml 文件中引入 spring-boot-starter-web 依赖启动器,就可以实现 web 场景开发,而不需要额外导入 Tomcat 服务器及其他 Web 依赖文件等。

Spring Boot 除了提供上述介绍的 Web 依赖启动器外,还提供了其他许多开发场景的相关依赖,可以通过 Spring Boot 官方文档进行查看。官方文档启动器

需要注意的是,Spring Boot 官方并不是针对所有场景开发的技术框架都提供了依赖启动器,例如 Mybatis、阿里巴巴的 Druid 数据源等,Spring Boot 官方就没有提供对象的依赖启动器。为了充分利用 Spring Boot 框架的优势,在 Spring Boot 官方没有整合这些技术的情况下, Mybatis 、Druid 等技术框架所在的团队主动与 Spring Boot 框架进行了整合,实现了各自的依赖启动器,例如 mybatis-spring-boot-starter、druid-spring-boot-starter 等。我们在pom.xml 文件中引入这些第三方的依赖启动器是需要配置对应的版本号。

1.1.3、依赖冲突

一般程序在运行时发生类似于 java.lang.ClassNotFoundException,Method not found: ‘……’,或者莫名其妙的异常信息,这种情况一般很大可能就是 jar包依赖冲突的问题引起的了。

一般在是A依赖C(低版本),B也依赖C(高版本)。 都是他们依赖的又是不同版本的C的时候会出现。

解决方案:

如果出现了类似于 java.lang.ClassNotFoundException,Method not found: 这些异常检查相关的依赖冲突问题,排除掉低版本的依赖,留下高版本的依赖。

我们可以使用 IDEA 插件 -> MavenHelper

1.1.4、版本锁定

我们的 SpringBoot 模块都需要继承一个父工程:spring-boot-starter-parent。在spring-bootstarter-parent的父工程spring-boot-dependencies 中对常用的依赖进行了版本锁定。这样我们在添加依赖时,很多时候都不需要添加依赖的版本号了。

我们也可以采用覆盖properties配置或者直接指定版本号的方式修改依赖的版本。

例如:

  • 直接指定版本号

org.aspectj

aspectjweaver

1.7.2

  • 覆盖 properties 配置

<aspectj.version>1.7.2</aspectj.version>

1.1.5、starter机制

当我们需要使用某种功能时只需要引入对应的starter即可。一个starter针对一种特定的场景,其内部引入了该场景所需的依赖。这样我们就不需要单独引入多个依赖了。

命名规律:

  • 官方starter都是以 spring-boot-starter 开头后面跟上场景名称。例如:spring-boot-starterdata-jpa

  • 非官方starter则是以 场景名-spring-boot-starter 的格式,例如:mybatis-spring-boot-starter

1.2、Spring Boot 自动配置


@SpringBootApplication

public class SpringBootKuangApplication {

public static void main(String[] args) {

SpringApplication.run(SpringBootKuangApplication.class, args);

}

}

  • @SpringBootApplication 注解:标注这个类是一个 SpringBoot 的应用

  • SpringApplication.run()方法:将 springboot 应用启动

我们进入@SpringBootApplication 注解

在这里插入图片描述

前面提到过,Spring Boot 应用的启动入口是 @SpringBootApplication 注解标注类中的 main() 方法,@SpringBootApplication 能够扫描 Spring 组件并自动配置 Spring Boot,那么它到底是如何自动配置 Spring Boot 的呢?下面通过查询 @SpringBootApplication 内部源码进行分析,关键代码如下:

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@SpringBootConfiguration

@EnableAutoConfiguration

@ComponentScan(

excludeFilters = {@Filter(

type = FilterType.CUSTOM,

classes = {TypeExcludeFilter.class}

), @Filter(

type = FilterType.CUSTOM,

classes = {AutoConfigurationExcludeFilter.class}

)}

)

public @interface SpringBootApplication {

@AliasFor(

annotation = EnableAutoConfiguration.class

)

Class<?>[] exclude() default {};

@AliasFor(

annotation = EnableAutoConfiguration.class

)

String[] excludeName() default {};

@AliasFor(

annotation = ComponentScan.class,

attribute = “basePackages”

)

String[] scanBasePackages() default {};

@AliasFor(

annotation = ComponentScan.class,

attribute = “basePackageClasses”

)

Class<?>[] scanBasePackageClasses() default {};

@AliasFor(

annotation = ComponentScan.class,

attribute = “nameGenerator”

)

Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

@AliasFor(

annotation = Configuration.class

)

boolean proxyBeanMethods() default true;

}

从上述源码中可以看出,@SpringBootApplication 注解是一个组合注解,包含 @SpringBootConfiguration@EnableAutoConfiguration@ComponentScan 这 3 个核心注解,关于这三个核心注解相关说明如下:

在这里插入图片描述

1.2.1、@SpringBootConfiguration注解

@SpringBootConfiguration 注解表示 Spring Boot 配置类,查看 @SpringBootConfiguration 注解源码,关键代码如下:

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Configuration

@Indexed

public @interface SpringBootConfiguration {

@AliasFor(

annotation = Configuration.class

)

boolean proxyBeanMethods() default true;

}

从上述源码中可以看出,@SpringBootConfiguration 注解内部有一个核心注解 @Configuration,该注解是 Spring 框架提供的,表示当前类是一个配置类,并可以被组件扫描器扫描。由此可见,@SpringBootConfiguration 注解的作用与 @Configuration 注解相同,都是标识一个可以被组件扫描器扫描的配置类,只不过是 @SpringBootConfiguration 是被 Spring Boot 进行了重新封装命名而已。

1.2.2、@EnableAutoConfiguration注解

@EnableAutoConfiguration 注解表示开启自动配置功能,该注解是 Spring Boot 框架最重要的注解,也是实现自动化配置的注解。查看该注解内部源码,关键代码如下:

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@AutoConfigurationPackage

@Import({AutoConfigurationImportSelector.class})

public @interface EnableAutoConfiguration {

String ENABLED_OVERRIDE_PROPERTY = “spring.boot.enableautoconfiguration”;

Class<?>[] exclude() default {};

String[] excludeName() default {};

}

从上述源码中可以看出,@EnableAutoConfiguration注解是一个组合注解,它主要包括有 @AutoConfigurationPackage 和 @Import 两个核心注解

①、@AutoConfigurationPackage

查看 @AutoConfigurationPackage 注解内部源码信息,关键代码如下:

@Target({ElementType.TYPE})

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Inherited

@Import({Registrar.class})

public @interface AutoConfigurationPackage {

String[] basePackages() default {};

Class<?>[] basePackageClasses() default {};

}

从上述源码中可以看出,@AutoConfigurationPackage 注解的功能是由 @Import 注解实现的,作用是向容器导入注册的所有组件,导入的组件由 Register 提供。查看 Register 类源码信息,关键代码如下:

static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {

Registrar() {

}

public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {

AutoConfigurationPackages.register(registry, (String[])(new AutoConfigurationPackages.PackageImports(metadata)).getPackageNames().toArray(new String[0]));

}

public Set determineImports(AnnotationMetadata metadata) {

return Collections.singleton(new AutoConfigurationPackages.PackageImports(metadata));

}

}

从上述源码中可以看出,在 Register 类中有一个 registerBeanDefinitions() 方法,使用 Debug 模式启动项目,会发现第 8 行代码中的代码获取的是项目主程序启动器类所在的目录。

也就是说,@AutoConfigurationPackage 注解的主要作用是获取项目主程序启动器类所在的根目录,从而指定后续组件扫描器要扫描的包位置。因此在定义项目包结构时,要求定义的包结构非常规范,项目主程序启动器类要定义在最外层的根目录位置,然后在根目录内部建立子包和类进行业务开发,这样才能够保证定义的类能够被组件扫描器扫描。

②、@Import({AutoConfigurationImportSelector.class})

查看 AutoConfigurationImportSelector 类的 getAutoConfigurationEntry() 方法,关键代码如下:

protected AutoConfigurationImportSelector.AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {

if (!this.isEnabled(annotationMetadata)) {

return EMPTY_ENTRY;

} else {

AnnotationAttributes attributes = this.getAttributes(annotationMetadata);

List configurations = this.getCandidateConfigurations(annotationMetadata, attributes);

configurations = this.removeDuplicates(configurations);

Set exclusions = this.getExclusions(annotationMetadata, attributes);

this.checkExcludedClasses(configurations, exclusions);

configurations.removeAll(exclusions);

configurations = this.getConfigurationClassFilter().filter(configurations);

this.fireAutoConfigurationImportEvents(configurations, exclusions);

return new AutoConfigurationImportSelector.AutoConfigurationEntry(configurations, exclusions);

}

}

上述源码中的 getAutoConfigurationEntry() 方法,其主要作用是筛选出当前项目环境需要启动的自动配置类,从而实现当前项目运行所需的自动配置环境

1.2.3、@ComponentScan注解

  • @ComponentScan 注解是一个组件包扫描器,用于将指定包中的注解类自动装配到 Spring 的 Bean 容器中。

  • @ComponentScan 注解具体扫描的包的根路径有 Spring Boot 项目主程序启动类所在包位置决定,在扫描过程中由 @AutoConfigurationPackage 注解进行解析,从而得到 Spring Boot 项目主程序启动类所在包的具体位置。

1.3、Spring Boot 执行流程

每个 Spring Boot 项目都有一个主程序启动器类,在主程序启动器类中有一个启动项目的 main() 方法,在该方法中通过执行 SpringApplication.run() 即可启动整个 Spring Boot 应用程序。

Spring Boot 的执行流程主要分为两步,分别是初始化 Spring Application 实例和初始化 Spring Boot 项目启动,如下图所示:

在这里插入图片描述

1.3.1、初始化 Spring Application实例

在这里插入图片描述

1.3.2、初始化Spring Boot 项目启动

在这里插入图片描述

2、SpringBoot视图技术

==================================================================================

在一个 web 应用中,通常会采用 MVC 设计模式实现对应的模型、视图和控制器,其中,视图是用户看到并与之交互的界面。对最初的Web应用来说,视图是由 HTML 元素组成的静态界面,而后期的 Web 应用更倾向于使用动态模板技术,从而实现前后端分离和页面的动态数据展示。Spring Boot 框架为简化项目的整体开发,提供了一些视图技术支持,并主要推荐整合模板引擎技术来实现前端页面的动态化内容。

2.1、Thymeleaf


Spring Boot 官方不推荐使用 JSP 模板,并且没有提供对应的整合配置,这是因为使用嵌入式 Servlet 容器的 Spring Boot 应用程序对于 JSP 模板存在一些限制,具体如下所示:

  • Spring Boot 默认使用嵌入式 Servlet 容器,以 jar 包的方式进行项目打包部署,这种 jar 包方式不支持 jsp 模板

  • Spring Boot 默认提供了一个处理请求路径 “/error” 的统一错误处理器,返回具体的异常信息。使用 JSP 模板时,无法使用 Spring Boot 自带的异常处理器,只能根据要求在 Spring Boot 项目的指定位置定制错误页面。

Thymeleaf 是一种现代的基于服务器端的 Java 模板引擎技术,它具有丰富的标签语言、函数和表达式,在使用 Spring Boot 框架进行页面设计时,一般会选择 Thymeleaf 模板。

2.2、基本使用


2.2.1、添加Thymeleaf依赖

org.springframework.boot

spring-boot-starter-thymeleaf

如果使用 Spring Initializr 方式创建,并选择了 Template Engines 模块下的 Thymeleaf 场景依赖,则不需要再添加依赖。

在这里插入图片描述

2.2.2、application.properties

在全局配置文件(application.properties 或者 application.yml)中配置 Thymeleaf 模板的参数,一般 Web 项目都会使用下列配置,关键代码如下所示(下面代码也可以不写,因为默认就是如下代码,不过最好将模板缓存设置为false):

#启动模板缓存

spring.thymeleaf.cache=true

#设置模板编码(可不配置)

spring.thymeleaf.encoding=UTF-8

#设置模板模式

spring.thymeleaf.mode=HTML5

#指定模板页面存放路径(可不配置)

spring.thymeleaf.prefix=classpath:/templates/

#指定模板页面名称后缀(可不配置)

spring.thymeleaf.suffix=.html

  • spring.thymeleaf.cache 表示是否开启 Thymeleaf 模板缓存,默认为true,一般在开发中通常会关闭缓存,保证项目调试过程中数据能够及时响应

  • spring.thymeleaf.encoding 用于指定 Thymeleaf 模板的编码格式,默认为 UTF-8

  • spring.thymeleaf.mode 表示设置模板模式。默认为 HTML

  • spring.thymeleaf.prefix 指定了 Thymeleaf 模板页面的存放路径

  • spring.thymeleaf.suffix 制定了 Thymelaf 模板页面的后缀名称,默认为 .html

2.2.3、创建Web控制器类

在项目中创建名称 com.xxx.controller 的包,并在该包下创建一个用于前端模板页面动态数据替换效果测试的访问控制器类 IndexController,代码如下:

@Controller

public class IndexController {

@RequestMapping(“/”)

public String index(Model model){

model.addAttribute(“title”,“Spring Boot”);

return “index”;

}

}

2.2.4、创建Thymeleaf模板页面

在项目的 templates 目录下创建 thymeleaf 模板(实际上创建 html 网页),只要我们把 HTML 页面放在 classpath:/templates/,thymeleaf 就能自动渲染。

  • 需要注意的是,使用 thymeleaf 模板,首先要引入其命名空间,命名空间如下:
  • 在 templates 目录下创建名为 index 的HTML网页,代码如下
首页

在这里插入图片描述

2.3、静态资源的访问


开发 Web 应用时,难免需要使用静态资源。Spring Boot 默认设置了静态资源的访问路径,默认将 /** 所有访问映射到以下目录。

  1. classpath:/META-INF/resources/:项目类路径下的 META-INF 文件夹下的 resources 文件夹下的所有文件。

  2. classpath:/resources/ : 项目类路径下的 resources 文件夹下的所有文件

  3. classpath:/static/ : 项目类路径下的 static 文件夹下的所有文件

  4. classpath:/public/ : 项目类路径下的 public 文件夹下的所有文件

注意:使用 Spring Initializr 方式创建的 Spring boot 项目会默认生成一个 resources 目录,在 resources 目录中新建 public、resources、static 三个子目录,Spring Boot 默认会从 public、resources、static 里面查找静态资源。(优先级)

3、Thymeleaf基本语法

=================================================================================

在 HTML 页面上使用 Thymeleaf 标签,Thymeleaf 标签能够动态地替换掉静态内容,动态显示页面内容,同时可以使用 th 前缀来替换 HTML 的任意属性,前提是在 HTML 页面中需要引入 Thymeleaf 模板的命名空间。

3.1、变量输出


在 Thymeleaf 模板页面中,输出控制器的模型数据可以使用如下方式,如下表所示:

| 表达式 | 表达式描述 |

| — | — |

| th:text | 显示文本,会转义特殊字符 |

| th:utext | 不会转义特殊字符 |

| th:value | 在 input 标签中输出值 |

| [[${}]] | 显示文本,相当于 th:text |

| [(${})] | 转义内容后显示,相当于 th:utext |

3.2、内置对象


Web 项目中经常会传递一些数据,例如 String 类型、列表、日期对象和数值等,thymeleaf 提供的内置对象可以通过 # 直接访问。常用内置对象如下:

| 内置对象 | 描述 |

| — | — |

| #dates | 日期格式化内置对象,具体方法参考 java.util.Date |

| #calendars | 日历,具体方法参考 java.util.Calendar |

| #strings | 字符串格式化,具体方法参考 java.lang.String |

| #numbers | 数字格式化 |

| #objects | 对象函数 |

| #bools | 逻辑参数,判断 boolean 类型的工具 |

| #arrays | 数组函数 |

| #list | 列表函数,具体方法参考 java.util.List |

| #sets | set操作工具,具体方法参考 java.util.Set |

| #maps | map函数,具体方法参考 java.util.Map |

| #aggregates | 操作数组或集合的工具 |

| #messages | 操作消息的工具 |

注意:内置对象一般都以 s 结尾,如 dates、lists、numbers 等,在使用内置对象时需要在对象名前加 #

上述的内置对象需要关注的是 #dates,常用的方法为 #dates.format(key,pattern)

model.addAttribute(“now”,new Date())

在 Thymeleaf 模板页面中使用 #dates.format() 方法格式化输出

3.3、条件判断


Thymeleaf 模板视图提供了常用的条件判断标签

| 表达式 | 表达式描述 |

| — | — |

| th:if | 条件判断,与java中的if类似 |

| th:unless | 条件判断,取反,条件为true,结果为false |

| th:switch | 条件判断,与java中的switch类似 |

| th:case | 条件判断,与java中的case类似 |

model.addAttribute(“sex”,1); // 1-男,2-女

3.4、迭代循环


Thymeleaf 模板视图提供了 th:each 循环迭代标签,该标签可以循环数组 arrays、list集合、set 集合 和 map集合

| 表达式 | 描述 |

| — | — |

| th:each | 循环 |

  1. 在项目中创建名为 com.xxx,entity 的包,在该包下创建 User 类

@Data

@NoArgsConstructor

@AllArgsConstructor

public class User {

private Integer id;

private String username;

private String phone;

private Integer sex;

private Date birthday;

}

  1. 在项目中的 com.xxx.controller 包下创建一个用户控制器 UserController

@Controller

@RequestMapping(“/user”)

public class UserController {

@RequestMapping(“/list”)

public String list(Model model){

List userList = new ArrayList<>();

userList.add(new User(1,“张三1”,“12345678”,1,new Date()));

userList.add(new User(2,“张三2”,“12345678”,1,new Date()));

userList.add(new User(3,“张三3”,“12345678”,1,new Date()));

userList.add(new User(4,“张三4”,“12345678”,1,new Date()));

// 将数据添加到模型中

model.addAttribute(“userList”,userList);

return “userlist”;

}

}

  1. 在 Thymeleaf 模板页面中使用
首页
编号 姓名 电话 性别 生日

th:each 标签的状态变量属性如下:

  1. index:当前迭代器的索引,从 0 开始

  2. cout:当前迭代对象的计数,从 1 开始

  3. size:被迭代对象的长度

  4. even/odd:布尔值,当前循环是否是偶数/奇数,从 0 开始

  5. first:布尔值,当前循环的是否是第一条,如果是返回 true,否则返回 false

  6. last: 布尔值,当前循环的是否是最后一条,如果是则返回 true,否则返回false

首页
编号 姓名 电话

面试题总结

其它面试题(springboot、mybatis、并发、java中高级面试总结等)

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!
=“${user.id}”>

th:each 标签的状态变量属性如下:

  1. index:当前迭代器的索引,从 0 开始

  2. cout:当前迭代对象的计数,从 1 开始

  3. size:被迭代对象的长度

  4. even/odd:布尔值,当前循环是否是偶数/奇数,从 0 开始

  5. first:布尔值,当前循环的是否是第一条,如果是返回 true,否则返回 false

  6. last: 布尔值,当前循环的是否是最后一条,如果是则返回 true,否则返回false

首页
编号 姓名 电话

面试题总结

其它面试题(springboot、mybatis、并发、java中高级面试总结等)

[外链图片转存中…(img-30yTg5dO-1714758386514)]

[外链图片转存中…(img-pDp92u3e-1714758386515)]

[外链图片转存中…(img-pgIwqWJ0-1714758386515)]

《一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码》点击传送门,即可获取!

  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值