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

tips: 先学习 ioc和di

Spring 核心思想解析:IoC 与 DI 一文讲透(从入门到工程理解)

一、前言

在前两篇中,我们已经完成:

复制代码
Controller 接口开发
DTO 参数接收
@Valid 参数校验

但当前代码仍然存在明显问题:

复制代码
Controller 承担了业务逻辑 ❌
返回结构不统一 ❌
没有异常处理 ❌
没有日志 ❌

👉 本篇将完成一次工程级升级


二、目标

我们将实现:

Controller → Service 分层 ✔

统一返回结构(Result)✔

统一异常处理 ✔

日志输出 ✔

三、统一返回结构(Result)

创建 Result 类

java 复制代码
package org.example.arkbackend.common;

import lombok.Data;

@Data
public class Result<T> {

    private int code;
    private String message;
    private T data;

    public static <T> Result<T> success(T data) {
        Result<T> r = new Result<>();
        r.setCode(0);
        r.setMessage("成功");
        r.setData(data);
        return r;
    }

    public static <T> Result<T> fail(String message) {
        Result<T> r = new Result<>();
        r.setCode(1);
        r.setMessage(message);
        return r;
    }
}

👉 返回统一格式:

java 复制代码
{
  "code": 0,
  "message": "成功",
  "data": {}
}

四、Service 层设计

1️⃣ 接口

java 复制代码
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️⃣ 实现类

java 复制代码
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 重构

java 复制代码
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 Result<String> register(@Valid @RequestBody UserRegisterDTO dto) {
        return Result.success(userService.register(dto));
    }

    @GetMapping("/{id}")
    public Result<String> getUser(@PathVariable Long id) {
        return Result.success(userService.getUserById(id));
    }

    @DeleteMapping("/{id}")
    public Result<Void> delete(@PathVariable Long id) {
        userService.deleteUser(id);
        return Result.success(null);
    }
}

👉 Controller 现在只负责:

复制代码
接收参数 + 调用 Service + 返回结果

六、统一异常处理(非常重要)

创建全局异常处理类

java 复制代码
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());
    }
}

👉 当异常发生:

java 复制代码
{
  "code": 1,
  "message": "用户名已存在"
}

七、日志(Log)

使用 @Slf4j

复制代码
@Slf4j

使用方式

复制代码
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)

👉 实现真实数据存储

相关推荐
来杯@Java1 小时前
图书管理系统(基于springboot+vue前后端分离的项目)计算机毕业设计java
java·spring boot·spring·vue·毕业设计·mybatis·课程设计
卷毛的技术笔记2 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
编程大师哥2 小时前
匿名函数 lambda + 高阶函数
java·python·算法
東雪木2 小时前
多线程与并发编程 专属复习笔记
java·开发语言·笔记·java面试
adrninistrat0r2 小时前
Java调用链MCP分析工具
java·python·ai编程
噜噜噜阿鲁~2 小时前
python学习笔记 | 11.3、面向对象高级编程-多重继承
java·开发语言
qq_2518364573 小时前
SpringBoot+Vue 共享电池柜管理系统 完整实现 前后端分离项目实战 完整代码
vue.js·spring boot·后端
春生野草3 小时前
反射、Tomcat执行
java·开发语言
_日拱一卒4 小时前
LeetCode:207课程表
java·数据结构·算法·leetcode·职场和发展
飞翔中文网4 小时前
Java学习笔记之抽象类与接口(设计思想)
java·笔记·学习