SpringBoot 3 实战:虚拟线程、全局异常处理与 JWT 鉴权完整方案


一、前言:SpringBoot 3 是 Java 后端的分水岭

SpringBoot 3 基于 Spring 6,要求 Java 17+,引入了 GraalVM Native Image、虚拟线程(Project Loom)、HTTP Interface 客户端等重大特性。本文从项目搭建到生产部署,完整覆盖 SpringBoot 3 的核心实战。


二、快速搭建项目

2.1 最简 pom.xml

xml 复制代码
<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>3.2.0</version>
</parent>

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>
  <dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
  </dependency>
</dependencies>

2.2 application.yml 关键配置

yaml 复制代码
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb?useSSL=false&characterEncoding=utf8
    username: ${DB_USER}
    password: ${DB_PASS}
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
  jpa:
    hibernate:
      ddl-auto: validate
    show-sql: false  # 生产环境关闭

三、RESTful API 设计

3.1 标准 Controller 写法

java 复制代码
@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {
    private final UserService userService;

    @GetMapping
    public PageResponse<UserDTO> list(
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size) {
        return userService.list(PageRequest.of(page, size));
    }

    @GetMapping("/{id}")
    public UserDTO getById(@PathVariable Long id) {
        return userService.getById(id);
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public UserDTO create(@Valid @RequestBody CreateUserRequest req) {
        return userService.create(req);
    }

    @PutMapping("/{id}")
    public UserDTO update(@PathVariable Long id, @Valid @RequestBody UpdateUserRequest req) {
        return userService.update(id, req);
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void delete(@PathVariable Long id) {
        userService.delete(id);
    }
}

3.2 统一响应体

java 复制代码
@Data
@Builder
public class ApiResponse<T> {
    private int code;
    private String message;
    private T data;
    private long timestamp = System.currentTimeMillis();

    public static <T> ApiResponse<T> ok(T data) {
        return ApiResponse.<T>builder().code(200).message("success").data(data).build();
    }

    public static <T> ApiResponse<T> error(int code, String message) {
        return ApiResponse.<T>builder().code(code).message(message).build();
    }
}

四、虚拟线程(Project Loom)

SpringBoot 3.2 原生支持虚拟线程,I/O 密集型场景吞吐量可提升10倍。

yaml 复制代码
# application.yml 开启虚拟线程
spring:
  threads:
    virtual:
      enabled: true
java 复制代码
// 无需任何代码改动,SpringBoot 自动将 @Async 和请求处理线程切换为虚拟线程
@Service
public class UserService {
    @Async
    public CompletableFuture<UserDTO> fetchAsync(Long id) {
        // 这里会跑在虚拟线程上,即使线程阻塞也不会耗尽系统线程
        return CompletableFuture.completedFuture(getById(id));
    }
}

五、全局异常处理

java 复制代码
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(NotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ApiResponse<Void> handleNotFound(NotFoundException e) {
        return ApiResponse.error(404, e.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ApiResponse<Map<String, String>> handleValidation(MethodArgumentNotValidException e) {
        Map<String, String> errors = new HashMap<>();
        e.getBindingResult().getFieldErrors()
            .forEach(err -> errors.put(err.getField(), err.getDefaultMessage()));
        return ApiResponse.error(400, "参数校验失败");
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ApiResponse<Void> handleGeneral(Exception e) {
        log.error("Unhandled error", e);
        return ApiResponse.error(500, "服务器内部错误");
    }
}

六、JWT 鉴权

java 复制代码
@Component
@RequiredArgsConstructor
public class JwtFilter extends OncePerRequestFilter {
    private final JwtUtil jwtUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
            HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        String header = request.getHeader("Authorization");
        if (header != null && header.startsWith("Bearer ")) {
            String token = header.substring(7);
            if (jwtUtil.isValid(token)) {
                var auth = new UsernamePasswordAuthenticationToken(
                    jwtUtil.getUsername(token), null, jwtUtil.getRoles(token));
                SecurityContextHolder.getContext().setAuthentication(auth);
            }
        }
        chain.doFilter(request, response);
    }
}

七、生产部署

dockerfile 复制代码
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app
COPY target/*.jar app.jar
RUN addgroup -S app && adduser -S app -G app
USER app
EXPOSE 8080
ENTRYPOINT ["java", \
  "-XX:+UseContainerSupport", \
  "-XX:MaxRAMPercentage=75", \
  "-jar", "app.jar"]

💬 SpringBoot 3 实战关键点已经覆盖,收藏备用!有问题欢迎评论区交流。


💬 觉得有用的话,点个赞+收藏,关注我,持续更新优质技术内容!

标签:springboot | java | 后端 | 实战 | 微服务

相关推荐
invicinble6 小时前
这里对java的知识体系做一个全域的介绍
java·开发语言·python
小码哥_常6 小时前
MyBatis-Plus:让数据库操作飞起来的神器
后端
wbs_scy6 小时前
【Linux 线程进阶】进程 vs 线程资源划分 + 线程控制全详解
java·开发语言
ss2736 小时前
食谱推荐系统功能测试如何写?
java·数据库·spring boot·功能测试
2301_811274316 小时前
基于SpringBoot的智能家居管理系统
spring boot·后端·智能家居
毕设源码_古学姐6 小时前
计算机毕业设计springboot智能家居项目管理系统 基于SpringBoot的智能家居项目管理平台设计与实现 SpringBoot技术驱动的智能家居项目管理系统开发
spring boot·智能家居·课程设计
毕设源码-张学姐6 小时前
计算机毕业设计springboot智能家居设备信息管理系统 基于SpringBoot的智能家居设备全生命周期管理平台 面向智慧家庭的SpringBoot设备资产与场景运营系统
spring boot·智能家居·课程设计
AI人工智能+电脑小能手6 小时前
【大白话说Java面试题】【Java基础篇】第15题:JDK1.7中HashMap扩容为什么会发生死循环?如何解决
java·开发语言·数据结构·后端·面试·哈希算法
舒一笑6 小时前
我把设备指纹生成逻辑拆开了:它到底凭什么区分不同设备?
后端·程序员·掘金技术征文
try2find7 小时前
打印ascii码报错问题
java·linux·前端