Spring Boot学习笔记(1/2)
前言
serverlet
- 服务器端小程序,第一代java web开发技术,基于java实现了一套用于动态网站的API
- Tomcat\Jetty\Undertow都是Servelet容器,用来管理Servelet类
jsp
- 在html页面中嵌入java代码,用于java web应用程序的用户界面部分,通过网页表单获取用户输入数据、访问数据库及其他数据源,然后动态地创建网页
- serverlet将html代码以字符串的形式向外输出,编写html文档就是在拼接字符串
- 第二代java web技术,是对serverlet的封装
war包和jar包
- JAR文件的目的是把类和相关的资源封装到压缩的归档文件中
- 对于WAR文件来说,一个WAR文件代表了一个Web应用程序,它可以包含 Servlet、HTML页面、Java类、图像文件,以及组成Web应用程序的其他资源,而不仅仅是类的归档文件
Maven
- Maven 是一个项目管理工具,可以对 Java 项目进行构建、依赖管理
spring boot特点
- 简化xml配置
- 内嵌serverlet容器
Tomcat
- Apache是web服务器,Tomcat是应用(java)服务器,它只是一个servlet容器,是Apache的扩展
- Apache是普通服务器,本身支支持html普通网页,可以通过cgi扩展支持php,可以与tomcat连通
- tomcat用于执行jsp和serlet,核心组件包括
- Web 容器:完成 Web 服务器的功能
- Servlet 容器:名字为 catalina,用于处理 Servlet 代码
- JSP 容器:用于将 JSP 动态网页翻译成 Servlet 代码
创建Spring Boot项目
-
使用Maven创建
-
在poc.xml中添加如下配置
- 父工程依赖
<!--父工程,有这个项目即为springboot项目--> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.5.2</version> <relativePath/> <!-- lookup parent from repository --> </parent>
- Spring Web依赖
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
-
reload项目,安装Spring Boot依赖
-
创建启动应用,创建控制器
-
默认端口8080,可在src/main/resources下的appilication.properties文件中修改端口号
server.port=8090
starter启动器
-
引入starter依赖,自动解决web所有配置
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies>
-
Spring Boot项目的父级依赖,被称为版本仲裁中心,对项目内常用依赖进行统一管理
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.4.5</version> <relativePath/> </parent>
Spring Boot配置绑定
JavaBean类
-
实现了Serializable接口,实例可被序列化
-
属性必须私有
-
实现了getter和setter方法
-
其它程序可以通过反射技术实例化JavaBean对象,并可获取其属性
-
配置绑定就是把配置文件中的值与 JavaBean 中对应的属性进行绑定
@ConfigurationProperties
-
在application.yml中添加对象及其属性
person: lastName: 张三 age: 18 boss: false birth: 1990/12/12 maps: { k1: v1,k2: 12 } //绑定字典 lists: //绑定列表 ‐ lisi ‐ zhaoliu dog: //绑定实例 name: 迪迪 age: 5
-
创建一个JavaBean类
- 类前需要增加
@Component和@ConfigurationProperties(prefix = "person")
注解- 只有在容器中的组件,才会拥有 SpringBoot 提供的强大功能。如果我们想要使用 @ConfigurationProperties 注解进行配置绑定,那么首先就要保证该对 JavaBean 对象在 IoC 容器中,所以需要用到 @Component 注解来添加组件到容器中。
- JavaBean 上使用了注解 @ConfigurationProperties(prefix = "person") ,它表示将这个 JavaBean 中的所有属性与配置文件中以“person”为前缀的配置进行绑定。
- 类中需要针对要传入的每个属性,定义get和set,以及构造方法
- 类前需要增加
-
对JavaBean类实例化前加一个注解
@Autowired
,即可完成配置绑定
@Value
- 当只需要读取配置文件中的某一个配置时,可以通过 @Value 注解获取
- 在类中声明每个私有属性前,加注解
@Value("${person.lastName}")
- 其余不变
@PropertySource
-
写一个单独的配置文件中,并在对应的 JavaBean 上使用 @PropertySource 注解指向该配置文件
-
resources目录下创建person.properties文件,写入属性值
-
创建JavaBean类前,加入注解:
@PropertySource(value = "classpath:person.properties")//指向对应的配置文件 @Component @ConfigurationProperties(prefix = "person")
IOC和DI
控制反转
- 把原本调用者通过代码实现的对象的创建,反转给 IoC 容器来帮忙实现,是面向对象编程中的一种设计原则,可以用来降低代码中的耦合度
- 本质是把对象的创建以及对象之间的调用过程,都交给Spring管理
- 底层原理包括xml解析、工厂模式、反射机制
- IOC容器的代表是BeanFactory及AppicationContext
基于XML配置文件方式实现控制反转
-
参考https://zhuanlan.zhihu.com/p/413580900
-
在xml配置文件中使用bean标签创建对象
-
注入属性
- 方式一:通过set方法注入
- 方式二:通过有参构造注入
-
注入bean
- 注入外部bean
- 注入内部bean
bean的生命周期
-
从创建到销毁
1、通过构造器创建bean实例(默认无参构造器) 2、为bean的属性注入值或对其他bean的引用(调用set方法) 3、把bean的实例传递给bean后置处理器方法 4、调用bean的初始化方法(需要进行配置) 5、把bean的实例传递给bean后置处理器方法 6、bean创建完毕,可以使用了 7、容器关闭的时候,调用bean的销毁方法(需要进行配置)
-
可以自定义初始化、销毁方法,添加后置处理器,精准控制bean的创建
事务管理
- 参考https://www.cnblogs.com/sharpest/p/7995203.html
- 事务的作用就是为了保证用户的每一个操作都是可靠的,事务中的每一步操作都必须成功执行,只要有发生异常就回退到事务开始未进行操作的状态。
- 首先使用注解 @EnableTransactionManagement 开启事务支持
- 然后在目标方法上添加注解 @Transactional 便可
单元测试
- 参考https://blog.csdn.net/wangxi06/article/details/114630426
Service层的单元测试
@SpringBootTest
:获取启动类,加载配置,寻找主配置启动类@RunWith(SpringRunner.class)
:让JUnit运行Spring的测试环境,获得Spring环境的上下文的支持@Test
:注解待测试方法,同时可以加下面两个注解@Transactional
:开启事务功能@Rollback()
: 事务回滚,默认是true
Controller层的单元测试
- 用到MockMvc,它使得你无需启动项目工程就能测试这些接口,MockMvc实现了对Http请求的模拟,能够直接使用网络的形式,转换到Controller的调用,这样可以使得测试速度快、不依赖网络环境
@SpringBootTest
>:获取启动类,加载配置,寻找主配置启动类(被 @SpringBootApplication 注解的)@RunWith(SpringRunner.class)
>:让JUnit运行Spring的测试环境,获得Spring环境的上下文的支持@AutoConfigureMockMvc
:用于自动配置MockMvc,配置后MockMvc类可以直接注入,相当于new MockMvc@Before
:初始化方法 ,对于每一个测试方法都要执行一次
让XML配置文件生效
@ImportResource 导入 Spring 配置文件
- 在主启动程序类上使用 @ImportResource 注解,将 Spring 配置文件 beans.xml 加载到项目中
全注解方式加载 Spring 配置
- 删除主启动类的 @ImportResource 注解
- 使用
@Configuration
注解定义一个注解类,相当于 Spring 的配置文件 - 配置类中包含一个或多个被 @Bean 注解的方法,该方法相当于 Spring 配置文件中的
标签定义的组件 - 方法名是组件 id(相当于
标签的属性 id)
Profile
多Profile方式
- Spring Boot 的配置文件共有两种形式:.properties 文件和 .yml 文件
- 在 helloworld 的 src/main/resources 下添加 4 个配置文件:
- application.properties:主配置文件
- application-dev.properties:开发环境配置文件
- application-test.properties:测试环境配置文件
- application-prod.properties:生产环境配置文件
- 在主配置文件中激活某环境的配置文件,也可在命令行中激活
外部配置文件
-
命令行中指定外部配置文件
java -jar {JAR} --spring.config.location={外部配置文件全路径}
配置文件加载优先级
-
以下是常用的 Spring Boot 配置形式及其加载顺序(优先级由高到低):
- 命令行参数
- 来自 java:comp/env 的 JNDI 属性
- Java 系统属性(System.getProperties())
- 操作系统环境变量
- RandomValuePropertySource 配置的 random.* 属性值
- 配置文件(YAML 文件、Properties 文件)
- @Configuration 注解类上的 @PropertySource 指定的配置文件
- 通过 SpringApplication.setDefaultProperties 指定的默认属性
-
命令行启动spring boot
java -jar springbootdemo-0.0.1-SNAPSHOT.jar --server.port=8081 --server.servlet.context-path=/bcb --server.port:指定服务器端口号; --server.servlet.context-path:指定上下文路径(项目的访问路径)
自动配置的原理
- Spring Boot 自动化配置也是基于 Spring Factories 机制实现的
- Spring Boot 启动时,会利用 Spring-Factories 机制,将这些 xxxAutoConfiguration 实例化并作为组件加入到容器中,以实现 Spring Boot 的自动配置
自动配置的生效和修改该
- spring.factories 文件中的所有自动配置类(xxxAutoConfiguration),都是必须在一定的条件下才会作为组件添加到容器中,配置的内容才会生效
- 这些限制条件在 Spring Boot 中以 @Conditional 派生注解的形式体现
Spring Boot日志
统一日志框架
- 分为日志门面(日志抽象层)和日志实现
- Spring boot用的是SLF4J和Logback
- 通常一个完整的应用下会依赖于多种不同的框架,而且它们记录日志使用的日志框架也不尽相同
- 当我们引入了依赖了其他日志框架的第三方框架(例如 Hibernate)时,只需要把这个框架所依赖的日志框架排除,即可实现日志框架的统一
日志配置及输出
-
五种优先级
package net.biancheng.www; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class SpringbootLoggingApplicationTests { Logger logger = LoggerFactory.getLogger(getClass()); /** * 测试日志输出 * SLF4J 日志级别从小到大trace>debug>info>warn>error */ @Test void logTest() { //日志级别 由低到高 logger.trace("trace 级别日志"); logger.debug("debug 级别日志"); logger.info("info 级别日志"); logger.warn("warn 级别日志"); logger.error("error 级别日志"); } }
-
在 application.properties 中,修改 Spring Boot 日志的默认配置
#日志级别 logging.level.net.biancheng.www=trace #使用相对路径的方式设置日志输出的位置(项目根目录目录\my-log\mylog\spring.log) #logging.file.path=my-log/myLog #绝对路径方式将日志文件输出到 【项目所在磁盘根目录\springboot\logging\my\spring.log】 logging.file.path=/spring-boot/logging #控制台日志输出格式 logging.pattern.console=%d{yyyy-MM-dd hh:mm:ss} [%thread] %-5level %logger{50} - %msg%n #日志文件输出格式 logging.pattern.file=%d{yyyy-MM-dd} === [%thread] === %-5level === %logger{50} === - %msg%n
Spring Boot静态资源映射
- 默认提供三种静态资源映射规则:
- WebJars 映射
- 默认资源映射
- 静态首页(欢迎页)映射
Webjars映射
- 通常我们会将这些 Web 前端资源拷贝到 Java Web 项目的 webapp 相应目录下进行管理,但是 Spring Boot 项目是以 JAR 包的形式进行部署的,不存在 webapp 目录
- WebJars 可以完美的解决上面的问题,它可以 Jar 形式为 Web 项目提供资源文件
- 方法:
- 访问webjar官网,找到需要的前端资源的pom依赖
- 将依赖加入pom.xml
- jar包引入到当前项目路径下的
/META-INF/resources/webjars/
- 访问
/webjars/**
下的所有请求,都会取上面路径下查找前端资源
默认静态资源映射
- 以下路径被称为静态资源文件夹,按优先级从高到底:
- classpath:/META-INF/resources/
- classpath:/resources/
- classpath:/static/
- classpath:/public/
静态首页映射
- 静态资源文件夹下的所有 index.html 被称为静态首页或者欢迎页,当我们访问“/”或者“/index.html”时,都会跳转到静态首页
Thymeleaf
- 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎,可集成到Web框架
- 与其它模板引擎相比,Thymeleaf 最大的特点是,即使不启动 Web 应用,也可以直接在浏览器中打开并正确显示模板页面
简介
- Thymeleaf 是新一代 Java 模板引擎,支持 HTML 原型,其文件后缀为“.html”,
- 因此它可以直接被浏览器打开,此时浏览器会忽略未定义的 Thymeleaf 标签属性,展示 thymeleaf 模板的静态页面效果;
- 当通过 Web 应用程序访问时,Thymeleaf 会动态地替换掉静态内容,使页面动态显示
语法规则
-
在html标签中声明名称空间
xmlns:th="http://www.thymeleaf.org"
-
标准表达式语法
-
变量表达式,使用 ${} 包裹的表达式被称为变量表达式,具有以下功能:
-
获取对象的属性和方法
${person.lastName}
-
使用内置的基本对象,常用的内置基本对象为:
- #ctx :上下文对象;
- #vars :上下文变量;
- #locale:上下文的语言环境;
- #request:HttpServletRequest 对象(仅在Web 应用中可用);
- #response:HttpServletResponse 对象(仅 Web 应用);
- #session:HttpSession 对象(仅Web 应用可用);
- #servletContext:ServletContext 对象(仅Web 应用)
-
使用内置的工具对象
-
-
选择变量表达式
-
当使用 th:object 存储一个对象后,我们可以在其后代中使用选择变量表达式(*{...})获取该对象中的属性
<div th:object="${session.user}" > <p th:text="*{fisrtName}">firstname</p> </div>
-
-
链接表达式
-
不管是静态资源的引用,还是 form 表单的请求,凡是链接都可以用链接表达式 (@{...})
-
链接表达式的形式结构如下:
- 无参请求:@
- 有参请求:@
-
使用链接表达式引入 css 样式表
<link href="asserts/css/signin.css" th:href="@{/asserts/css/signin.css}" rel="stylesheet">
-
-
-
th属性:Thymeleaf 还提供了大量的 th 属性,这些属性可以直接在 HTML 标签中使用
Thymeleaf 公共页面抽取
-
头部导航栏、侧边菜单栏和公共的 js css 等,我们一般会把这些公共页面片段抽取出来,存放在一个独立的页面中,然后再由其他页面根据需要进行引用
-
抽取公共页面
-
使用 Thymeleaf 提供的 th:fragment 属性为这些抽取出来的公共页面片段命名,如commons,html:
<div th:fragment="fragment-name" id="fragment-id"> <span>公共页面片段</span> </div>
-
-
引用公共页面
-
使用以下3个属性,将公共页面片段引入到当前页面
- th:insert:将代码块片段整个插入到使用了 th:insert 属性的 HTML 标签中;
- th:replace:将代码块片段整个替换使用了 th:replace 属性的 HTML 标签中;
- th:include:将代码块片段包含的内容插入到使用了 th:include 属性的 HTML 标签中。
-
例如在fragment.html中引入commons.html
<!--th:insert 片段名引入--> <div th:insert="commons::fragment-name"></div> <!--th:insert id 选择器引入--> <div th:insert="commons::#fragment-id"></div>
-
-
传递参数
-
传入参数
<!--th:insert 片段名引入--> <div th:insert="commons::fragment-name(var1='insert-name',var2='insert-name2')"></div> <!--th:insert id 选择器引入--> <div th:insert="commons::#fragment-id(var1='insert-id',var2='insert-id2')"></div>
-
使用参数
<!--使用 var1 和 var2 声明传入的参数,并在该片段中直接使用这些参数 --> <div th:fragment="fragment-name(var1,var2)" id="fragment-id"> <p th:text="'参数1:'+${var1} + '-------------------参数2:' + ${var2}">...</p> </div>
-
Spring Boot整合Thymeleaf
引入依赖
-
pom.xml中添加Thymeleaf的Starter依赖
<!--Thymeleaf 启动器--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency>
创建模板文件
- Spring Boot 通过 ThymeleafAutoConfiguration 自动配置类对 Thymeleaf 提供了一整套的自动化配置方案
- Thymeleaf 模板的默认位置在 resources/templates 目录下,默认的后缀是 html,即只要将 HTML 页面放在“classpath:/templates/”下,Thymeleaf 就能自动进行渲染
示例
-
创建hello.html
<!DOCTYPE html> <!--导入thymeleaf的名称空间--> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--th:text 为 Thymeleaf 属性,用于获取指定属性的值--> <h1 th:text="'欢迎来到'+${name}"></h1> </body> </html>
-
新建一个控制类 HelloController,并通过参数 map 传递数据到前台页面中
package net.biancheng.www.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import java.util.Map; @Controller public class HelloController { @RequestMapping("/hello") public String hello(Map<String, Object> map) { //通过 map 向前台页面传递数据 map.put("name", "编程帮(www.biancheng.net)"); return "hello"; } }