SpringBoot实现统一返回接口(除AOP)

news2024/9/22 4:20:29

起因

关于使用AOP去实现统一返回接口在之前的博客中我们已经实现了,但我突然突发奇想,SpringBoot中异常类的统一返回好像是通过@RestControllerAdvice 这个注解去完成的,那我是否也可以通过这个注解去实现统一返回接口。

正文

这个方法主要是通过@ControllerAdvice + ResponseBodyAdvice实现统一返回结果。其实本质来说和aop实现是相通的明白一个另一个就非常好理解了。
(Result 的代码我就不在这边重复贴了,读者可以去我直接用AOP实现的博客中拿)

自定义注解

import com.study.project.common.BaseResponse;
import com.study.project.common.ResultCode;

import java.lang.annotation.*;

import static com.study.project.common.ResultCode.SUCCESS;

/**
 * @date 2023/2/18
 */
@Documented
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface FunctionResult {
    String value() default "";
    
	//默认code为成功
    ResultCode code() default SUCCESS;
}

自定义一个响应拦截

import com.study.project.annotation.FunctionResult;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;


/**
 * @author Chengming.Zhang
 * @date 2023/2/18
 * ResponseBodyAdvice主要是对加了@RestController(也就是@Controller+@ResponseBody)注解的处理器将要返回的值进行增强处理。
 *其实也就是采用了AOP的思想,对返回值进行一次修改。
 */
@RestControllerAdvice
public class FunctionResponseBodyAdvice implements ResponseBodyAdvice  {
    //判断当前类上是否有@FunctionResult
    protected boolean isFunctionResult(MethodParameter returnType) {
        /**
         * getContainingClass() 获取当前类的信息
         * isAnnotationPresent 判断当前类上是否存在某个注解
         */
        Class<?> containingClass = returnType.getContainingClass();
        boolean annotationPresent = containingClass.isAnnotationPresent(FunctionResult.class);
        Annotation[] annotations = containingClass.getAnnotations();
        return returnType.getContainingClass().isAnnotationPresent(FunctionResult.class);
    }

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return isFunctionResult(returnType);
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {

        Method method = returnType.getMethod();
        Class<?> methodReturnType = method.getReturnType();
        //判断是否为void的方法
        if (methodReturnType.equals(void.class)) {
            return body;
        }
        //判断当前方法是否有@FunctionResult注解,如果没有则全部按照成功返回,如果有则根据具体指定的返回码以及返回内容返回
        FunctionResult result = returnType.getMethod().getAnnotation(FunctionResult.class);
        if (result == null) {
            return new BaseResponse(ResultCode.SUCCESS, body);
        }
        ResultCode code = result.code();
        return new BaseResponse(result.code(), body);
    }
}

controller类

import com.study.project.annotation.FunctionResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @date 2023/2/4
 */
@FunctionResult
@RestController
public class TestController {

    @RequestMapping("/test5")
    public int test5(){
        return 1;
    }

    @RequestMapping("/test6")
    public void test6(){
        System.err.println("test6");
    }
}

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

你是不是以为代码已经结束?
其实这个代码是有问题hhhhh,当接口的返回类型是String的时候就会提示报错
在这里插入图片描述
看控制台的报错信息发现是接口的返回参数转换的时候报错了,于是我们根据控制台上的报错信息进行断点排查

首先我们找到控制台中的第一行的报错类StringHttpMessageConverter.java中的addDefaultHeaders方法,发这个方法其实是重新了他父类的AbstractHttpMessageConverter的方法

在这里插入图片描述
在这里插入图片描述
AbstractHttpMessageConverter中的方法Result的参数是T,但是StringHttpMessageConverter在重写的时候将其转为了String,因此当ResponseBodyAdvice返回Result格式的时候就会报错,所以我们就需要在ResponseBodyAdvice中需要单独处理一下String类型。

完整代码

import cn.hutool.json.JSONUtil;
import com.study.project.annotation.FunctionResult;
import jdk.nashorn.internal.objects.annotations.Function;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;


/**
 * @author Chengming.Zhang
 * @date 2023/2/18
 * ResponseBodyAdvice主要是对加了@RestController(也就是@Controller+@ResponseBody)注解的处理器将要返回的值进行增强处理。
 *其实也就是采用了AOP的思想,对返回值进行一次修改。
 */
@RestControllerAdvice
public class FunctionResponseBodyAdvice implements ResponseBodyAdvice  {
    //判断当前类上是否有@FunctionResult
    protected boolean isFunctionResult(MethodParameter returnType) {
        /**
         * getContainingClass() 获取当前类的信息
         * isAnnotationPresent 判断当前类上是否存在某个注解
         */
        Class<?> containingClass = returnType.getContainingClass();
        boolean annotationPresent = containingClass.isAnnotationPresent(FunctionResult.class);
        Annotation[] annotations = containingClass.getAnnotations();
        return returnType.getContainingClass().isAnnotationPresent(FunctionResult.class);
    }

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return isFunctionResult(returnType);
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {

        Method method = returnType.getMethod();
        Class<?> methodReturnType = method.getReturnType();
        if (methodReturnType.equals(void.class)) {
            return body;
        }
        //判断当前方法是否有@FunctionResult注解,如果没有则全部按照成功返回,如果有则根据具体指定的返回码以及返回内容返回
        FunctionResult result = returnType.getMethod().getAnnotation(FunctionResult.class);
        if (result == null) {
            if (body instanceof String) {
                return JSONUtil.toJsonStr(new BaseResponse(ResultCode.SUCCESS, body));
            }
            return new BaseResponse(ResultCode.SUCCESS, body);
        }
        if (body instanceof String) {
            return JSONUtil.toJsonStr(new BaseResponse(result.code(), body));
        }
        return new BaseResponse(result.code(), body);
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/356157.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Django框架之模型视图--HttpResponse对象

HttpResponse对象 视图在接收请求并处理后&#xff0c;必须返回HttpResponse对象或子对象。HttpRequest对象由Django创建&#xff0c;HttpResponse对象由开发人员创建。 1 HttpResponse 可以使用django.http.HttpResponse来构造响应对象。 HttpResponse(content响应体, con…

【opencv源码解析0.2】opencv库源码编译

如何编译opencv库源码 大家好&#xff0c;我是周旋&#xff0c;感谢大家学习【opencv源码解析】系列&#xff0c;本系列首发于公众号【周旋机器视觉】。 上篇文章我们介绍了如何配置opencv环境&#xff0c;搞清了opencv的包含目录include、静态库链接以及动态库链接的作用。 【…

(考研湖科大教书匠计算机网络)第五章传输层-第四节:TCP流量控制

获取pdf&#xff1a;密码7281专栏目录首页&#xff1a;【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一&#xff1a;流量控制概述二&#xff1a;流量控制举例三&#xff1a;拓展阅读&#xff08;可不看&#xff09;&#xff08;1&#xff09;TCP流量控制完整例子&a…

马上卸载这个恶心的软件!

大家好&#xff0c;我是良许。 春节已经过完了&#xff0c;但在这喜庆的日子里&#xff0c;又有一个小丑在上窜下跳了。 没错&#xff0c;这个不要脸的小丑依然还是 Notepad 的作者。 好好的一个开发者&#xff0c;为何老喜欢整一些有得没得的东西&#xff1f;好好搬砖写代码…

pygame8 扫雷游戏

一、游戏规则&#xff1a; 1、点击方格&#xff0c;如果是地雷&#xff0c;游戏失败&#xff0c;找到所有地雷游戏胜利 2、如果方块上出现数字&#xff0c;则表示在其周围的八个方块中共有多少颗地雷 二、游戏主逻辑&#xff1a; 主要逻辑即调用run_game, 然后循环检测事件…

云计算|OpenStack|社区版OpenStack---基本概念科普(kvm的驱动类别和安装)

前言&#xff1a; 云计算里基本都是基于kvm技术作为底层支撑&#xff0c;但&#xff0c;该技术是比较复杂的&#xff0c;首先&#xff0c;需要硬件的 支撑&#xff0c;表现在物理机上&#xff0c;就是需要在BIOS中调整设置虚拟化功能&#xff0c;这个虚拟机功能通常是interVT或…

Fastjson2基础使用以及底层序列化/反序列化实现探究

1 Fastjson2简介 Fastjson2是Fastjson的升级版&#xff0c;特征&#xff1a; 协议支持&#xff1a;支持JSON/JSONB两种协议部分解析&#xff1a;可以使用JSONPath进行部分解析获取需要的值语言支持&#xff1a;Java/Kotlin场景支持&#xff1a;Android8/服务端其他特性支持&a…

python基础知识有哪些需要背(记住是基础知识)我是初学者

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;一个有趣的事情&#xff0c;一个有趣的事情&#xff0c;今天让我们一起来看看吧&#xff01; 1、python基础知识有哪些需要背&#xff08;记住是基础知识&#xff09;我是初学者 或看好Python的广阔前景&#xff0c;或…

RabbitMQ 入门到应用 ( 五 ) 应用

6.更多应用 6.1.AmqpAdmin 工具类 可以通过Spring的Autowired 注入 AmqpAdmin 工具类 , 通过这个工具类创建 队列, 交换机及绑定 import org.springframework.amqp.core.AmqpAdmin; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.Di…

python基于django微信小程序的适老化老人健康预警小程序

随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生,各行各业相继进入信息管理时代, 适老化老人健康预警微信小程序就是信息时代变革中的产物之一。 任何系统都要遵…

Spring国际化实现

Java国际化 Java使用Unicode来处理所有字符。 Locales 国际化主要涉及的是数字、日期、金额等。 有若干个专门负责格式处理的类。为了对格式进行控制&#xff0c;可以使用Locale类。它描述了&#xff1a; 一种语言一个位置(通常包含)一段脚本(可选&#xff0c;自Java SE7开…

CMMI之需求开发流程

需求开发&#xff08;Requirement Development, RD&#xff09;的目的是通过调查与分析&#xff0c;获取用户需求并定义产品需求。需求开发过程域是SPP模型的重要组成部分。本规范阐述了需求开发过程域的两个主要规程&#xff1a; 需求调查 [SPP-PROC-RM-SURVEY] 需求定义 [SPP…

消失的数字【C语言】

题目&#xff1a; 数组nums包含从0到n的所有整数&#xff0c;但其中缺了一个。请编写代码找出那个缺失的整数。你有办法在O(n)时间内完成吗&#xff1f; 解法&#xff1a; int missingNumber(int* nums, int numsSize){int val0;for(int i0;i<numsSize;i){val^nums[i];}fo…

Vue3之条件渲染

1.何为条件渲染 条件渲染就是在指定的条件下&#xff0c;渲染出指定的UI。比如当我们显示主页的时候&#xff0c;应该隐藏掉登录等一系列不相干的UI元素。即UI元素只在特定条件下进行显示。而在VUE3中&#xff0c;这种UI元素的显示和隐藏可以通过两个关键字&#xff0c;v-if 和…

Qt动画框架详解

目录1.前言2.原理3.属性动画4.并行执行的动画5.顺序执行的动画6.扩展属性动画支持的数据类型1.前言 为软件适当的添加一些动画&#xff0c;能够提高软件的用户体验。在使用Qt框架开发软件时&#xff0c;我们可以用Qt提供的动画框架来为QWidget等UI元素添加动画效果。本文从动画…

程序员和他的女朋友一起创建了价值 150,000,000 美元的网站

本篇文章讲述了Otis和Elizabeth Chandler创办Goodreads.com的故事。他们从小就爱读书&#xff0c;创办网站前他们的困惑是没有很多人在线分享书评。Otis和Elizabeth觉得如果有一个地方把所有人的评论和评价收集起来&#xff0c;那将会很有价值。奥蒂斯和伊丽莎白从小就喜欢读书…

MMKV与mmap:全方位解析

概述 MMKV 是基于 mmap 内存映射的移动端通用 key-value 组件&#xff0c;底层序列化/反序列化使用 protobuf 实现&#xff0c;性能高&#xff0c;稳定性强。从 2015 年中至今&#xff0c;在 iOS 微信上使用已有近 3 年&#xff0c;其性能和稳定性经过了时间的验证。近期已移植…

海量数据相似数据查询方法

1、海量文本常见 海量文本场景&#xff0c;如何寻找一个doc的topn相似doc&#xff0c;一般存在2个问题&#xff0c; 1)、两两对比时间o(n^2) 2)、高维向量比较比较耗时。 文本集可以看成(doc,word)稀疏矩阵&#xff0c;一般常见的方法是构建到排索引&#xff0c;然后进行归并…

论文投稿指南——中文核心期刊推荐(社会学)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…

【论文精读】DeepWalk: Online Learning of Social Representations

DeepWalk: Online Learning of Social Representations 本文是我参加Datawhale的CS224W图机器学习时的笔记&#xff0c;第一次学习图机器学习&#xff0c;对DeepWalk这篇开山之作的理解。 论文的三位作者均来自纽约州立大学石溪分校&#xff0c;杨振宁和丘成桐也曾在此教学。 …