SpringBoot学习与使用(一)

本文介绍了SpringBoot的基础知识,包括其概念、特点和创建项目的方法。详细讲述了如何通过Spring官网和IDEA构建SpringBoot项目,包括配置文件、日志管理和单元测试。SpringBoot简化了配置,提供自动装配特性,旨在提升开发效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SpringBoot基础

在这里插入图片描述

1、概念

1.1、简单介绍

Spring官网:点击查看
在这里插入图片描述
在这里插入图片描述
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。Spring Boot致力于在蓬勃发展的快速应用开发领域成为领导者。
2013年,Pivotal团队开始研发SpringBoot。
2014年4月,发布全新开源的轻量级框架的第一个SpringBoot版本。
原博文:点击查看

1.2、特点:

为什么要学习SpringBoot?
SpringBoot是为了简化Spring应用的创建、运行、调试、部署等一系列问题而诞生的产物,自动装配 的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖就可以轻易的搭建出一个 WEB 工程。
末接触SpringBoot之前,搭建一个普通的WEB工程往往需要花费30分钟左右,如果遇到点奇葩的问题,耽搁的时间会更长一点,但自从用了SpringBoot后,真正体会到什么叫分分钟搭建一个WEB项目。
在传统的一些框架中 (SSH、SSM、Servlet/JSP)虽然功能很强大但是配置起来太麻烦了,相比python或者php,Java就略显臃肿,主要问题有两点:
1、复杂的配置文件:
项目之间各种配置文件铺天盖地,在开发的过程中占用了大量的时间,并且需要对这些配置文件进行维护,所以整个项目感觉特别复杂,并且Java代码和配置文件之间的切换开发,给程序开发人员带来很大的负担。
2、各种依赖比较混乱:
主要问题就是版本冲突,不同技术的版本需要我们知道哪些版本存在冲突问题,一旦使用错误,就需要重新再去下载依赖库进行依赖配置。
而Spring Boot简化了基于Spring的应用开发,只需要一个run”就创建了一个独立的、生产级别的Spring应用,Spring Boot为Spring平台及第三方提供了开箱即用的设置(默认设置的包就是启动器starter),这样我们就可以简单的开始使用了。Spring Boot主张 用最少的配置做更多的事,如果我们创建一个Java应用,并使用java-jar启动,就能得到一个生产级别的web工程。

特点:

  • 创建独立的 Spring应用程序
  • 直接内嵌Tomcat、Jetty或Undertow (无需部署WAR文件)
  • 提供自以为是的“入门”依赖项以简化我们的构建配置
  • 尽可能自动配置 Spring3rd方库
  • 提供生产就绪功能,例如指标、运行状况检查和外部化配置
  • 完全不需要代码生成,也不需要 XML 配置
    SpringBoot=Spring+SpringMVC

2、构建SpringBoot项目

2.1、通过spring官网构建

Spring构建项目官网:点击查看
在这里插入图片描述

2.2、通过idea构建

2.2.1、创建项目

在这里插入图片描述

2.2.2、选择依赖

在这里插入图片描述

2.2.3、启动项目

点击启动项目
在这里插入图片描述
查看项目启动日志
在这里插入图片描述

2.2.4、前后台交互

简单体验下
后端部分:
在这里插入图片描述
前端页面:
在这里插入图片描述
简单前后端交互完成!!!

2.2.5、springboot项目的目录结构

项目目录结构
在这里插入图片描述
启动类:它里面有一个main方法,通过调用SpringApplication类的run方法来运行项目
resource -> static:存放静态资源(css,js,image等)
配置文件:主要的配置文件,SpringBoot项目启动时候,会自动加载配置文件。文件类型可以是:application.yml / application.yaml / application.properties
pom.xml:此文件是maven构建的基础,里面包含项目基本信息、依赖配置、插件配置等。

pom.xml
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.2.6、自定义banner

SpringBoot启动的时候,我们可以看到如下内容,这一块其实是可以自定义的,而且在 2.X 版本中,它支持的格式从文本扩展到banner.txtbanner.jpgbanner.gifbanner.jpeg等等,只需要在**resouces****目录下添加指定命名的文件即可。

定义banner文件
在这里插入图片描述
重新运行项目
在这里插入图片描述

2.2.7、查看SpringBoot默认提供的Bean

在这里插入图片描述

在这里插入图片描述

2.2.8、手动注入Bean

在这里插入图片描述
运行查看是否注入,在控制层也可以用 @Value 注解获取

2.2.9、简单了解配置文件

从启动日志中可以发现,SpringBoot默认的端口是 8080,那么如果端口被占用了怎么办呢? 不要慌,问题不大,可以去杀掉占用8080端口的进程,也可以修改端口号
在这里插入图片描述

2.2.10、关于starter

starter 翻译意思是:参赛人、发令员

SpringBoot中的starter是一种非常重要的机制(自动化配置),能够抛弃以前繁杂的配置,将其统一集成进starter,应用者只需要在maven中引入
starter依赖SpringBoot就能自动扫描到要加载的信息并启动相应的默认配置。starter让我们摆脱了各种依赖库的处理,需要配置各种信息的困扰。
SpringBoot会自动通过classpath路径下的类发现需要的Bean,并注册进IOC容器。SpringBoot提供了针对日常企业应用研发各种场景的
spring-boot-starter依赖模块。所有这些依赖模块都遵循着约定成俗的默认配置,并允许我们调整这些配置,即遵循“约定大于配置”的理念。

例如:
spring-boot-starter-web
spring-boot-starter-parent 这是SpringBoot的父级依赖,这样当前的项目就是SpringBoot项目了。spring-boot-starter-parent 是个特殊的 starter。

功能1:默认依赖配置(绝对兼容)

它用来提供相关的 Maven 默认依赖。使用它之后,常用的包依赖可以省去 version 标签,当我们搭建web应用的时候,可以像下面这样添加spring-boot-starter-web依赖:
在这里插入图片描述
但是这种默认允许不填写版本号的依赖也必须是boot中默认给定的,如果没有默认给定,还是需要手动填写的。

功能2:默认环境配置 (绝对兼容)

默认使用 Java8,可以添加以下配置修改版本。
默认使用UTF-8编码,可添加以下配置修改编码等。
在这里插入图片描述

功能3:资源过滤

识别默认配置文件
在这里插入图片描述
过滤打包内容(打包的时候把 src/main/resources 下所有文件都打包到jar包中)
在这里插入图片描述

3、YAML / YML配置文件

在我们翻阅stater的过程中,也应该发现配置文件除了可是使用application*,properties类型,还可以使用后缀为.yml或.yaml类型,这种类型相比properties类型支持了集合对象等数据,但是前提也必须是application*才能被Spring扫描到。

YAML是“YAML Ain't a Markup Language” (YAML不是一种标记语言)的递归缩写。在开发的这种语言时,
YAML的意思其实是:“Yet Another Markup Language”(仍是一种标记语言),但为了强调这种语言以数据
做为中心,而不是以标记语言为重点,而用反向缩略语重命名。

配置环境基础信息,创建application.yaml

3.1、语法规则
  1. 大小写敏感
  2. 使用缩进表示层级关系
  3. 缩进时不允许使用Tab键,只允许使用空格。
  4. 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
  5. 可以使用“-小写字母”或小写字母来代替“大写字母”,如 userName 与 user-name,user name 含义是一样的
  6. key: value 格式书写 key 后面跟着冒号,再后面跟着一个空格,然后是值
  7. 注释使用 #
3.2、数据类型

YAML支持的数据结构有三种:

  1. 普通的值(数字,字符串,布尔)
  2. 对象(属性和值)、Map(键值对)
  3. 数组(List、Set)

测试代码:

# 基本数据类型
catname: 小橘猫
catage: 5
ischengnian: true

# 对象
cat:
  name: 加菲猫
  age: 6

# 数组
dog:
  - 京巴
  - 哈士奇
  - 藏獒
  - 泰迪

# 组合 对象里面包含数组
animal:
  bear:
    - 黑熊
    - 棕熊
    - 北极熊
  pig:
    - 黑猪
    - 白猪

# 组合 数组里面包含对象
car:
  - car1: 兰博基尼
  - car2: 宝马

car2:
  - { carname1: 一汽大众, price: 20w }
  - { carname2: 宝马a6, price: 40w }

在控制层读取配置文件信息

package edu.xja.springbootfirst.controller;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @author: lvjt
 * @Date: 2023/3/16 11:22
 * @description: some description
 */

@Controller
//@PropertySource("classpath:application-dev.yml.1")
@RequestMapping("/animal")
public class AnimalController {

    @RequestMapping("/showCat")
    public String showCat(String name){
        System.out.println(name);
        return "cat";
    }

    @Value("${catname}")
    private String catname;
    @Value("${catage}")
    private int catage;
    @Value("${ischengnian}")
    private boolean ischengnian;

    // 获取application.yml里面的基本数据类型
    @RequestMapping("/showCat1")
    public String showCat1(){
        System.out.println("=====================================showCat1==================================");
        System.out.println(catname);
        System.out.println(catage);
        System.out.println(ischengnian);
        System.out.println("=======================================================================");
        return "cat";
    }

    @Value("${cat.name}")
    private String cat_name;
    @Value("${cat.age}")
    private String cat_age;

    // 获取application.yml里面的对象
    @RequestMapping("/showCat2")
    public String showCat2(){
        System.out.println("=====================================showCat2==================================");
        System.out.println(cat_name);
        System.out.println(cat_age);
        System.out.println("=======================================================================");
        return "cat";
    }

    @Value("${dog[0]}")
    private String jingba;
    @Value("${dog[1]}")
    private String hashiqi;
    @Value("${dog[2]}")
    private String zangao;
    @Value("${dog[3]}")
    private String taidi;

    // 获取application.yml里面的数组
    @RequestMapping("/showDog")
    public String showDog(){
        System.out.println("=====================================showDog==================================");
        System.out.println(jingba);
        System.out.println(hashiqi);
        System.out.println(zangao);
        System.out.println(taidi);
        System.out.println("=======================================================================");
        return "cat";
    }

    @Value("${animal.bear[0]}")
    private String heixiong;
    @Value("${animal.pig[0]}")
    private String baizhu;

    // 获取application.yml里面的  组合 对象里面包含数组
    @RequestMapping("/showAnimal")
    public String showAnimal(){
        System.out.println("=====================================showAnimal==================================");
        System.out.println(heixiong);
        System.out.println(baizhu);
        System.out.println("=======================================================================");
        return "cat";
    }

    @Value("${car[0].car1}")
    private String car1;
    @Value("${car[1].car2}")
    private String car2;

    // 获取application.yml里面的  组合 对象里面包含数组
    @RequestMapping("/showCar1")
    public String showCar1(){
        System.out.println("=====================================showCar1==================================");
        System.out.println(car1);
        System.out.println(car2);
        System.out.println("=======================================================================");
        return "cat";
    }

    @Value("${car2[0].carname1}")
    private String car1Name;
    @Value("${car2[0].price}")
    private String car1Price;

    @Value("${car2[1].carname2}")
    private String car2Name;
    @Value("${car2[1].price}")
    private String car2Price;

    // 获取application.yml里面的  组合 对象里面包含数组
    @RequestMapping("/showCar2")
    public String showCar2(){
        System.out.println("=====================================showCar2==================================");
        System.out.println(car1Name);
        System.out.println(car1Price);
        System.out.println(car2Name);
        System.out.println(car2Price);
        System.out.println("=======================================================================");
        return "cat";
    }
}

在这里插入图片描述
关于直接获取数组类型
读取yml中配置的一个数组,通过 @Vaule 一直获取不到,通过一番资料的查询,才彻底清楚了 @Vaule 的使用情况。
在Spring中读取配置文件的快捷方法常见的有两种,一个是通过 @Vaule 注解进行单一字段的注入,另外一种方法就是通过 @ConfigurationProperties 注解来进行批量注入。
在这里插入图片描述

在这里插入图片描述
声明配置类
在这里插入图片描述
使用方法
在这里插入图片描述

4、SpringBoot日志配置

SpringBoot内部采用的是 Commons Logging 进行日志记录,但在底层为 Java Util Logging + Log4J2.Logback 等日志框架提供了默认配置,
Java虽然有很多可用的日志框架,但是不用担心,一般来说,使用springBoot默认的 Logback 就可以了。

4.1、日志格式

在这里插入图片描述
输出如下元素:

Logback是没有 FATAL 级别的日志,它将被映射到 ERROR

  1. 时间日期:精确到毫秒,可以用于排序
  2. 日志级别:ERROR、WARN、INFO、DEBUG、TRACE
  3. 进程ID
  4. 分隔符:采用—来标识日志开始部分
  5. 线程名:方括号括起来
  6. Logger名: 通常使用源代码的类名
  7. 日志内容:我们输出的消息
4.2、日志级别拓展log4j
log4i定义了很全的日志级别,分别是: OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、ALL,
一共8个级别的log,它们的优先级顺序为: OFF > FATAL > ERROR> WARN >INFO > DEBUG >TRACE>ALL。
但是除去一些不常用的日志级别(如OFF、FATAL、TRACE、ALL)。其实,我们一般经常使用ERRORWARN、INFO、
DEBUG这四种级别。而Log4j也建议我们使用四个级别,优先级从高到低分别是ERROR.WARN、INFO、DEBUG。
通过在这里定义的级别,可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别,则应用程序
中所有DEBUG级别的日志信息将不被打印出来。而优先级高的将被打印出来。
项目上生产环境时候一定得把debug的日志级别重新调为warn或者更高,避免产生大量日志。
  1. OFF:最高等级的,用于关闭所有日志记录
  2. FATAL:指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。
  3. ERROR:指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。
  4. WARN:表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员一些提示。
  5. INFO:消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志。
  6. DEBUG: 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。
  7. TRACE:跟踪日志,日志消息的粒度太细,很低的日志级别,一般不会使用。
  8. ALL:最低等级的,用于打开所有日志记录。
4.3、日志输出

SpringBoot默认为我们输出的日志级别为 INFOWARNERROR,如需要输出更多日志的时候,
可以通过以下方式开启命令模式配置java -jar app.jar --debug=true, 这种命令会被SpringBoot解析,且优先级最高。
资源文件配置: application.yml 配置 debug=true 即可。该配置只对嵌入式容器SpringHibernate 生效,我们自己的项目想要输出 DEBUG 需要额外配置。
配置规则:

logging:
	level:具体的包名=具体的日志级别
# 例如:
logging:
	level: 
		org.springframework = info
		org.apache = error
...
4.4、文件保存

默认情况下,SpringBoot仅将日志输出到控制台,不会写入到日志文件中去。如果除了控制台输出之外,还想写日志文件,则需要在springboot的核心配置文件设置 logging.filelogging.path 属性。
logging.file:将日志写入到指定的文件中,默认为相对路径,可以设置成绝对路径。
logging.path:将名为spring.log写入到指定的文件夹中,如( /var/log )。
日志文件在达到 10MB 时,会进行切割,产生一个新的日志文件(如:spring.1.log、spring.2.log),新的日志依旧输出到spring.log中去,默认情况下会记录ERRORWARNINFO级别消息。
logging.file.max-size:限制日志文件大小
logging.file.max-history:限制日志保留天数

logging:
  level:
    org.springframework.boot: info
    edu.abc: info # 建议:info 或者 warn
    org.apache: info
  file:
    # path: E://springboot-new//springboot-log
    # path: E:\springboot-new\springboot-log
    path: E:\springboot-new\springboot-log\boot2.txt

# 如果颜色消失,可以配置这个
spring:
  output:
    ansi:
      enabled: always
4.5、自定义Log日志
package edu.xja;

import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@Log4j2
@RequestMapping("/plant")
public class PlantController {

    // 自定义日志信息
    @RequestMapping("/showPear")
    public String showPear(){
        log.warn("我写的代码被{}警告{}了","idea","很多次");
        log.info("正常打印日志的基本信息");
        log.error("出现了一个很奇怪的错误!");
        log.debug("正在对某一块区域的代码进行debug!");
        log.trace("正在追踪日志信息");
        return "plant";
    }
}

在这里插入图片描述
推荐一个显示五颜六色日志的插件:Grep Console
在这里插入图片描述

5、SpringBoot单元测试

在这里插入图片描述

在实际开发中,每当完成一个功能接口或业务方法的编写后,通常都会借助单元测试验证该功能是否正确。SpringBoot对项目的单元测试提供了很好的支持,在使用时,需要提前在项目的pom.xml文件中添加 spring-boot-starter-test 测试依赖启动器,可以通过相关注解实现单元测试。
SpringBoot项目的单元测试:

5.1、添加依赖

添加 spring-boot-starter-test 测试依赖启动器。
在项目的pom.xml文件中添加 spring-boot-starter-test 测试依赖启动器,示例代码如下:

<!--        springboot 单元测试-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
<!--        junit单元测试平台启动器-->
<dependency>
    <groupId>org.junit.platform</groupId>
    <artifactId>junit-platform-launcher</artifactId>
    <scope>test</scope>
</dependency>

上述代码中,展示了SpringBoot框架集成单元测试提供的依赖启动器,其范围默认为test。需要说明的是,如果是使用 Spring lnitializr方式(就是在idea里面搭建)搭建的SpringBoot项目,会自动加入 spring-boot-starter-test 测试依赖启动器,无需开发者再手动添加。

5.2、编写单元测试类

在项目中添加测试依赖启动器后,可以编写SpringBoot项目中相关方法对应的单元测试。
如果是使用 Spring lnitialir方式 搭建的Spring Boot项目,会在 src.test.java 测试目录下自动创建与项目主程序启动类对应的单元测试类。

package edu.xja.category;

import edu.xja.entity.Category;
import edu.xja.service.CategoryService;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

// 和以前不太一样,这种方式会启动当前spring容器
@SpringBootTest
public class CategoryTest {

    // 特殊要求,获取IOC容器中的CategoryService对象
    @Autowired
    private CategoryService categoryService;

    /**
     * 查询所有防盗门分类信息
     *
     * @return
     */
    @Test
    public void testQueryList(){
        List<Category> categoryList = categoryService.queryList();
        categoryList.forEach(System.out::println);
    }

    // 在测试之前做一些事情...
    @BeforeEach
    public void before(){
        System.out.println("CategoryTest...before...");
    }

    // 在测试之后做一些事情...
    @AfterEach
    public void after(){
        System.out.println("CategoryTest...after...");
    }
}

在这里插入图片描述

6、Junit4单元测试

需要在pom.xml依赖文件里面引入 junithamcrest 这两个依赖jar包

<!--        junit 4-->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest</artifactId>
    <scope>test</scope>
</dependency>

需要在测试方法的方法上面加上 @Test 注解

package edu.xja.test;

import org.junit.Test;

public class FirstTest {

    @Test
    public void testOne(){
        System.out.println(11111);
    }
}

双击方法名,然后右键运行此方法进行测试

在这里插入图片描述

可以看到,控制台输出11111,测试已经成功了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值