别再只写增删改查了!用这个SpringBoot+Vue学生管理系统,我搞懂了前后端数据交互的三种核心方式
从CRUD到工程思维SpringBootVue学生管理系统中的三种核心通信模式实战当你能熟练编写增删改查代码后是否曾思考过为什么企业级项目中的前后端交互总显得如此复杂本文将带你突破功能实现的层面通过重构学生管理系统深入剖析三种核心通信模式。这不是又一个简单的CRUD教程而是一次工程思维的升级之旅。1. Axios拦截器打造企业级HTTP通信层在基础项目中我们通常直接使用Axios发起请求但这会导致大量重复代码。想象一下每个请求都需要手动添加token每个响应都要处理错误提示——这种写法在真实项目中根本无法维护。1.1 请求拦截器的实战应用在src/utils/request.js中创建自定义Axios实例const service axios.create({ baseURL: process.env.VUE_APP_BASE_API, timeout: 5000 }) // 请求拦截器 service.interceptors.request.use( config { if (store.getters.token) { config.headers[Authorization] Bearer ${store.getters.token} } return config }, error { return Promise.reject(error) } )这段代码实现了自动为所有请求添加Authorization头统一处理请求超时配置集中管理API基础路径1.2 响应拦截器的错误处理艺术继续在同一个文件中添加响应拦截service.interceptors.response.use( response { const res response.data if (res.code ! 200) { // 处理业务逻辑错误 if (res.code 401) { MessageBox.confirm(登录已过期请重新登录, 提示, { confirmButtonText: 重新登录, cancelButtonText: 取消, type: warning }).then(() { store.dispatch(user/resetToken).then(() { location.reload() }) }) } return Promise.reject(new Error(res.message || Error)) } else { return res } }, error { // 处理HTTP状态码错误 if (error.response.status 404) { Message({ message: 资源不存在, type: error, duration: 5 * 1000 }) } return Promise.reject(error) } )这种处理方式带来三大优势统一错误处理不再需要在每个请求中重复写错误提示自动token刷新当token过期时自动引导用户重新登录业务状态码解耦后端返回的自定义状态码与HTTP状态码分离处理2. Vue组件通信优雅管理学生列表状态在学生管理系统中最常见的场景是添加学生后刷新列表、删除学生后更新视图。新手通常会直接操作DOM或强制刷新页面但这违背了Vue的数据驱动原则。2.1 Props与自定义事件的黄金组合在StudentList.vue组件中template div student-form successhandleFormSuccess / student-table :studentsstudents deletehandleDelete / /div /template script export default { data() { return { students: [] } }, methods: { handleFormSuccess(newStudent) { this.students.unshift(newStudent) }, handleDelete(id) { this.students this.students.filter(s s.id ! id) } } } /script这种模式实现了表单组件通过$emit触发事件父组件监听事件并更新数据表格组件通过props接收最新数据2.2 EventBus在复杂场景下的应用当组件层级过深时props/events会变得繁琐。我们可以在src/utils/event-bus.js中创建事件中心import Vue from vue export const EventBus new Vue()在学生表单组件中发布事件import { EventBus } from /utils/event-bus export default { methods: { submitForm() { addStudent(this.form).then(res { EventBus.$emit(student-added, res.data) }) } } }在任意需要响应的组件中订阅import { EventBus } from /utils/event-bus export default { created() { EventBus.$on(student-added, student { this.students.unshift(student) }) } }注意使用EventBus时务必在组件销毁前移除事件监听否则会导致内存泄漏3. SpringBoot控制器RESTful设计的精髓很多开发者分不清Controller和RestController的区别导致API设计混乱。让我们通过学生管理系统来理解它们的正确用法。3.1 RestController的标准化响应创建StudentApiController.javaRestController RequestMapping(/api/students) public class StudentApiController { GetMapping public ResultListStudent listStudents() { ListStudent students studentService.list(); return Result.success(students); } PostMapping public ResultStudent createStudent(Valid RequestBody StudentDTO dto) { Student student studentService.create(dto); return Result.success(student); } }其中Result是统一响应体Data public class ResultT { private int code; private String message; private T data; public static T ResultT success(T data) { ResultT result new Result(); result.setCode(200); result.setMessage(success); result.setData(data); return result; } }这种设计保证了所有API返回统一格式包含明确的状态码和消息支持泛型返回不同类型数据3.2 Controller在服务端渲染中的应用对于需要服务端渲染的页面如报表导出可以这样设计Controller RequestMapping(/students) public class StudentViewController { GetMapping(/export) public String exportReport(Model model) { model.addAttribute(students, studentService.list()); return student-report; } }关键区别返回的是视图名称而非JSON通过Model对象传递数据适合生成PDF、Excel等二进制文件4. 工程化进阶从Demo到生产级的改造让我们把简单的学生管理系统改造成接近企业级的项目结构。4.1 前端项目结构优化src/ ├── api/ # 所有API请求 │ └── student.js ├── components/ # 公共组件 ├── router/ # 路由配置 ├── store/ # Vuex状态管理 │ └── modules/ # 模块化store │ └── user.js ├── utils/ # 工具函数 │ ├── auth.js # 权限相关 │ └── request.js # Axios封装 └── views/ # 页面组件 └── student/ ├── List.vue └── Form.vue4.2 后端分层架构改造com.example.student/ ├── config/ # 配置类 ├── controller/ # 控制器 │ ├── api/ # RESTful API │ └── web/ # 传统MVC ├── dto/ # 数据传输对象 ├── entity/ # 数据库实体 ├── repository/ # 数据访问层 ├── service/ # 业务逻辑层 │ └── impl/ # 实现类 └── util/ # 工具类4.3 API文档自动化添加Swagger配置Configuration EnableSwagger2 public class SwaggerConfig { Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.basePackage(com.example.student.controller.api)) .paths(PathSelectors.any()) .build() .apiInfo(apiInfo()); } private ApiInfo apiInfo() { return new ApiInfoBuilder() .title(学生管理系统API) .description(前后端分离架构) .version(1.0) .build(); } }访问/swagger-ui.html即可看到自动生成的API文档。