springboot项目controller统一返回对象格式以及全局自定义异常方式

 更新时间:2025年11月03日 08:41:35   作者:0和1搭建网络世界  
本文介绍了在Web接口开发中,统一封装接口返回数据格式和处理运行时异常的重要性,通过使用@ControllerAdvice和ResponseBodyAdvice,可以实现全局拦截和封装,为了处理Swagger请求,提出了解决方案,包括对Swagger请求放行和自定义注解拦截特定接口

一、需求背景

1.在web接口开发时,每个模块接口返回数据格式需做封装,如果每个模块的返回格式不同,前端需要最不同数据格式的适配,使得整个项目很杂乱。如果对接口的返回数据做统一封装就解决此类问题。

2.项目的运行时异常,例如用户名错误此类的提示性异常,需要对此类异常做统一性封装。

二、方法

解决方法

问题一:使用@ControllerAdvice注解,以及实现ResponseBodyAdvice接口,从而实现拦截后再封装逻辑

问题二:使用@ControllerAdvice和@ExceptionHandler注解配合使用,从而捕获自定义异常类,实现逻辑的再处理。

三、具体实现

/**
*封装的接口统一返回对象
*/
@Data
public class ResultPo<T> {
    private int code;
    private String msg;
    private T data;

    public static<T> ResultPo<T> success(T t){
        ResultPo<T> resultPo = new ResultPo<>();
        resultPo.setCode(ResponseCodeEnum.SUCCESS.getCode());
        resultPo.setMsg(ResponseCodeEnum.SUCCESS.getMessage());
        resultPo.setData(t);
        return resultPo;
    }

    public static ResultPo error(int code,String msg){
        ResultPo resultPo = new ResultPo();
        resultPo.setCode(code);
        resultPo.setMsg(msg);
        return resultPo;
    }
}

// 自定义异常类
@Getter
public class BusinessException extends RuntimeException{
    private String msg;
    private int code;

    public  BusinessException(String msg){
        super(msg);
        this.msg =msg;
        this.code = ResponseCodeEnum.FAIL.getCode();
    }

    public  BusinessException(String msg,int code){
        super(msg);
        this.msg =msg;
        this.code = code;
    }
}


@ResponseBody
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice<Object> {

    Logger log = LoggerFactory.getLogger(ResponseAdvice.class);

	// 自定义异常捕获
    @ExceptionHandler(BusinessException.class)
    public ResultPo customException(BusinessException bs){
        ResultPo resultPo = new ResultPo();
        resultPo.setCode(bs.getCode());
        resultPo.setMsg(bs.getMsg());
        resultPo.setData(null);
        return resultPo;
    }
	
	/**
	*return turn 代表此接口会进入beforeBodyWrite方法,进行逻辑处理
	*/
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return !returnType.getDeclaringClass().getName().contains("springfox");
//        return true;
    }

    @Nullable
    @Override
    public Object beforeBodyWrite(@Nullable Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    	// 如果接口返回为string类型,则需要单独处理
        if(returnType.getGenericParameterType().equals(String.class)){
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                HttpHeaders headers = response.getHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                return objectMapper.writeValueAsString(ResultPo.success(body));
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
        }
        // 接口出现自定义异常,已被customException方法捕获,则无需再次封装
        if(returnType.getGenericParameterType().equals(ResultPo.class)){
            return body;
        }
        return ResultPo.success(body);
    }
}

四、遇到的问题

当项目中使用swagger时,会拦截swagger的相关请求

出现的原因:@ControllerAdvice注解会拦截@Controller以及@RestController标记的接口,而swagger的接口是web接口,也是带有@RestController相关接口

解决方法:

1.对swagger进行放行,就是上面代码中那样,放行带有springfox字样的接口

@Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return !returnType.getDeclaringClass().getName().contains("springfox");
//        return true;
    }

2.自定义一个注解,在需要统一返回值的接口上添加上自定义注解,然后@ControllerAdvice根据自定义注解进行拦截

// ResponseResult为自定义注解
@ControllerAdvice(annotations = ResponseResult.class)

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot应用线上重启脚本的命令详解

    SpringBoot应用线上重启脚本的命令详解

    这篇文章主要介绍了SpringBoot应用线上重启脚本,通过查找应用进程PID,杀死应用进程PID,运行启动脚本,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • java RocketMQ快速入门基础知识

    java RocketMQ快速入门基础知识

    这篇文章主要介绍了java RocketMQ快速入门基础知识,所以RocketMQ是站在巨人的肩膀上(kafka),又对其进行了优化让其更满足互联网公司的特点。它是纯Java开发,具有高吞吐量、高可用性、适合大规模分布式系统应用的特点。,需要的朋友可以参考下
    2019-06-06
  • Java基础之多线程

    Java基础之多线程

    以下是我们Java基础多线程的一些知识点总结,看完以后会觉得多线程也可以这么简单,小编精心推荐,希望能对大家有所帮助
    2018-09-09
  • 解析Java中如何获取Spring中配置的bean

    解析Java中如何获取Spring中配置的bean

    本篇文章是对在Java中如何获取Spring中配置的bean进行了详细的分析介绍,需要的朋友参考下
    2013-07-07
  • Java使用FFM API调用SDL详解

    Java使用FFM API调用SDL详解

    这篇文章主要为大家详细介绍了Java如何使用FFM API调用SDL,文中的示例代码讲解详细,具有一定的借鉴价值,有需要的小伙伴可以参考一下
    2025-01-01
  • Springboot中com.mysql.cj.jdbc.Driver在yml文件中爆红的原因解读

    Springboot中com.mysql.cj.jdbc.Driver在yml文件中爆红的原因解读

    这篇文章主要介绍了Springboot中com.mysql.cj.jdbc.Driver在yml文件中爆红的原因解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • 贪心算法原理及在Java中的使用

    贪心算法原理及在Java中的使用

    我们可能在好多地方都会听到贪心算法这一概念,并且它的算法思想也比较简单就是说算法只保证局部最优,进而达到全局最优。但我们实际编程的过程中用的并不是很多,究其原因可能是贪心算法使用的条件比较苛刻,所要解决的问题必须满足贪心选择性质
    2021-05-05
  • Java求出任意数字的各个位数之和方式

    Java求出任意数字的各个位数之和方式

    这篇文章主要介绍了Java求出任意数字的各个位数之和方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01
  • SpringBoot项目使用Liquibase数据库版本管理方式

    SpringBoot项目使用Liquibase数据库版本管理方式

    Liquibase是开源数据库版本管理工具,支持多数据库及多格式变更日志,实现变更追踪、上下文执行、文档生成等功能,需配置目录结构及master.xml文件,注意@PostConstruct初始化顺序问题,建议用CommandLineRunner替代
    2025-09-09
  • Java实现读取html文本内容并按照格式导出到excel中

    Java实现读取html文本内容并按照格式导出到excel中

    这篇文章主要为大家详细介绍了如何使用Java实现读取html文本提取相应内容按照格式导出到excel中,文中的示例代码讲解详细,需要的可以参考下
    2024-02-02

最新评论