以下是一个使用Spring开发的简单 REST API 小程序,通过对一张user
表进行操作,代码演示如何RestAPI开发中实现数据校验、全局异常处理和返回Json格式数据。 使用的核心框架包括
创建一个 Maven 项目,添加以下依赖:
4.0.0
com.example
user-crud-api
0.0.1-SNAPSHOT
jar
org.springframework.boot
spring-boot-starter-parent
3.4.3
17
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-data-jpa
com.mysql
mysql-connector-j
runtime
org.projectlombok
lombok
true
org.springframework.boot
spring-boot-starter-validation
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
org.projectlombok
lombok
配置 MySQL 数据库连接:
# 数据源配置
spring.datasource.url=jdbc:mysql://localhost:3306/user_db?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
spring.datasource.username=root
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
# JPA 配置
spring.jpa.hibernate.ddl-auto=update # 根据实体自动更新数据库表结构
spring.jpa.show-sql=true # 打印 SQL 语句(开发时使用)
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
# 服务器端口(可选)
server.port=8080
user_db
已创建,并调整 username
、password
和 url
匹配您的环境。使用 Lombok 和 Bean Validation 注解定义 User
实体:
package com.themarscloud.example.validation.model;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank(message = "Username cannot be blank")
@Size(min = 3, max = 50, message = "Username must be between 3 and 50 characters")
private String username;
@NotBlank(message = "Password cannot be blank")
@Size(min = 6, message = "Password must be at least 6 characters")
private String password;
@NotBlank(message = "Email cannot be blank")
@Email(message = "Email must be valid")
private String email;
}
@Data
自动生成 getter/setter、@Builder
提供构建器模式、@NoArgsConstructor
和 @AllArgsConstructor
生成无参和全参构造函数。@NotBlank
、@Size
、@Email
确保数据校验。使用 Spring Data JPA 创建 UserRepository
接口:
package com.themarscloud.example.validation.repository;
import com.themarscloud.example.validation.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository {
}
JpaRepository
提供了默认的 CRUD 操作,无需额外实现。创建服务层处理业务逻辑:
package com.themarscloud.example.validation.service;
import com.themarscloud.example.validation.model.User;
import com.themarscloud.example.validation.repository.UserRepository;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
public List getAllUsers() {
return userRepository.findAll();
}
public Optional getUserById(Long id) {
return userRepository.findById(id);
}
public User createUser(@Valid User user) {
return userRepository.save(user);
}
public User updateUser(Long id, @Valid User userDetails) {
User user = userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("User not found with id: " + id));
user.setUsername(userDetails.getUsername());
user.setPassword(userDetails.getPassword());
user.setEmail(userDetails.getEmail());
return userRepository.save(user);
}
public void deleteUser(Long id) {
User user = userRepository.findById(id)
.orElseThrow(() -> new RuntimeException("User not found with id: " + id));
userRepository.delete(user);
}
}
createUser
和 updateUser
方法中使用 Valid
触发 Bean Validation 校验。创建 REST 控制器处理 HTTP 请求:
@RequestBody
的方法上使用 Valid
触发校验。package com.themarscloud.example.validation.controller;
import com.themarscloud.example.validation.model.User;
import com.themarscloud.example.validation.service.UserService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/users")
public class UserController {
@Autowired
private UserService userService;
// 获取所有用户
@GetMapping
public ResponseEntity> getAllUsers() {
List users = userService.getAllUsers();
return ResponseEntity.ok(users);
}
// 根据 ID 获取用户
@GetMapping("/{id}")
public ResponseEntity getUserById(@PathVariable Long id) {
return userService.getUserById(id)
.map(ResponseEntity::ok)
.orElseGet(() -> ResponseEntity.notFound().build());
}
// 创建用户
@PostMapping
public ResponseEntity createUser(@Valid @RequestBody User user) {
User createdUser = userService.createUser(user);
return ResponseEntity.ok(createdUser);
}
// 更新用户
@PutMapping("/{id}")
public ResponseEntity updateUser(@PathVariable Long id, @Valid @RequestBody User userDetails) {
User updatedUser = userService.updateUser(id, userDetails);
return ResponseEntity.ok(updatedUser);
}
// 删除用户
@DeleteMapping("/{id}")
public ResponseEntity deleteUser(@PathVariable Long id) {
userService.deleteUser(id);
return ResponseEntity.ok().build();
}
}
在 com.themarscloud.example.validation.exception 包下(如果没有该包,请创建)添加以下 @ControllerAdvice 实现:
package com.themarscloud.example.validation.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ControllerAdvice
public class GlobalExceptionHandler {
*// 处理数据校验异常(MethodArgumentNotValidException)*
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity
创建 Spring Boot 启动类:
package com.themarscloud.example.validation;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class ExampleValidationApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleValidationApplication.class, args);
}
}
使用 Postman 或 curl 测试以下端点:
GET /api/users:获取所有用户。
GET /api/users/{id}:获取指定 ID 的用户。
POST /api/users:创建用户(示例 JSON):
{
"username": "john_doe",
"password": "password123",
"email": "[email protected]"
}
PUT /api/users/{id}:更新用户(类似 POST 的 JSON)。
DELETE /api/users/{id}:删除用户。
数据校验示例:如果 POST 请求的 JSON 中 username
长度小于 3 或 email
格式错误,服务器会返回 400 Bad Request
响应,包含验证错误信息,例如:
{
"timestamp": "2025-02-25T10:00:00Z",
"status": 400,
"error": "Bad Request",
"errors": [
{
"field": "username",
"message": "Username must be between 3 and 50 characters"
}
],
"path": "/api/users"
}
使用 Postman 或 curl 测试以下场景,观察返回的统一错误格式:
数据校验失败: 发送以下无效 JSON 到 POST /api/users: 预期返回:
{
"username": "a", *// 长度小于 3*
"password": "123", *// 长度小于 6*
"email": "invalid-email" *// 无效邮箱*
}
{
"timestamp": "2025-02-25T12:00:00Z",
"status": 400,
"error": "Bad Request",
"path": "user",
"errors": {
"username": "Username must be between 3 and 50 characters",
"password": "Password must be at least 6 characters",
"email": "Email must be valid"
}
}
资源未找到: 发送 GET /api/users/999(假设 ID 999 的用户不存在): 预期返回:
{
"timestamp": "2025-02-25T12:00:00Z",
"status": 404,
"error": "Not Found",
"message": "User not found with id: 999"
}
其他异常: 手动抛出 Exception(例如在服务层或控制器中添加测试代码),验证 handleGeneralException 的返回:
{
"timestamp": "2025-02-25T12:00:00Z",
"status": 500,
"error": "Internal Server Error",
"message": "Some internal error occurred"
}
确保 MySQL 服务器运行,并创建 user_db
数据库。
编译和运行项目:
mvn clean install
java -jar target/validation-0.0.1-SNAPSHOT.jar
访问 http://localhost:8080/api/users
,使用 Postman 或浏览器测试 API。
spring-boot-starter-validation
依赖已添加,Spring Boot 会自动集成 Hibernate Validator 进行校验。spring-boot-starter-logging
或 slf4j
进行日志记录,调试 SQL 和 API 调用。UserRepository
中使用 Pageable
和 Sort
实现分页和排序。spring-boot-starter-test
编写测试用例。