一个基础的SpringBoot应用

6029 字
16 分钟

爱是需要付出代价,爱是需要担当,爱是需要努力争取,爱是需要你为了对方而放弃一些事情,并改变自己。

—— 《悬崖上的金鱼公主》

创建SpringBoot项目

SpringBoot框架是基于Spring基础上开发的一款帮助我们快速开发一个Spring应用的框架。在vscode中,我们可以借助Spring Initializr Java Support插件自动化的创建一个SpringBoot应用:

1746788071910

Packet name

简单选择一下版本和语言,最后在输入一个Packet Name:

1746788427287

我们将前两段当作组织名(GroupId):top.ulna,通常为反向域名。

最后一段 ArtifactId,即其中的 .test

主要用途:

  • GroupidArtifactId 组成了项目的唯一标识符。
  • 不同的 Groupid用来区分不同来源的库。
  • 依赖声明:GroupidArtifactId是引入依赖的重要依据。

Dependencies

我们这里介绍几个经常使用的基础插件,博主也是萌新不一定全,也不一定常用(T_T):

spring-boot-starter-web

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

作用

  • 这是构建 Web 应用(包括 RESTful API)的核心依赖。
  • 包含以下组件:
    • Spring MVC :用于处理 HTTP 请求和响应。
    • Embedded Tomcat :内置的 Tomcat 服务器,用于运行应用。
    • Jackson :用于对象与 JSON 的序列化和反序列化。
    • Validation API :支持数据验证功能。

典型场景

  • 开发 RESTful 服务、Web 应用或 API。

spring-boot-configuration-processor

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>

作用

  • 用于处理自定义配置属性的注解,帮助生成配置元数据文件。
  • 主要用于开发过程中为 application.propertiesapplication.yml 文件中的自定义配置提供自动补全和提示。

spring-boot-devtools

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

作用

  • 用于提升开发效率的工具,提供以下功能:
    • 自动重启 :当项目中的代码或文件发生更改时,应用会自动重启。
    • LiveReload :支持浏览器页面的实时刷新。
    • 禁用缓存 :在开发环境中禁用模板(如 Thymeleaf)的缓存。
    • 全局属性支持 :支持全局设置,提升开发体验。

注意

  • 该依赖仅在开发环境中生效,生产环境中不会加载。

典型场景

  • 开发过程中频繁修改代码时,减少手动重启的麻烦。

spring-boot-starter-test

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

作用

  • 提供 Spring Boot 应用的测试工具包,包括单元测试和集成测试。
  • 包含以下测试工具和框架:
    • JUnit 5 :单元测试框架。
    • AssertJ :流式断言库,提供更强大的断言功能。
    • Mockito :用于模拟依赖对象的测试库。
    • Hamcrest :匹配器库,提供灵活的断言机制。
    • Spring Test :支持测试 Spring 上下文和依赖注入。
    • JSONassert :用于断言 JSON 结构是否符合预期。
    • XmlUnit :用于断言 XML 内容是否符合预期。

典型场景

  • 让ai写个测试,然后看看测试结果

项目目录

以我创建包:com.example.demo 为例:

demo/
├── .mvn/
│   └── wrapper/
│       └── maven-wrapper.properties
├── .vscode/
│   └── NEWLY_CREATED_BY_SPRING_INITIALIZR
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/
│   │   │       └── example/
│   │   │           └── demo/
│   │   │               └── DemoApplication.java
│   │   └── resources/
│   │       ├── application.properties
│   │       ├── static/
│   │       └── templates/
│   └── test/
│       └── java/
│           └── com/
│               └── example/
│                   └── demo/
│                       └── DemoApplicationTests.java
├── .gitattributes
├── HELP.md
├── mvnw
├── mvnw.cmd
└── pom.xml

SpringBoot项目在Maven项目的基础上创建。

而SpringBoot目录下我们通常采取如下规范进行编码:

src/
├── main/
│   ├── java/
│   │   └── com/example/demo/
│   │       ├── DemoApplication.java    // 启动类
│   │       ├── controller/             // 控制器层
│   │       ├── service/                // 服务层
│   │       ├── repository/             // 数据访问层
│   │       └── model/                  // 实体类
│   ├── resources/
│       ├── application.properties      // 配置文件
│       ├── static/                     // 静态资源(HTML, CSS, JS 等)
│       ├── templates/                  // 模板文件(如 Thymeleaf 模板)
│       └── public/                     // 公共资源
├── test/
│   ├── java/                           // 测试代码

SpringBoot应用

Spring中,每一层的作用是为了实现应用的分层架构,遵循单一职责原则,使代码更易于维护、测试和扩展。以下是各层的作用说明以及如何组织代码的说明。

1.启动类(DemoApplication.java)

作用:

  • 项目的入口,负责启动SpringBoot应用。
  • 初始化Spring容器,并加载所有的配置和Bean。

Bean 是由 Spring 容器管理的对象,用于实现依赖注入和组件化管理,是应用程序的核心构建模块。

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

2.控制器层(Controller)

作用:

  • 接收用户的HTTP请求并返回响应。
  • 处理请求参数和调用服务层。
  • 是应用程序的入口点,负责将用户输入传递给服务层。
  • 使用 @RestController 返回Json,或 @Controller返回视图。
package com.example.demo.controller;

import com.example.demo.service.HelloService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    private final HelloService helloService;

    @Autowired	//自动注入Service类
    public HelloController(HelloService helloService) {
        this.helloService = helloService;
    }

    @GetMapping("/hello")
    public String sayHello(@RequestParam String name) {
        return helloService.getGreeting(name);  // 调用服务层
    }
}

3.服务层(Service)

作用:

  • 封装业务逻辑
  • 调用数据访问层处理数据,并将结果返回给Controller。
  • 是业务规则实现的核心,独立于控制器和数据访问层。
package com.example.demo.service;

import org.springframework.stereotype.Service;

@Service
public class HelloService {
    public String getGreeting(String name) {
        return "Hello, " + name + "!";
    }
}

4.数据访问层(Respository)

作用:

  • 负责与数据库交互,执行CRUD操作。
  • 使用Spring Data JPA 或其他持久化工具
  • 数据访问层只关心数据的存储和检索,不关心其他业务逻辑。
  • CRUD:即创建(Create)、读取(Read)、更新(Update)、删除(Delete)。
  • 持久化:将应用程序对象的状态保存到数据库的过程。
package com.example.demo.repository;

import com.example.demo.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
    User findByUsername(String username);  // 根据用户名查询用户
}

5.实体类(Model)

作用:

  • 定义数据库表对应的实体
  • 用于封装数据(通常是业务数据)
  • 使用JPA注解(如 @Entity@Id@Column)定义实体和数据库表的映射关系。
package com.example.demo.model;

import jakarta.persistence.*;

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(unique = true, nullable = false)
    private String username;

    @Column(nullable = false)
    private String password;

    // Getters and Setters
    public Long getId() {
        return id;
    }
    public void setId(Long id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

6.配置文件(application.properties/application.yml)

作用:

  • 配置应用程序的属性,如端口号,数据库连接,日志级别等。
# 应用程序名称
spring.application.name=demo

# 服务器端口
server.port=8080

# 数据库配置
spring.datasource.url=jdbc:mysql://localhost:3306/demo
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.hibernate.ddl-auto=update

7.静态资源(static)

作用:

  • 存放静态文件,如HTML、CSS、JavaScript,图片等。
  • Spring Boot默认会将 static/目录下的资源直接暴露为公共URL。

假设资源路径为:

src/main/resources/static/css/style.css

则获取资源的URL为:

http://localhost:8080/css/style.css

8.模板文件(templates)

作用:

  • 存放动态生成的HTML文件,通常配合模板引擎如(Thymeleaf)使用。

9.测试代码

作用:编写单元测试和集成测试,确保应用功能的正确性。

package com.example.demo;

import com.example.demo.controller.HelloController;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class HelloControllerTest {

    @Test
    void testSayHello() {
        HelloController controller = new HelloController(name -> "Hello, " + name + "!");
        String response = controller.sayHello("John");
        assertEquals("Hello, John!", response);
    }
}