【SpringBoot】统一功能处理详解

【SpringBoot】统一功能处理详解

🎬 那我掉的头发算什么个人主页
🔥 个人专栏: 《javaSE》《数据结构》《数据库》《javaEE》

⛺️待到苦尽甘来日


在这里插入图片描述

文章目录

统一数据返回格式

快速入门

统一的数据返回格式使用 @ControllerAdvice 和 ResponseBodyAdvice 的方式实现@ControllerAdvice 表示控制器通知类添加类 ResponseAdvice , 实现 ResponseBodyAdvice 接口,并在类上添加@ControllerAdvice 注解。

packagecom.hbu.book.responseAdvice;importorg.jspecify.annotations.Nullable;importorg.springframework.core.MethodParameter;importorg.springframework.http.MediaType;importorg.springframework.http.server.ServerHttpRequest;importorg.springframework.http.server.ServerHttpResponse;importorg.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;publicclassResponseAdviceimplementsResponseBodyAdvice{@Overridepublicbooleansupports(MethodParameter returnType,Class converterType){returnfalse;}@Overridepublic@NullableObjectbeforeBodyWrite(@NullableObject body,MethodParameter returnType,MediaType selectedContentType,Class selectedConverterType,ServerHttpRequest request,ServerHttpResponse response){returnnull;}}

supports 方法:判断是否要执行 beforeBodyWrite 方法. true 为执行,false 不执行。通过该方法可以选择哪些类或哪些方法的 response 要进行处理,其他的不进行处理。

在这里插入图片描述


beforeBodyWrite方法: 对response方法进行具体操作处理。

此时还没启动统一处理,这时访问接口返回结果是这样的:

在这里插入图片描述
packagecom.hbu.book.model;importcom.hbu.book.enums.ResultCodeEnum;importlombok.Data;@DatapublicclassResult<T>{privateResultCodeEnum code;//-1 未登录 200 正常 -2 出错privateString errMsg;privateT data;publicstatic<T>Resultsuccess(T data){Result result =newResult(); result.setCode(ResultCodeEnum.SUCCESS); result.setErrMsg(""); result.setData(data);return result;}publicstatic<T>Resultfail(String errMsg){Result result =newResult(); result.setCode(ResultCodeEnum.FAIL); result.setErrMsg(errMsg); result.setData(null);return result;}publicstatic<T>Resultfail(String errMsg,T data){Result result =newResult(); result.setCode(ResultCodeEnum.FAIL); result.setErrMsg(errMsg); result.setData(data);return result;}publicstatic<T>Resultunlogin(){Result result =newResult(); result.setCode(ResultCodeEnum.UNLOGIN); result.setErrMsg("用户未登录");return result;}}
packagecom.hbu.book.responseAdvice;importcom.hbu.book.model.Result;importorg.jspecify.annotations.Nullable;importorg.springframework.core.MethodParameter;importorg.springframework.http.MediaType;importorg.springframework.http.server.ServerHttpRequest;importorg.springframework.http.server.ServerHttpResponse;importorg.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;publicclassResponseAdviceimplementsResponseBodyAdvice{@Overridepublicbooleansupports(MethodParameter returnType,Class converterType){returntrue;}@Overridepublic@NullableObjectbeforeBodyWrite(@NullableObject body,MethodParameter returnType,MediaType selectedContentType,Class selectedConverterType,ServerHttpRequest request,ServerHttpResponse response){returnResult.success(body);}}

启动了之后再次访问接口:

在这里插入图片描述

存在问题


在这里插入图片描述


在这里插入图片描述


但是数据库中确实是插入了这个数据。

其他的操作都是正常的。

packagecom.hbu.book.controller;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;@RequestMapping("/test")@RestControllerpublicclassTestController{@RequestMapping("/t1")publicStringt1(){return"t1";}@RequestMapping("/t2")publicbooleant2(){returntrue;}@RequestMapping("/t3")publicIntegert3(){return200;}}

多方测试下,只有返回类型是String的接口才会发生这种错误。并且报错方式都是一样的。

核心原因是 Spring 处理 String 类型返回值的消息转换器优先级问题:当控制器方法返回 String 时,Spring 会优先使用 StringHttpMessageConverter 处理响应,但这个转换器只能处理 String 类型,而 ResponseAdvice 把 String 包装成了 Result 对象,导致转换器尝试将 Result 强制转为 String 时抛出类型转换异常。

代码优化

packagecom.hbu.book.config;importcom.hbu.book.model.Result;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.core.MethodParameter;importorg.springframework.http.MediaType;importorg.springframework.http.server.ServerHttpRequest;importorg.springframework.http.server.ServerHttpResponse;importorg.springframework.web.bind.annotation.ControllerAdvice;importorg.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;importtools.jackson.databind.ObjectMapper;@ControllerAdvicepublicclassResponseAdviceimplementsResponseBodyAdvice{@AutowiredprivateObjectMapper objectMapper;@Overridepublicbooleansupports(MethodParameter returnType,Class converterType){returntrue;}@OverridepublicObjectbeforeBodyWrite(Object body,MethodParameter returnType,MediaType selectedContentType,Class selectedConverterType,ServerHttpRequest request,ServerHttpResponse response){if(body instanceofResult){return body;}if(body instanceofString){return objectMapper.writeValueAsString(Result.success(body));}returnResult.success(body);}}

优点

1.方便前端程序员更好的接收和解析后端数据接口返回的数据
2. 降低前端程序员和后端程序员的沟通成本,按照某个格式实现就可以了,因为所有接口都是这样返回的.
3. 有利于项目统一数据的维护和修改.
4. 有利于后端技术部门的统一规范的标准制定,不会出现稀奇古怪的返回内容.

统一异常处理

统一异常处理使用的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表示控制器通知类, @ExceptionHandler 是异常处理器,两个结合表示当出现异常的时候执行某个通知,也就是执行某个方法事件。

packagecom.hbu.book.config;importcom.hbu.book.model.Result;importlombok.extern.slf4j.Slf4j;importorg.springframework.web.bind.annotation.ControllerAdvice;importorg.springframework.web.bind.annotation.ExceptionHandler;importorg.springframework.web.bind.annotation.ResponseBody;@ControllerAdvice@ResponseBody@Slf4jpublicclassExceptionAdvice{@ExceptionHandlerpublicObjecthandler(Exception e){ log.error("出现异常:",e);returnResult.fail(e.getMessage());}}

测试一下:

packagecom.hbu.book.controller;importorg.apache.ibatis.jdbc.Null;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.RestController;@RequestMapping("/test")@RestControllerpublicclassTestController{@RequestMapping("/t1")publicStringt1(){Integer x =7/0;return"t1";}@RequestMapping("/t2")publicbooleant2(){String a =null; a.contains("a");returntrue;}@RequestMapping("/t3")publicIntegert3(){int[] arr =newint[10];System.out.println(arr[100]);return200;}}
在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


在这里插入图片描述


对于不同的异常,我们其实可以设置不同的方法:

packagecom.hbu.book.config;importcom.hbu.book.model.Result;importlombok.extern.slf4j.Slf4j;importorg.springframework.web.bind.annotation.ControllerAdvice;importorg.springframework.web.bind.annotation.ExceptionHandler;importorg.springframework.web.bind.annotation.ResponseBody;@ControllerAdvice@ResponseBody@Slf4jpublicclassExceptionAdvice{@ExceptionHandlerpublicObjecthandler(Exception e){ log.error("出现异常:",e);returnResult.fail(e.getMessage());}@ExceptionHandlerpublicObjecthandler(NullPointerException e){ log.error("出现空指针异常:",e);returnResult.fail(e.getMessage());}@ExceptionHandlerpublicObjecthandler(ArithmeticException e){ log.error("出现除0异常:",e);returnResult.fail(e.getMessage());}@ExceptionHandlerpublicObjecthandler(ArrayIndexOutOfBoundsException e){ log.error("出现数组越界异常:",e);returnResult.fail(e.getMessage());}}

或者也可以:

packagecom.hbu.book.config;importcom.hbu.book.model.Result;importlombok.extern.slf4j.Slf4j;importorg.springframework.web.bind.annotation.ControllerAdvice;importorg.springframework.web.bind.annotation.ExceptionHandler;importorg.springframework.web.bind.annotation.ResponseBody;@ControllerAdvice@ResponseBody@Slf4jpublicclassExceptionAdvice{@ExceptionHandlerpublicObjecthandler(Exception e){ log.error("出现异常:",e);returnResult.fail(e.getMessage());}// @ExceptionHandler// public Object handler(NullPointerException e){// log.error("出现空指针异常:",e);// return Result.fail(e.getMessage());// }// @ExceptionHandler// public Object handler(ArithmeticException e){// log.error("出现除0异常:",e);// return Result.fail(e.getMessage());// }// @ExceptionHandler// public Object handler(ArrayIndexOutOfBoundsException e){// log.error("出现数组越界异常:",e);// return Result.fail(e.getMessage());// }@ExceptionHandler(NullPointerException.class)publicObjecthandler1(Exception e){ log.error("出现异常:",e);returnResult.fail(e.getMessage());}@ExceptionHandler(ArrayIndexOutOfBoundsException.class)publicObjecthandler2(Exception e){ log.error("出现异常:",e);returnResult.fail(e.getMessage());}}

我们一般不把异常的具体内容返回给前端,因此可以这样处理:

在这里插入图片描述
在这里插入图片描述


在这里插入图片描述


这里我们没有针对t1做特别的异常处理,最后打印出来的是内部异常。
所以说,当没有匹配的异常时,会自动去寻找有没有报的异常的父类的处理方法,然后执行处理方法。

Read more

【Linux】线程同步

【Linux】线程同步

📝前言: 上篇文章我们讲解了【Linux】线程互斥,这篇文章我们来讲讲Linux——线程同步 🎬个人简介:努力学习ing 📋个人专栏:Linux 🎀ZEEKLOG主页 愚润求学 🌄其他专栏:C++学习笔记,C语言入门基础,python入门基础,C++刷题专栏 目录 * 一,同步定义 * 二,条件变量 * 1. 基本介绍 * 2. 接口 * 2.1 初始化和销毁 * 初始化 * 销毁 * 2.2 等待和通知 * 等待 * 通知(唤醒) * 三,使用经典规范 * 1. 等待代码 * 2. 唤醒代码 * 四,生产者消费者模型 * 1. 基本介绍 * 2.

By Ne0inhk
08-OpenClaw自动化与定时任务

08-OpenClaw自动化与定时任务

OpenClaw 自动化与定时任务 免费专栏全套教程:OpenClaw从入门到精通 OpenClaw 提供了一套完整的自动化系统,包括 Heartbeat 心跳机制、Cron 定时任务、Hooks 事件钩子和 Webhook 外部触发。本章将详细介绍这些机制的概念、配置和实战应用。 目录 1. 自动化工作流概念 2. Heartbeat 心跳机制 3. Cron 定时任务配置 4. Hooks 事件钩子 5. Webhook 外部触发 6. 实战案例 7. 故障排查 1. 自动化工作流概念 1.1 核心组件 OpenClaw 的自动化系统由四个核心组件构成: 组件用途触发方式适用场景Heartbeat周期性检查自动定时批量检查、上下文感知监控Cron精确定时任务时间驱动固定时间执行、独立任务Hooks事件驱动响应事件触发命令响应、生命周期管理Webhook外部系统集成HTTP 请求第三方系统对接、推送接收 1.

By Ne0inhk
Flutter 三方库 sort_json 的鸿蒙化适配指南 - 实现 JSON 键值的自动化递归排序、支持规范化输出与项目配置文件清理

Flutter 三方库 sort_json 的鸿蒙化适配指南 - 实现 JSON 键值的自动化递归排序、支持规范化输出与项目配置文件清理

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net Flutter 三方库 sort_json 的鸿蒙化适配指南 - 实现 JSON 键值的自动化递归排序、支持规范化输出与项目配置文件清理 前言 在进行 Flutter for OpenHarmony 的工程化开发时,保持项目配置文件(如 package.json、.json5 或各种国际化语言文件)的条理性是至关重要的。特别是在多人协作或版本控制(Git)中,无序的 JSON 键值会导致严重的冲突。sort_json 是一个专注于将 JSON 字符串或文件重新排版并按字母顺序排序的库。本文将探讨如何利用该工具优化鸿蒙项目的配置管理。 一、原理解析 / 概念介绍 1.1 基础原理 sort_json 通过将输入的 JSON

By Ne0inhk
【Linux】线程池(一)C++ 手写线程池:基于策略模式实现高性能日志模块

【Linux】线程池(一)C++ 手写线程池:基于策略模式实现高性能日志模块

文章目录 * 池化技术 * 线程池的日志模块 * 日志与策略模式 * 日志模块 * 两个核心问题 * 设计文件等级 * 刷新策略 * 获取日志时间 * logger类实现 * 内部类LogMessage实现 * 日志刷新流程图及源码 池化技术 池化技术可以减少很多的底层重复工作,例如创建进程、线程、申请内存空间时的系统调用和初始化工作,例如线程池,先预先创建好一些线程,当任务到来时直接将预先创建好的线程唤醒去处理任务,效率会远远高于任务到来时临时创建线程。例如内存池,但我们要用1mb空间时内存池会一次性申请20mb空间,效率会远远高于用多少空间申请多少空间(申请空间会调用系统调用)。 线程池是执行流级别的池化技术,STL中的空间配置器和内存池是内存块管理级别的池化技术。 线程池的日志模块 下⾯开始,我们结合我们之前所做的所有封装,进⾏⼀个线程池的设计。在写之前,我们要做如下准备。 * 准备线程的封装 * 准备锁和条件变量的封装 * 引⼊日志,对线程进⾏封装 日志与策略

By Ne0inhk