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依赖

  • 创建启动应用,创建控制器

    image-20221109202548432
  • 默认端口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 配置形式及其加载顺序(优先级由高到低):

    1. 命令行参数
    2. 来自 java:comp/env 的 JNDI 属性
    3. Java 系统属性(System.getProperties())
    4. 操作系统环境变量
    5. RandomValuePropertySource 配置的 random.* 属性值
    6. 配置文件(YAML 文件、Properties 文件)
    7. @Configuration 注解类上的 @PropertySource 指定的配置文件
    8. 通过 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";
        }
    }
    
posted @ 2022-11-16 21:45  z5onk0  阅读(19)  评论(0编辑  收藏  举报