SpringBoot框架

1.SpringBoot简介

1.1 原有Spring优缺点分析

1.1.1 Spring的优点分析

Spring是Java企业版(Java Enterprise Edition,javeEE)的轻量级代替品。无需开发重量级的Enterprise JavaBean(EJB),Spring为企业级Java开发提供了一种相对简单的方法,通过依赖注入和面向切面编程,用简单的Java对象(Plain Old Java Object,POJO)实现了EJB的功能。

1.1.2 Spring的缺点分析

虽然Spring的组件代码是轻量级的,但它的配置却是重量级的。
不论是一开始的基于XML的配置,还是Spring2.5引入的基于注解的组件扫描,还是Spring 3.0引入的基于Java的配置,这些都代表了开发时的额外损耗。
因为在思考Spring配置和解决业务问题之间需要进行思维切换,甚至还带来了何种方式配置更好的无谓争论,所以编写配置挤占了编写应用程序逻辑的时间。和所有框架一样,Spring实用,但与此同时它要求的回报也不少。
除此之外,项目的依赖管理也是一件耗时耗力的事情。在环境搭建时,需要分析要导入哪些库的坐标,而且还需要分析导入与之有依赖关系的其他库的坐标,一旦选错了依赖的版本,随之而来的不兼容问题就会严重阻碍项目的开发进度。

1.2. SpringBoot的概述

SpringBoot对上述Spring的缺点进行的改善和优化,基于约定优于配置的思想,可以让开发人员不必在配置与逻辑业务之间进行思维的切换,全身心的投入到逻辑业务的代码编写中,从而大大提高了开发的效率,一定程度上缩短了项目周期。

1.2.1. SpringBoot的特点

● SpringBoot不是对Spring功能上的增强,而是提供了一种快速构建Spring的方式
● 开箱即用,没有代码生成,也无需XML配置。同时也可以修改默认值来满足特定的需求
● 提供了一些大型项目中常见的非功能性特性,如嵌入式服务器(嵌入Tomcat,无需部署WAR文件)、安全、指标,健康检测、外部配置等

1.2.2. SpringBoot的核心功能

● 起步依赖
起步依赖本质上是一个Maven项目对象模型(Project Object Model,POM),定义了对其他库的传递依赖,这些东西加在一起即支持某项功能。
简单的说,起步依赖就是将具备某种功能的坐标打包到一起,并提供一些默认的功能。
● 自动配置
Spring Boot的自动配置是一个运行时(更准确地说,是应用程序启动时)的过程,考虑了众多因素,才决定Spring配置应该用哪个,不该用哪个。该过程是Spring自动完成的。
后面会详细说明起步依赖与自动配置的原理解析。

2.SpringBoot实例

2.1.创建SpringBoot简单实例

2.1.1.创建工程

项目类型: Spring Boot
名称: springboot
SpringBoot版本: 3.5.5
选择依赖: Spring Web,Lombok,Spring Boot DevTools

2.1.2.工程主启动类

@SpringBootApplication
public class SpringbootApplication {
    public static void main(String[] args) {  
        SpringApplication.run(SpringbootApplication.class, args);
    }
}

注意:

  1. @SpringBootApplication注解指定该类为SpringBoot的程序入口类。
  2. SpringBoot项目的Bean默认扫描规则是:根据启动类所在包位置从上往下扫描。
    例如:如果启动类所在的包为:com.neuedu.springboot;那么就会自动扫描com.neuedu.springboot 包及其所有子包,否则不会被扫描!
    所以,mapper、service、controller所在包是启动类所在包的子包。
  3. SpringApplication类中的run方法会对当前SpringBoot工程进行启动。

2.1.3.创建Controller

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
    public class HelloController {
        @GetMapping("/hello")
        public String say(){          //可以直接返回对象或集合,客户端将接收到json数据
            return "hello...";
        }
    }

2.1.4.测试

执行启动类中的run方法就会启动当前的SpringBoot工程。

Tomcat started on port(s): 8080 (http) with context path ''
Started SpringbootApplication in 2.44 seconds (process running for 3.598)

发送请求测试 url

http://localhost:8080/hello

注意:SpringBoot内嵌了Tomcat,所以只需要运行SpringBoot工程的主启动类即可。

2.2.SpringBoot的跨域处理

SpringBoot还给我们提供了两种跨域处理方式:
1.使用 @CrossOrigin 注解配置某一个 Controller 允许跨域AJAX请求。

//只要在此Controller上使用@CrossOrigin注解就可实现跨域访问,并可配置允许跨域的url
@CrossOrigin("*") 
@RestController
public class DeptController { }

2.定义MVC配置类实现 WebMvcConfigurer 接口中的 addCorsMappings 方法,在此方法中配置全局跨域处理。

import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableWebMvc
public class WeMvcConfig implements WebMvcConfigurer {
    /**
     * 跨域访问设置
     */
    public void addCorsMappings(CorsRegistry registry) {
        /*
         * addMapping:配置可以被跨域的路径,可以任意配置,可以具体到直接请求路径。
         * allowedOrigins:允许访问的url,可以固定单条或者多条内容
         * allowedMethods:允许的请求方式,如:POST、GET、PUT、DELETE等。
         * allowedHeaders:允许的请求header,可以自定义设置任意请求头信息。
         */
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("*")
                .allowedHeaders("*")
                .exposedHeaders("*");
    }
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        StringHttpMessageConverter converter = new StringHttpMessageConverter();
        converter.setDefaultCharset(Charset.forName("UTF-8"));
        List<MediaType> list = new ArrayList<MediaType>();
        list.add( MediaType.APPLICATION_JSON);
        converter.setSupportedMediaTypes(list);
        converters.add(converter);
        converters.add( new MappingJackson2HttpMessageConverter() );
    }
}

2.3.SpringBoot热部署

配置 IDEA 自动编译(IDE 基础设置)
即使添加了 DevTools,IDEA 默认也不会自动编译修改后的代码,需要手动开启自动编译:
步骤 1:开启“自动构建项目”
打开 IDEA 配置:文件 → 设置 → 构建, 执行, 部署 → 编译器
勾选-自动构建项目
点击 应用 保存设置
步骤 2:允许运行时自动编译
这一步是让 IDEA 在应用运行时也能自动编译,避免“应用启动后[修改代码]
打开 IDEA 配置:文件 → 设置 → 高级设置
搜索: 自动 make
勾选 即使开发的应用程序当前正在运行,也允许自动 make 启动
点击 应用 保存设置
步骤 3:调试模式运行项目

3.SpringBoot原理分析

一、核心设计思想:约定优于配置 (Convention over Configuration)
这是 Spring Boot 的灵魂。它意味着:
传统Spring的痛苦: 开发人员需要花费大量时间配置 XML 或 JavaConfig 来定义 Bean、数据源、MVC 等,虽然灵活但繁琐。
SpringBoot的解决方案: Spring Boot 预先定义好了一套“约定俗成”的默认配置。例如:

  • 默认内嵌 Tomcat 服务器。
  • 默认的配置文件名为 application.properties 或 application.yml。
  • 默认的日志配置(使用 Logback)。

好处: 开发者如果遵循这些约定,就可以用极少的配置(甚至零配置)快速启动和运行项目。如果你不想用约定,也可以通过自定义配置轻松覆盖它们。
二、核心原理:四大核心
Spring Boot 的魔法主要源于以下四个核心特性:

  1. 自动配置 (Auto-Configuration)
    这是 Spring Boot 最神奇、最核心的功能。
    Spring Boot 会在启动时自动扫描项目的 Classpath,根据你引入的依赖(JAR 包),自动为你配置 Spring 应用程序的 Bean。
  • 例子当你引入了 spring-boot-starter-web 依赖,Spring Boot 会判断:“用户想要开发一个Web应用”,于是它自动配置内嵌的 Servlet 容器、DispatcherServlet、CharacterEncodingFilter 等 Web 开发必需的 Bean。
  • 如何实现:
    @SpringBootApplication 注解中的 @EnableAutoConfiguration 是关键。
    Spring Boot 在 spring-boot-autoconfigure Jar 包下预先定义了大量自动配置类(如 ServletWebServerFactoryAutoConfiguratio)。
    流程: 应用启动 -> 检查 Classpath -> 如果存在 DataSource.class 且没有用户自己配置的 DataSource Bean -> 则执行 DataSourceAutoConfiguration 来创建一个默认的 DataSource Bean。

@SpringBootConfiguration:等同与@Configuration,既标注该类是Spring的一个配置类@EnableAutoConfiguration:SpringBoot自动配置功能开启 @ComponentScan:定义扫描路径,从中找出标识了需要装配的类,并自动装配到spring容器中

  1. 起步依赖 (Starter Dependencies)
    自动配置的基础,解决了依赖管理噩梦。
  • 是什么: 一系列预定义好的依赖描述符(POM文件)。每个 Starter 都集成了开发某个功能所需的所有依赖库,并且这些库的版本都经过了严格的兼容性测试。
  • 例子: 你不需要自己去找 Spring MVC、Tomcat、Jackson 的库并担心它们的版本兼容问题。只需引入一个 spring-boot-starter-web,它就帮你把所有东西都管理好了。
  • 好处: 极大简化了 Maven/Gradle 配置,避免了“依赖地狱”(Jar包冲突)。
  1. Actuator (监控管理)
    Spring Boot 为生产环境运行的项目提供了一套开箱即用的监控和管理功能。
  • 是什么: 通过引入 spring-boot-starter-actuator 依赖,你的应用会暴露一系列预定义的 HTTP 端点(Endpoints),如 /health(健康检查), /info(应用信息), /metrics(性能指标), /env(环境变量)等。
  • 价值: 让你能深入了解应用程序的运行状态,非常适合做监控和运维。
  1. 嵌入式容器 (Embedded Container)
    改变了Java Web应用的部署方式。
  • 是什么: Spring Boot 应用不再需要将项目打包成 WAR 包并部署到外部的 Tomcat/ Jetty 服务器中。而是将服务器(Tomcat, Jetty, Undertow)作为库直接嵌入到最终的可执行 Jar 包中。
  • 好处:
    1.简化部署: 只需要一条命令 java -jar yourapp.jar 即可启动一个完整的 Web 应用。
    2.应用自包含: 所有东西都在一个Jar包里,便于分发和云原生部署。
    3.统一性: 解决了“在我的环境是好的,为什么线上不行?”这类因环境差异导致的问题。

4.SpringBoot工程配置文件

SpringBoot是基于约定的,所以很多配置都有默认值,但如果想使用自己的配置替换默认配置的话,就可以使用SpringBoot配置文件进行配置。
SpringBoot配置文件有两种:properties文件形式、yml文件形式。SpringBoot默认会从Resources目录下加载application.properties或application.yml文件。

4.1.application.properties配置文件

下面是一个 application.properties 配置文件实例:

## 修改服务器启动端口
server.port=8080
## 设置应用程序访问上下文路径
server.servlet.context-path=/elm
## 设置SpringBoot日志输出级别(error、warn、info、debug)
logging.level.org.springframework=debug

4.2.application.yml配置文件

YML文件格式是YAML (YAML Aint Markup Language)编写的文件格式,YAML是一种直观的能够被电脑识别的数据序列化格式,并且容易被人类阅读,容易和脚本语言交互的,可以被支持YAML库的不同的编程语言程序导入,比如: C/C++, Ruby, Python, Java, Perl, C#, PHP等。YML文件是以数据为核心的,比传统的xml方式更加简洁。
YML文件的扩展名可以使用.yml或者.yaml。
下面是一个 application.yml 配置文件实例:

server:
    port: 8765
    servlet:
        context-path: /springboot

yml文件基本语法:

  1. 大小写敏感
  2. 使用缩进表示层级关系(缩进的空格数并不重要,只要相同层级的元素左对齐即可)
  3. 缩进不允许使用tab,只允许空格
  4. 冒号后必须要有一个空格
  5. 使用 # 作为注释

4.3.SpringBoot配置信息的查询

4.3.1.@Value注解

我们可以通过@Value注解,将配置文件中的值映射到一个Spring管理的Bean的属性上。

@RestController
public class HelloController {
    //server.port 就是SpringBoot配置文件中的一个值
    @Value("${server.port}")
    private int port;
    @GetMapping("/value")
    public String hello(){
        System.out.println("端口:"+port);
        return "hello" ;
    }
}

5.SpringBoot日志使用

5.1. 核心概念:Spring Boot 与 Logback

Spring Boot 默认使用 SLF4J 作为日志门面(API),并内置了 Logback 作为其默认的日志实现框架。这意味着你无需额外添加任何依赖即可开始使用。
SLF4J: 提供统一的日志接口,让你的代码与具体的日志实现解耦。
Logback: 是 Log4j 的继任者,性能更好,功能更强大。

5.2. 快速开始:基本使用

在任何需要记录日志的类中,按以下步骤操作:
1.导入 SLF4J 的 Logger 和 LoggerFactory
2.获取 Logger 实例(通常以当前类名命名)
3.使用不同级别的方法记录日志
示例

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DemoController {
    // 获取Logger实例
    private static final Logger logger = LoggerFactory.getLogger(DemoController.class);
    @GetMapping("/hello")
    public String sayHello() {
        // 记录不同级别的日志
        logger.trace("This is a TRACE log - very detailed");
        logger.debug("This is a DEBUG log - debugging info");
        logger.info("This is an INFO log - business process info");
        logger.warn("This is a WARN log - warning, but not an error");
        logger.error("This is an ERROR log - an error occurred");
        return "Hello World!";
    }
}

日志级别 (从低到高):
TRACE < DEBUG < INFO < WARN < ERROR < OFF
默认情况下,Spring Boot 的日志级别是 INFO,所以 TRACE 和 DEBUG 级别的日志不会输出。
使用 Lombok 简化代码:
如果项目使用了Lombok,可以用 @Slf4j 注解省略创建 Logger 的代码。
示例

@Slf4j // 自动注入一个名为 'log' 的 Logger
@RestController
public class DemoController {
    @GetMapping("/hello")
    public String sayHello() {
        log.info("This is done with Lombok!"); // 直接使用 log
        return "Hello";
    }
}

5.3. 日志基础配置

在application.yml中配置
1.设置日志级别

logging:
  level: # 设置日志级别
    root: INFO # 设置根日志级别
    com.neuedu.springboot: DEBUG # 设置特定包的日志级别(常用于调试)

2.日志输出到文件

logging:
  file:
    name: logs/app.log  # 日志文件路径

3.设置日志格式

logging:
  pattern:
   console: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n" # 控制台输出模式
   file: "%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n" # 文件输出模式

常用格式符说明:

  • %d: 日期时间
  • %thread: 线程名
  • %-5level: 日志级别(左对齐,固定5字符宽度)
  • %logger{36}: Logger 当前日志输出类名(最长36字符)
  • %msg: 日志消息
  • %n: 换行符

6.SpringBoot整合MyBatis

6.1.添加MyBatis相关依赖

   <!-- MyBatis Spring Boot Starter -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
       <version>3.0.5</version>
    </dependency>

    <!-- mysql数据库驱动 -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>runtime</version>
    </dependency>

6.2.新建数据库: springboot

初始化脚本

drop table if exists `user`;

create table `user`
(
    id        int primary key auto_increment,
    name  varchar(20),
    age     int ,
    email  varchar(30)
);

6.3.添加MyBatis相关配置

在application.yml配置文件中配置MyBatis相关信息

# jdbc 数据源配置
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=utf8&serverTimezone=GMT%2B8
    username: root
    password: root

# mybatis配置
mybatis:
  type-aliases-package: com.neuedu.springboot.po # po别名包
  mapper-locations: classpath:mappers/*.xml # 批量加载mapper映射文件  

6.4.创建po类

@Data
public class User {
    private Integer id;
    private String  name;
    private Integer age;
    private String  email;
}

6.5.创建mapper接口及映射文件

UserMapper.java

import com.neuedu.springboot.po.User;
import org.apache.ibatis.annotations.*;
import java.util.List;

public interface UserMapper {
    @Insert("insert into `user`(name,age,email) values (#{name},#{age},#{email})")
    int insert(User user);
    @Delete("delete from `user` where id=#{id}")
    int deleteBId(Integer id);
    @Update("update `user` set name=#{name},age=#{age},email=#{email} where id=#{id}")
    int update(User user);
    @Select(" select * from `user`")
    List<User> selectAll();
    @Select(" select * from `user` where id=#{id}")
    User selectById(Integer id);

    List<User> select(User user);
}

UserMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.neuedu.springboot.mapper.UserMapper">
    <select id="select" parameterType="user" resultType="user">
        select * from `user`
        <where>
            <if test="id!=null">
                and id=#{id}
            </if>
            <if test="name!=null and name!=''">
                and name like concat('%',#{name},'%')
            </if>
        </where>
    </select>
</mapper>

6.6.创建service接口与实现类

UserService

import com.neuedu.springboot.po.User;
import java.util.List;

public interface UserService {
    String addUser(User user);
    String updateUser(User user);
    String deleteUser(int id);
    List<User> queryAllUsers();
    User queryUserById(int id);
    List<User> query(User user);
}

UserServiceImpl

import com.neuedu.springboot.mapper.UserMapper;
import com.neuedu.springboot.po.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper mapper;

    @Override
    public String addUser(User user) {
        return mapper.insert(user)==1?"新增成功":"新增失败";
    }

    @Override
    public String updateUser(User user) {
        return mapper.update(user)==1?"修改成功":"修改失败";
    }

    @Override
    public String deleteUser(int id) {
        return mapper.deleteById(id)==1?"删除成功":"删除失败";
    }

    @Override
    public List<User> queryAllUsers() {
        return mapper.selectAll();
    }

    @Override
    public User queryUserById(int id) {
        return mapper.selectById(id);
    }

    @Override
    public List<User> query(User user) {
        return mapper.select(user);
    }
}

6.7.创建响应结果封装类

Result

import lombok.Builder;
import lombok.Data;

@Data
@Builder
public class Result<T> {
    private int code;       // 状态码
    private String msg;     // 消息
    private T data;         // 数据

    // 成功静态方法
    public static <T> Result<T> success(T data) {
        return Result.<T>builder()
                .code(200)
                .msg("success")
                .data(data)
                .build();
    }

    // 失败静态方法
    public static <T> Result<T> error(int code, String msg) {
        return Result.<T>builder()
                .code(code)
                .msg(msg)
                .build();
    }
}

6.8.创建controller

UserController

import com.neuedu.springboot.po.User;
import com.neuedu.springboot.response.Result;
import com.neuedu.springboot.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private  UserService service;

    @GetMapping
    public Result< List<User> > queryAll(){
        List<User> list = service.queryAllUsers();
        return Result.success(list);
    }

    @GetMapping("/{id}")
    public Result<User> queryById(@PathVariable("id") int id){
        User user = service.queryUserById(id);
        return Result.success(user);
    }

    @PostMapping("/select")
    public Result< List<User> > query(@RequestBody User user){
        List<User> list = service.query(user);
        return Result.success(list);
    }

    @PostMapping
    public Result<String> add (@RequestBody User user) {
       String result = service.addUser(user);
       return Result.success(result);
    }

    @PutMapping
    public Result<String> update (@RequestBody User user) {
        String result = service.updateUser(user);
        return Result.success(result);
    }
    @DeleteMapping("/{id}")
    public Result<String> delete (@PathVariable("id") int id) {
        String result = service.deleteUser(id);
        return Result.success(result);
    }
   @PostMapping("/query")
    public Result<List<User>> query(@RequestBody User user  ) {
        List<User> list = service.query(user);
        return Result.success(list);
    }
}

6.9.修改SpringbootApplication启动类

@SpringBootApplication
@MapperScan("com.neuedu.springboot.mapper")
public class SpringbootApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }
}

@MapperScan 是 MyBatis 框架中的一个重要注解,注解用于配置 MyBatis的mapper接口扫描路径

6.11.测试

使用ApiFox发送请求测试

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容