Spring Boot 实战(三):Service 分层 + 统一返回 + 异常处理(工程级写法)

张开发
2026/4/16 20:51:41 15 分钟阅读

分享文章

Spring Boot 实战(三):Service 分层 + 统一返回 + 异常处理(工程级写法)
tips 先学习 ioc和diSpring 核心思想解析IoC 与 DI 一文讲透从入门到工程理解一、前言在前两篇中我们已经完成Controller 接口开发 DTO 参数接收 Valid 参数校验但当前代码仍然存在明显问题Controller 承担了业务逻辑 ❌ 返回结构不统一 ❌ 没有异常处理 ❌ 没有日志 ❌ 本篇将完成一次工程级升级二、目标我们将实现Controller → Service 分层 ✔统一返回结构Result✔统一异常处理 ✔日志输出 ✔三、统一返回结构Result创建 Result 类package org.example.arkbackend.common; import lombok.Data; Data public class ResultT { private int code; private String message; private T data; public static T ResultT success(T data) { ResultT r new Result(); r.setCode(0); r.setMessage(成功); r.setData(data); return r; } public static T ResultT fail(String message) { ResultT r new Result(); r.setCode(1); r.setMessage(message); return r; } } 返回统一格式{ code: 0, message: 成功, data: {} }四、Service 层设计1️⃣ 接口package org.example.arkbackend.service; import org.example.arkbackend.dto.UserRegisterDTO; public interface UserService { String register(UserRegisterDTO dto); String getUserById(Long id); void deleteUser(Long id); }2️⃣ 实现类package org.example.arkbackend.service.impl; import lombok.extern.slf4j.Slf4j; import org.example.arkbackend.dto.UserRegisterDTO; import org.example.arkbackend.service.UserService; import org.springframework.stereotype.Service; Slf4j Service public class UserServiceImpl implements UserService { Override public String register(UserRegisterDTO dto) { log.info(开始注册用户{}, dto.getUsername()); // 模拟业务逻辑 if (admin.equals(dto.getUsername())) { throw new RuntimeException(用户名已存在); } return 注册成功 dto.getUsername(); } Override public String getUserById(Long id) { log.info(查询用户ID{}, id); return 用户ID id; } Override public void deleteUser(Long id) { log.info(删除用户ID{}, id); } }五、Controller 重构package org.example.arkbackend.controller; import jakarta.validation.Valid; import org.example.arkbackend.common.Result; import org.example.arkbackend.dto.UserRegisterDTO; import org.example.arkbackend.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; RestController RequestMapping(/user) public class UserController { Autowired private UserService userService; PostMapping(/register) public ResultString register(Valid RequestBody UserRegisterDTO dto) { return Result.success(userService.register(dto)); } GetMapping(/{id}) public ResultString getUser(PathVariable Long id) { return Result.success(userService.getUserById(id)); } DeleteMapping(/{id}) public ResultVoid delete(PathVariable Long id) { userService.deleteUser(id); return Result.success(null); } } Controller 现在只负责接收参数 调用 Service 返回结果六、统一异常处理非常重要创建全局异常处理类package org.example.arkbackend.exception; import org.example.arkbackend.common.Result; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; RestControllerAdvice public class GlobalExceptionHandler { ExceptionHandler(Exception.class) public Result? handleException(Exception e) { return Result.fail(e.getMessage()); } } 当异常发生{ code: 1, message: 用户名已存在 }七、日志Log使用 Slf4jSlf4j使用方式log.info(注册用户{}, username); log.error(发生异常{}, e.getMessage()); 优点✔ 可追踪 ✔ 可定位问题 ✔ 可分析行为八、完整执行流程请求进入 Controller → 参数校验Valid → 调用 Service → Service 执行业务逻辑 → 返回 Result → 异常统一处理九、当前项目结构controller/ dto/ service/ service/impl/ common/ exception/ 已具备企业级基础架构 ✔十、一句话总结通过 Service 分层、统一返回结构和全局异常处理可以将简单接口升级为具备工程规范的后端系统下一篇Spring Boot 实战四MySQL MyBatis 接入打通用户注册最小闭环数据库MySQL 持久层Mapper / JPA 实现真实数据存储

更多文章