在Java后端开发领域,SpringBoot无疑是最受欢迎的技术框架之一。其通过"约定优于配置"的理念,极大地简化了Spring应用的初始搭建和开发过程。这种简化不仅体现在代码层面,更深刻地改变了Java Web应用的部署范式------SpringBoot与Tomcat形成的嵌入式集成关系,将传统需要独立安装配置的应用服务器直接内置于应用之中,使得复杂的Web应用部署转变为简单的可执行JAR包运行。
回顾传统的Java Web开发,开发者需要经历繁琐的环境配置:独立安装Tomcat服务器、配置server.xml、部署WAR包、管理应用服务器生命周期。而SpringBoot的革命性设计彻底改变了这一局面,其默认将Tomcat作为内置服务器 打包在应用中,让每个SpringBoot应用都成为一个自包含、可独立运行的执行单元。这种设计带来了真正的开箱即用 体验------开发者无需单独安装配置Tomcat,只需一行java -jar命令即可启动完整的Web服务。
本文我们将基于SpringBoot+Gradle技术栈,从零开始构建一个简单的HTTP服务,逐步实现从项目初始化、API开发、业务逻辑构建到最终部署上线的全流程。
一、环境准备
首先选择一个适合自己的集成开发环境,例如IntelliJ IDEA或VSCode,并使用对应的开发环境创建一个SpringBoot应用程序。
我创建的Demo程序应用结构如下所示:
bash
SpringBootDemo/
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/xiaxl/demo/
│ │ │ ├── DemoApplication.java
│ │ │ └── controller/
│ │ └── resources/
│ │ └── application.properties
│ └── test/
├── build.gradle
└── settings.gradle
settings.gradle 是Gradle的项目设置文件,用于定义项目的基本信息和模块配置,这里定义了项目的根模块名称。
bash
# 项目名称,影响构建产物的命名
rootProject.name = 'SpringBootDemo'
build.gradle 是Gradle构建脚本的核心文件,定义了项目的构建配置、依赖管理和插件应用。
bash
plugins {
# 应用Java插件,提供编译、测试、打包等任务
id 'java'
# SpringBoot插件,提供bootJar、bootRun等任务
id 'org.springframework.boot' version '3.3.3'
# 依赖管理插件,简化Spring依赖版本管理
id 'io.spring.dependency-management' version '1.1.6'
}
group = 'com.xiaxl' # 组织标识,通常使用公司域名
version = '0.0.1-SNAPSHOT' # 项目版本,SNAPSHOT表示开发中版本
java {
toolchain {
languageVersion = JavaLanguageVersion.of(23) # 指定JDK版本为23
}
}
repositories {
// 配置国内镜像加速依赖下载(按需使用)
maven { url 'https://maven.aliyun.com/nexus/content/groups/public/' }
maven { url 'https://mirrors.cloud.tencent.com/nexus/repository/maven-public/' }
maven { url 'https://developer.huawei.com/repo/' }
// maven仓库
mavenCentral()
}
dependencies {
// 核心依赖:SpringBoot Web Starter,包含:
// - Spring MVC (Web框架)
// - Tomcat (嵌入式Web服务器)
// - Jackson (JSON处理)
// - 验证、数据绑定等
// Spring Boot Web Starter
implementation 'org.springframework.boot:spring-boot-starter-web'
// 数据校验
implementation 'org.springframework.boot:spring-boot-starter-validation'
// Lombok简化代码
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
//
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
useJUnitPlatform()
}
// 可选:配置JAR包输出名称
bootJar {
archiveFileName = 'springboot-demo.jar'
}
application.properties 是Spring Boot应用的核心配置文件,用于定义应用的各种配置参数,如服务器端口、应用名称、数据库连接等。
java
spring.application.name=SpringBootDemo # 应用名称
spring.servlet.multipart.max-file-size=-1 # 单个文件大小限制,-1表示不限制
spring.servlet.multipart.max-request-size=-1 # 请求总大小限制,-1表示不限制
server.port=8081 # 服务端口
DemoApplication.java SpringBoot 是Spring Boot应用的主启动类,是应用程序的入口点。通过@SpringBootApplication注解标记,包含了自动配置、组件扫描等Spring Boot核心功能。
java
package com.xiaxl.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// 使用@SpringBootApplication注解标记该类为Spring Boot应用的主配置类
@SpringBootApplication
public class DemoApplication {
// main方法是Java应用程序的入口点
// 当JVM启动时,首先执行这个方法
// args参数用于接收命令行参数
public static void main(String[] args) {
// SpringApplication.run()是启动Spring Boot应用的核心方法
// 第一个参数:主配置类(通常是带有@SpringBootApplication注解的类)
// 第二个参数:命令行参数,会传递给Spring应用上下文
// 这个方法执行以下操作:
// 1. 创建Spring应用上下文(ApplicationContext)
// 2. 启用自动配置
// 3. 启动嵌入式Web服务器(如Tomcat)
// 4. 扫描并注册所有Spring组件
// 5. 返回应用上下文对象(此处未接收返回值)
SpringApplication.run(DemoApplication.class, args);
}
}
HelloController
创建一个HelloController,用于验证环境是否OK。
java
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
// 访问地址:GET http://localhost:8081/api/hello
// @RestController:标记这个类为一个 REST 控制器,意味着类中的方法会处理 HTTP 请求并返回数据。
@RestController
public class HelloController {
@GetMapping("/api/hello")
public HelloResponse getHelloMessages() {
HelloResponse response = new HelloResponse();
response.setStartupMessage("欢迎来到精彩世界!");
response.setNewMessages(Arrays.asList("望长城内外惟余莽莽,大河上下顿失滔滔。"));
response.setStatusCode(200);
return response;
}
public static class HelloResponse {
private String startupMessage;
private List<String> newMessages;
private int statusCode;
public String getStartupMessage() {
return startupMessage;
}
public void setStartupMessage(String startupMessage) {
this.startupMessage = startupMessage;
}
public List<String> getNewMessages() {
return newMessages;
}
public void setNewMessages(List<String> newMessages) {
this.newMessages = newMessages;
}
public int getStatusCode() {
return statusCode;
}
public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}
public void addNewMessage(String message) {
if (this.newMessages == null) {
this.newMessages = new ArrayList<>();
}
this.newMessages.add(message);
}
}
}
使用示例: 访问 http://localhost:8081/api/hello

二、基础接口实现
掌握 SpringBoot 基础环境构建后,将学习如何实现常用的 HTTP 接口。涵盖 GET 和 POST 两种最常用的 HTTP 方法。
ApiResponse.java - 统一响应格式封装类
在构建 RESTful API 时,保持统一的响应格式非常重要。这有助于提高代码的可维护性。这里我们创建一个通用的 ApiResponse类来封装所有接口的响应。
这个类用于标准化所有 API 接口的响应格式,包含成功状态、消息、数据、时间戳和状态码,确保前后端交互的一致性。
java
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
// 使用Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@Data
// 生成无参构造函数
@NoArgsConstructor
// 生成全参构造函数
@AllArgsConstructor
// Jackson序列化注解:当字段值为null时,不包含在JSON输出中。这样可以减少响应体大小,避免前端处理null值。
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ApiResponse<T> {
private boolean success;
private String message;
private T data;
private LocalDateTime timestamp;
private Integer code;
// 成功响应快捷方法
public static <T> ApiResponse<T> success(T data) {
return new ApiResponse<>(true, "操作成功", data, LocalDateTime.now(), 200);
}
public static <T> ApiResponse<T> success(String message, T data) {
return new ApiResponse<>(true, message, data, LocalDateTime.now(), 200);
}
// 失败响应快捷方法
public static <T> ApiResponse<T> error(String message) {
return new ApiResponse<>(false, message, null, LocalDateTime.now(), 500);
}
public static <T> ApiResponse<T> error(String message, Integer code) {
return new ApiResponse<>(false, message, null, LocalDateTime.now(), code);
}
}
UserDTO.java - 用户数据传输对象
为了在不同层之间传递数据,我们使用 DTO(Data Transfer Object)模式。UserDTO类用于封装用户相关的数据传输。
这个类定义了用户数据的结构,包含用户的基本信息和业务字段,支持链式调用提高代码可读性。
java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
import java.util.List;
// 使用Lombok注解自动生成getter、setter、toString、equals和hashCode方法
@Data
// 生成无参构造函数
@NoArgsConstructor
// 生成全参构造函数
@AllArgsConstructor
// 使用Lombok的@Accessors注解,开启链式调用(chain = true)。
// 使得setter方法返回当前对象,可以连续调用。如:user.setId(1L).setName("张三")
@Accessors(chain = true) // 支持链式调用
public class UserDTO {
private Long id;
private String name;
private String email;
private Integer age;
private String phone;
private String address;
private Boolean active;
private LocalDateTime createTime;
private LocalDateTime updateTime;
private List<String> roles;
// 静态工厂方法
public static UserDTO createDefault() {
return new UserDTO()
.setId(1L)
.setName("张三")
.setEmail("zhangsan@example.com")
.setAge(25)
.setPhone("13800138000")
.setAddress("北京市海淀区")
.setActive(true)
.setCreateTime(LocalDateTime.now())
.setUpdateTime(LocalDateTime.now())
.setRoles(List.of("USER", "EDITOR"));
}
}
UserController.java - 用户控制器基类
下面创建控制器基类,并初始化一些模拟数据用于演示。在实际项目中,这些数据通常来自数据库。
这是处理用户相关请求的控制器,使用内存 Map 模拟数据库存储,包含数据初始化方法。
java
import com.xiaxl.demo.model.response.ApiResponse;
import com.xiaxl.demo.model.response.UserDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@RestController
public class UserController {
// 内存存储模拟数据(替代数据库)
private final Map<Long, UserDTO> mUserMap = new HashMap<>();
private Long idCounter = 1L;
// 初始化一些测试数据
public UserController() {
initMockData();
}
private void initMockData() {
for (int i = 1; i <= 3; i++) {
UserDTO user = new UserDTO()
.setId((long) i)
.setName("用户" + i)
.setEmail("user" + i + "@example.com")
.setAge(20 + i)
.setPhone("1380013800" + i)
.setAddress("地址" + i)
.setActive(true)
.setCreateTime(LocalDateTime.now())
.setUpdateTime(LocalDateTime.now())
.setRoles(List.of("USER"));
mUserMap.put(user.getId(), user);
idCounter++;
}
}
}
1. GET 接口
GET 请求是 HTTP 方法中最常用的一种,主要用于从服务器请求数据。在实际的 Web 开发中,根据不同的数据检索需求,GET 接口的实现也分为多种形式。本文将详细介绍三种最常见的 GET 接口实现方式。
1.1 基础 GET 接口
这种接口用于获取某一类资源的完整集合或列表,通常不需要任何输入参数。它是最简单、最直接的 GET 接口形式,适用于像"获取所有用户"、"查询所有文章"这样的场景。
关键注解 :@GetMapping用于将 HTTP GET 请求映射到特定的控制器方法。
java
/**
* 简单的GET请求 - 获取所有用户列表
* 访问地址:GET http://localhost:8081/api/users
*/
@GetMapping("/api/users")
public ResponseEntity<ApiResponse<List<UserDTO>>> getAllUsers() {
log.info("获取所有用户列表");
List<UserDTO> userList = new ArrayList<>(mUserMap.values());
return ResponseEntity.ok(ApiResponse.success("获取用户列表成功", userList));
}
使用示例:
- 访问
http://localhost:8081/api/users

1.2 路径参数 GET 接口
实际开发中,我们经常需要获取某个特定ID(或唯一标识)的资源详情。这时,将标识符作为URL路径的一部分(路径参数)是最佳实践。这种方式语义清晰,符合RESTful架构风格。
关键注解 :@PathVariable用于将URL中的模板变量绑定到方法的参数上。
java
/**
* GET请求 - 根据ID获取单个用户
* 访问地址:GET http://localhost:8081/api/users/{id}
* 例如:GET http://localhost:8081/api/users/1
*/
@GetMapping("/api/users/{id}")
public ResponseEntity<ApiResponse<UserDTO>> getUserById(@PathVariable Long id) {
log.info("根据ID查询用户,ID: {}", id);
UserDTO user = mUserMap.get(id);
if (user == null) {
return ResponseEntity
.status(HttpStatus.NOT_FOUND)
.body(ApiResponse.error("用户不存在", 404));
}
return ResponseEntity.ok(ApiResponse.success("获取用户成功", user));
}
- 访问
http://localhost:8081/api/users/1

1.3 查询参数 GET 接口
实际开发中,对于复杂的检索需求,例如根据多个条件过滤结果或进行分页查询,使用查询参数是最灵活的方式。查询参数以 ?开始,以 key=value的形式拼接在URL后面,多个参数用 &连接。这种接口非常适合实现搜索功能。
关键注解 :@RequestParam用于将请求参数绑定到控制器的方法参数。required=false表示参数非必填,defaultValue提供默认值。
java
/**
* GET请求 - 带查询参数的用户搜索
* 访问地址:GET http://localhost:8081/api/users/search?name=用户1&active=true
*/@GetMapping("/api/users//search")
public ResponseEntity<ApiResponse<List<UserDTO>>> searchUsers(
@RequestParam(required = false) String name,
@RequestParam(required = false) Boolean active,
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size) {
log.info("搜索用户 - name: {}, active: {}, page: {}, size: {}",
name, active, page, size);
List<UserDTO> result = mUserMap.values().stream()
.filter(user -> name == null || user.getName().contains(name))
.filter(user -> active == null || user.getActive().equals(active))
.skip((page - 1) * (long) size)
.limit(size)
.toList();
return ResponseEntity.ok(ApiResponse.success("搜索成功", result));
}
- 访问
http://localhost:8081/api/users/search?name=用户1&active=true

2. POST接口
POST 请求用于向服务器提交数据,通常用于创建新资源。在RESTful架构中,POST方法对应CRUD中的Create操作,用于向服务器添加新的资源。
在正式开始介绍前,先介绍一个UserRequest类,这是一个数据验证DTO(Data Transfer Object)类,用于接收和验证前端传递的用户创建请求数据。
UserRequest.java
UserRequest通过Jakarta Validation API提供了字段级别的数据验证规则,确保输入数据的合法性。
java
import jakarta.validation.constraints.*;
import lombok.Data;
@Data
// 用户创建请求DTO(Data Transfer Object)类
// 用于接收前端传递的用户创建请求数据
// 包含各种验证注解,确保数据合法性
public class UserRequest {
@NotBlank(message = "用户名不能为空")
@Size(min = 2, max = 20, message = "用户名长度必须在2-20个字符之间")
private String name;
@NotBlank(message = "邮箱不能为空")
@Email(message = "邮箱格式不正确")
private String email;
@NotNull(message = "年龄不能为空")
@Min(value = 1, message = "年龄必须大于0")
@Max(value = 150, message = "年龄不能超过150")
private Integer age;
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
@NotBlank(message = "地址不能为空")
private String address;
private String remark;
@AssertTrue(message = "必须同意用户协议")
private Boolean agreeTerms;
}
2.1 POST 接口处理 JSON 数据
以下举例展示如何处理 JSON 格式的 POST 请求。JSON是目前RESTful API最常用的数据交换格式,具有结构清晰、跨平台、易于解析的优点。本接口演示了完整的用户创建流程,包括参数验证、业务逻辑处理和响应返回。
java
/**
* POST请求 - 创建用户(JSON格式请求体)
* 访问地址:POST http://localhost:8081/api/post/users
* 请求头:Content-Type: application/json
* 请求体示例:
* {
* "name": "李四",
* "email": "lisi@example.com",
* "age": 30, * "phone": "13900139000",
* "address": "上海市浦东新区",
* "agreeTerms": true
* }
* @param request 接收并验证请求体中的JSON数据,自动反序列化为UserRequest对象,
* Valid注解触发对UserRequest对象中字段的验证规则
* @param bindingResult 接收参数验证结果,包含所有验证错误信息
* @return ApiResponse<UserDTO>
*/
@PostMapping("/api/post/users")
public ResponseEntity<ApiResponse<UserDTO>> createUser(
@Valid @RequestBody UserRequest request,
BindingResult bindingResult) {
log.info("创建用户 - 请求数据: {}", request);
// 参数校验
if (bindingResult.hasErrors()) {
Map<String, String> errors = new HashMap<>();
for (FieldError error : bindingResult.getFieldErrors()) {
errors.put(error.getField(), error.getDefaultMessage());
}
return ResponseEntity
.badRequest()
.body(ApiResponse.error(errors.toString(), 400));
}
// 检查用户名是否已存在
boolean exists = mUserMap.values().stream()
.anyMatch(user -> user.getName().equals(request.getName()));
if (exists) {
return ResponseEntity
.badRequest()
.body(ApiResponse.error("用户名已存在", 400));
}
// 创建用户
UserDTO newUser = new UserDTO()
.setId(idCounter++)
.setName(request.getName())
.setEmail(request.getEmail())
.setAge(request.getAge())
.setPhone(request.getPhone())
.setAddress(request.getAddress())
.setActive(true)
.setCreateTime(LocalDateTime.now())
.setUpdateTime(LocalDateTime.now())
.setRoles(List.of("USER"));
mUserMap.put(newUser.getId(), newUser);
log.info("用户创建成功,ID: {}", newUser.getId());
return ResponseEntity
.status(HttpStatus.CREATED)
.body(ApiResponse.success("用户创建成功", newUser));
}
使用 Postman 测试:
bash
POST http://localhost:8081/api/post/users
Headers:Content-Type: application/json
Body:
{
"name":"李四",
"email":"lisi@example.com",
"age":30,
"phone":"13900139000",
"address":"上海市浦东新区",
"agreeTerms":true
}

2.2 POST 接口处理表单请求
除了 JSON 格式,表单提交是另一种常见的 POST 请求方式,常用于文本表单提交。表单提交通常用于传统的Web应用,通过application/x-www-form-urlencoded格式传递键值对数据。这种方式适合简单的数据传输,如登录、搜索等场景。
java
/**
* POST表单请求 - 用户登录(application/x-www-form-urlencoded)
* 访问地址:POST http://localhost:8081/api/users/login
* 请求头:Content-Type: application/x-www-form-urlencoded
* 请求体:name=张三&password=123456
*/
@PostMapping(value = "/api/users/login", consumes = "application/x-www-form-urlencoded")
public ResponseEntity<ApiResponse<Map<String, Object>>> login(
@RequestParam String name,
@RequestParam String password) {
log.info("用户登录 - name: {}", name);
// 模拟用户验证
Optional<UserDTO> userOptional = mUserMap.values().stream()
.filter(user -> user.getName().equals(name))
.findFirst();
if (userOptional.isEmpty()) {
return ResponseEntity
.badRequest()
.body(ApiResponse.error("用户名或密码错误", 401));
}
// 模拟密码验证(实际项目中使用加密验证)
UserDTO user = userOptional.get();
if (!"123456".equals(password)) { // 模拟固定密码
return ResponseEntity
.badRequest()
.body(ApiResponse.error("用户名或密码错误", 401));
}
// 生成模拟token
String token = "Bearer " + UUID.randomUUID();
Map<String, Object> loginResult = new HashMap<>();
loginResult.put("user", user);
loginResult.put("token", token);
loginResult.put("expiresIn", 3600);
log.info("用户登录成功,生成token: {}", token);
return ResponseEntity.ok(ApiResponse.success("登录成功", loginResult));
}
使用 Postman 测试:
bash
POST http://localhost:8081/api/users/login
Headers:Content-Type: application/x-www-form-urlencoded
Body:name=张三&password=123456

2.3 POST 接口文件请求
文件上传是Web应用中常见的功能,通过multipart/form-data格式支持二进制文件传输。这种方式允许在单个请求中同时传输文本字段和二进制文件,非常适合需要上传图片、文档等文件的场景。
java
/**
* 处理多个文件POST上传
* POST http://localhost:8081/api/uploadFiles
* Content-Type: multipart/form-data; boundary=4235013262151947840 * <p>
* ----4235013262151947840
* Content-Disposition: form-data; name="files"; filename="111.png" * Content-Type: image/png * <p>
* 111.png字节流数据
* ----4235013262151947840
* Content-Disposition: form-data; name="files"; filename="222.png" * Content-Type: image/png * <p>
* 222.png字节流数据
* ----4235013262151947840
* * @param files 文件列表
* @return
*/
@PostMapping("/api/uploadFiles")
public ResponseEntity<ApiResponse<List<String>>> uploadFiles(@RequestParam("files") MultipartFile[] files) {
// 创建一个列表
List<String> fileUris = new ArrayList<>();
// 循环输入的文件
for (MultipartFile file : files) {
try {
// 获取并清理文件名
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
// 构建文件上传路径
Path uploadPath = Paths.get(UPLOAD_DIR + fileName);
// 创建上传目录
File uploadDir = new File(UPLOAD_DIR);
if (!uploadDir.exists()) {
uploadDir.mkdirs();
}
// 创建输出流,写入文件
try (FileOutputStream fos = new FileOutputStream(uploadPath.toFile())) {
fos.write(file.getBytes());
}
// 上传后的文件路径
String fileUri = UPLOAD_DIR + fileName;
// 缓存到文件列表中
fileUris.add(fileUri);
} catch (IOException e) {
e.printStackTrace();
return ResponseEntity
.badRequest()
.body(ApiResponse.error(e.getMessage(), 500));
}
}
return ResponseEntity.ok(ApiResponse.success("上传成功", fileUris));
}
使用 Postman 测试:
bash
POST http://localhost:8081/api/uploadFiles
Content-Type: multipart/form-data; boundary=4235013262151947840
----4235013262151947840
Content-Disposition: form-data; name="files"; filename="111.png"
Content-Type: image/png
111.png字节流数据
----4235013262151947840
Content-Disposition: form-data; name="files"; filename="222.png"
Content-Type: image/png
222.png字节流数据
----4235013262151947840

三、数据库集成
在现代Web应用开发中,数据库集成是至关重要的一环。Spring Boot通过Spring Data JPA提供了简洁高效的数据访问解决方案,可以大大减少样板代码的编写。本章将详细介绍如何在Spring Boot项目中集成SQLite数据库,并实现完整的用户管理功能。
本示例使用SQLite,因为它无需单独安装数据库服务器,且数据存储在单一文件中,便于开发和测试。同时,我们将采用分层架构设计,确保代码的可维护性和扩展性。
1. 环境准备
在开始编码之前,需要配置项目依赖和数据库连接。以下是具体的配置步骤:
build.gradle 添加SQLite数据库相关依赖库,这些依赖将为我们提供数据库连接、JPA支持以及必要的工具类。
bash
dependencies {
// SQLite数据库(关键依赖)
implementation 'org.xerial:sqlite-jdbc:3.45.1.0'
// 添加以下依赖以支持SQLite方言
implementation 'org.hibernate.orm:hibernate-community-dialects:6.3.1.Final'
// Spring Data JPA
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
// JSON序列化
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310'
}
application.properties 添加数据库相关配置,这些配置项定义了数据库连接参数、JPA行为以及SQL日志输出等设置。
bash
spring.datasource.url=jdbc:sqlite:demo.db
spring.datasource.driver-class-name=org.sqlite.JDBC
spring.datasource.username=admin
spring.datasource.password=123456
spring.jpa.database-platform=org.hibernate.community.dialect.SQLiteDialect
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.community.dialect.SQLiteDialect
spring.sql.init.mode=never
DemoApplication.java 增加注解EnableJpaRepositories,启用JPA仓库功能,这是Spring Data JPA的核心配置。
java
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
@SpringBootApplication
@EnableJpaRepositories
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
UserEntity.java 创建一个UserEntity类,该类对应数据库中的users表,使用JPA注解定义实体与表的映射关系。
java
import jakarta.persistence.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.AllArgsConstructor;
import java.time.LocalDateTime;
import java.util.List;
@Entity
@Table(name = "users")
@Data
// 生成无参构造函数
@NoArgsConstructor
// 生成全参构造函数
@AllArgsConstructor
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, unique = true)
private String name;
@Column(nullable = false)
private String email;
private String password;
@Column(name = "nick_name")
private String nickname;
private Integer age;
private String phone;
private String address;
private Boolean active;
private List<String> roles;
@Column(name = "create_time")
private LocalDateTime createTime;
@Column(name = "update_time")
private LocalDateTime updateTime;
// 自动设置时间
@PrePersist
protected void onCreate() {
createTime = LocalDateTime.now();
updateTime = LocalDateTime.now();
}
@PreUpdate
protected void onUpdate() {
updateTime = LocalDateTime.now();
}
}
UserDbController
创建一个UserDbController,作为用户管理的RESTful API控制器,处理HTTP请求并调用服务层方法。
java
import com.xiaxl.demo.model.response.ApiResponse;
import com.xiaxl.demo.model.response.UserDTO;
import com.xiaxl.demo.model.request.UserRequest;
import com.xiaxl.demo.service.UserService;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@Slf4j
@RestController
// Lombok注解,自动生成一个包含所有final字段的构造函数
// 这通常用于依赖注入,Spring会自动调用此构造函数注入所需的依赖
public class UserDbController {
// 声明一个UserService类型的final常量,使用依赖注入方式初始化
// UserService是Spring Data JPA接口,用于操作用户数据表
// final关键字确保该引用在构造函数初始化后不能被修改
private final UserService mUserService;
// 使用构造器注入(推荐)
@Autowired
public UserDbController(UserService userService) {
this.mUserService = userService;
}
}
UserService
创建一个UserService,作为业务逻辑层,处理用户相关的业务操作,包括数据转换和业务规则验证。
java
import com.xiaxl.demo.model.db.UserEntity;
import com.xiaxl.demo.model.response.ApiResponse;
import com.xiaxl.demo.model.response.UserDTO;
import com.xiaxl.demo.model.request.UserRequest;
import com.xiaxl.demo.repository.UserRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
public class UserService {
// 声明一个UserRepository类型的final常量,使用依赖注入方式初始化
// UserRepository是Spring Data JPA接口,用于操作用户数据表
// final关键字确保该引用在构造函数初始化后不能被修改
private final UserRepository mUserRepository;
// 使用构造器注入(推荐)
@Autowired
public UserService(UserRepository userRepository) {
this.mUserRepository = userRepository;
}
/**
* 实体转DTO
*
* @param userEntity
* @return
*/
public UserDTO convertToDTO(UserEntity userEntity) {
UserDTO dto = new UserDTO();
BeanUtils.copyProperties(userEntity, dto);
return dto;
}
/**
* @param userDTO
* @return
*/
public UserEntity convertToEntity(UserDTO userDTO) {
UserEntity userEntity = new UserEntity();
BeanUtils.copyProperties(userDTO, userEntity);
return userEntity;
}
}
UserRepository.java
创建一个UserRepository接口,继承JpaRepository,获得基本的CRUD操作能力,并定义自定义查询方法。
java
import com.xiaxl.demo.model.db.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository // 添加 @Repository 注解
public interface UserRepository extends JpaRepository<UserEntity, Long> {
// 根据用户名查找用户
Optional<UserEntity> findByName(String name);
// 根据邮箱查找用户
Optional<UserEntity> findByEmail(String email);
// 查找所有用户按创建时间倒序
@Query("SELECT u FROM UserEntity u ORDER BY u.createTime DESC")
List<UserEntity> findAllOrderByCreatedAtDesc();
}
2. Post创建用户接口
现在来实现创建用户的API接口。这个接口将接收POST请求,验证输入数据,并将用户信息保存到数据库中。
UserDbController中添加如下方法,创建用于客户端post请求创建用户。
java
/**
* POST请求 - 创建用户(JSON格式请求体)
* 访问地址:POST http://localhost:8081/api/post/users
* 请求头:Content-Type: application/json
* 请求体示例:
* {
* "name": "李四",
* "email": "lisi@example.com", * "age": 30, * "phone": "13900139000", * "address": "上海市浦东新区",
* "agreeTerms": true * } * * @param request 接收并验证请求体中的JSON数据,自动反序列化为UserCreateRequest对象,
* Valid注解触发对UserCreateRequest对象中字段的验证规则
* @param bindingResult 接收参数验证结果,包含所有验证错误信息
* @return ApiResponse<UserDTO>
*/
@PostMapping("/api/post/create/user")
public ResponseEntity<ApiResponse<UserDTO>> createUser(
@Valid @RequestBody UserRequest request,
BindingResult bindingResult) {
log.info("创建用户 - 请求数据: {}", request);
// 参数校验
if (bindingResult.hasErrors()) {
Map<String, String> errors = new HashMap<>();
for (FieldError error : bindingResult.getFieldErrors()) {
errors.put(error.getField(), error.getDefaultMessage());
}
return ResponseEntity
.badRequest()
.body(ApiResponse.error(errors.toString(), 400));
}
return mUserService.createUser(request);
}
UserService中添加如下方法,创建用于客户端post请求创建用户。
java
/**
* 创建用户
*
* @param request
* @return
*/
public ResponseEntity<ApiResponse<UserDTO>> createUser(UserRequest request) {
// 检查用户名是否已存在
if (mUserRepository.findByName(request.getName()).isPresent()) {
return ResponseEntity.badRequest()
.body(ApiResponse.error("用户名已存在"));
}
// 检查邮箱是否已存在
if (mUserRepository.findByEmail(request.getEmail()).isPresent()) {
return ResponseEntity.badRequest()
.body(ApiResponse.error("邮箱已存在"));
}
// 调用内部事务方法
UserEntity savedUserEntity = saveUserEntity(request);
return ResponseEntity.status(HttpStatus.CREATED)
.body(ApiResponse.success("用户创建成功", convertToDTO(savedUserEntity)));
}
@Transactional
public UserEntity saveUserEntity(UserRequest request) {
log.info("saveUserEntity: ", request);
try {
// 实际的创建逻辑,带有事务
UserEntity newUserEntity = new UserEntity();
newUserEntity.setName(request.getName());
newUserEntity.setEmail(request.getEmail());
newUserEntity.setAge(request.getAge());
newUserEntity.setPhone(request.getPhone());
newUserEntity.setAddress(request.getAddress());
newUserEntity.setActive(true);
newUserEntity.setCreateTime(LocalDateTime.now());
newUserEntity.setUpdateTime(LocalDateTime.now());
newUserEntity.setRoles(List.of("USER"));
log.info("saveUserEntity: ", request);
return mUserRepository.save(newUserEntity);
}catch (Exception e){
e.printStackTrace();
log.info("Exception: ", e.getMessage());
}
return null;
}
使用 Postman 测试: 通过Postman发送POST请求到创建用户接口,可以验证接口功能是否正常。

3. 返回所有用户
接下来实现获取所有用户信息的接口。当用户数量较多时,直接返回所有用户可能导致性能问题,但在开发阶段,这个功能对于测试和数据验证非常有用。
UserDbController中添加如下方法,处理获取所有用户的GET请求。
python
/**
* 获取所有用户
* GET http://localhost:8081/api/get/users
*/@GetMapping("/api/get/users")
public ResponseEntity<ApiResponse<List<UserDTO>>> getAllUsers() {
log.info("getAllUsers");
return mUserService.getAllUsers();
}
UserService中添加如下方法,实现获取所有用户的业务逻辑。
python
/**
* 返回全部用户
*
* @return
*/
public ResponseEntity<ApiResponse<List<UserDTO>>> getAllUsers() {
List<UserDTO> users = mUserRepository.findAllOrderByCreatedAtDesc().stream()
.map(this::convertToDTO)
.collect(Collectors.toList());
return ResponseEntity.ok(ApiResponse.success("获取成功", users));
}
使用 Postman 测试: 通过Postman测试获取所有用户接口,可以查看当前数据库中的所有用户信息。

至此,已经完成了Spring Boot与SQLite数据库的基本集成,实现了用户的创建和查询功能。这种分层架构的设计使得代码结构清晰,各层职责分明,便于后续的功能扩展和维护。
三、案例代码
以上完整的案例代码,请见以下地址:
https://download.csdn.net/download/aiwusheng/92620719
该案例代码是一个完整的Spring Boot项目示例,展示了如何实现文件上传功能并集成SQLite数据库。项目采用标准的MVC分层架构,包含Controller层、Service层、Repository层和Entity层,代码结构清晰,便于学习和扩展。
项目结构说明:
- Controller层:处理HTTP请求,接收参数并返回响应
- Service层:实现业务逻辑,包括用户创建、查询等操作
- Repository层:继承JpaRepository,提供数据访问接口
- Entity层:定义数据表映射实体类
- 配置文件:包含Gradle依赖配置和数据库连接配置
主要功能:
- 多文件上传接口(POST /api/uploadFiles)
- 用户创建接口(POST /api/post/create/user)
- 用户查询接口(GET /api/get/users)
- 参数校验和异常处理
- 事务管理
- 日志记录
技术栈:
- Spring Boot 3.x
- Spring Data JPA
- SQLite数据库
- Lombok简化代码
- 参数校验注解
- Spring Web(文件上传支持)
项目可直接运行,适合作为Spring Boot文件上传和数据库集成的入门学习参考。