zoukankan      html  css  js  c++  java
  • spring boot 2 全局统一返回RESTful风格数据、统一异常处理

    全局统一返回RESTful风格数据,主要是实现ResponseBodyAdvice接口的方法,对返回值在输出之前进行修改。
    使用注解@RestControllerAdvice拦截异常并统一处理。

    开发环境:
    IntelliJ IDEA 2019.2.2
    jdk1.8
    Spring Boot 2.2.2

    1、创建一个SpringBoot项目,pom.xml引用的依赖包如下

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
    
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.62</version>
            </dependency>

    2、定义一个返回类

    package com.example.response.entity;
    
    import lombok.Data;
    import lombok.NoArgsConstructor;
    import lombok.ToString;
    
    import java.io.Serializable;
    
    @Data
    @NoArgsConstructor
    @ToString
    public class ResponseData<T> implements Serializable {
        /**
         * 状态码:0-成功,1-失败
         * */
        private int code;
    
        /**
         * 错误消息,如果成功可为空或SUCCESS
         * */
        private String msg;
    
        /**
         * 返回结果数据
         * */
        private T data;
    
        public static ResponseData success() {
            return success(null);
        }
    
        public static ResponseData success(Object data) {
            ResponseData result = new ResponseData();
            result.setCode(0);
            result.setMsg("SUCCESS");
            result.setData(data);
            return result;
        }
    
        public static ResponseData fail(String msg) {
            return fail(msg,null);
        }
    
        public static ResponseData fail(String msg, Object data) {
            ResponseData result = new ResponseData();
            result.setCode(1);
            result.setMsg(msg);
            result.setData(data);
            return result;
        }
    }

    3、统一拦截接口返回数据

    新建一个类GlobalResponseHandler,用注解@RestControllerAdvice,并且实现ResponseBodyAdvice接口的方法,其中方法supports可以判断哪些需要拦截,方法beforeBodyWrite可以对返回值在输出之前进行修改,从而实现返回统一的接口数据。

    package com.example.response.config;
    
    import com.alibaba.fastjson.JSON;
    import com.example.response.entity.ResponseData;
    import org.springframework.core.MethodParameter;
    import org.springframework.http.MediaType;
    import org.springframework.http.converter.HttpMessageConverter;
    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;
    
    /**
     * 实现ResponseBodyAdvice接口,可以对返回值在输出之前进行修改
     */
    @RestControllerAdvice
    public class GlobalResponseHandler implements ResponseBodyAdvice<Object> {
    
        //判断支持的类型
        @Override
        public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
            // 检查注解是否存在,存在则忽略拦截
            if (methodParameter.getDeclaringClass().isAnnotationPresent(IgnorReponseAdvice.class)) {
                return false;
            }
            if (methodParameter.getMethod().isAnnotationPresent(IgnorReponseAdvice.class)) {
                return false;
            }
            return true;
        }
    
        @Override
        public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
            // 判断为null构建ResponseData对象进行返回
            if (o == null) {
                return ResponseData.success();
            }
            // 判断是ResponseData子类或其本身就返回Object o本身,因为有可能是接口返回时创建了ResponseData,这里避免再次封装
            if (o instanceof ResponseData) {
                return (ResponseData<Object>) o;
            }
            // String特殊处理,否则会抛异常
            if (o instanceof String) {
                return JSON.toJSON(ResponseData.success(o)).toString();
            }
            return ResponseData.success(o);
        }
    }
    新建自定义注解IgnorReponseAdvice
    package com.example.response.config;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target({ElementType.TYPE, ElementType.METHOD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface IgnorReponseAdvice {
    }

    4、统一异常处理

    package com.example.response.exception;
    import com.example.response.entity.ResponseData;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.RestControllerAdvice;
    
    @RestControllerAdvice
    public class GlobalExceptionHandler {
        @ExceptionHandler(Exception.class)
        public ResponseData exceptionHandler(Exception e) {
            e.printStackTrace();
            return ResponseData.fail("服务器异常:" + e.getMessage());
        }
    }

    5、新建一个测试用的实体类

    package com.example.response.entity;
    
    import lombok.Data;
    
    @Data
    public class User {
        private Long userId;
        private String userName;
        public User(Long userId, String userName){
            this.userId = userId;
            this.userName = userName;
        }
    }

    6、新建一个测试用的控制器类

    package com.example.response.controller;
    
    import com.example.response.config.IgnorReponseAdvice;
    import com.example.response.entity.ResponseData;
    import com.example.response.entity.User;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.ArrayList;
    import java.util.List;
    
    @RestController
    public class DemoController {
        @GetMapping("user")
        public User user() {
            User u = new User(100L, "u1");
            return u;
        }
    
        @GetMapping("userList")
        public List<User> userList(){
            List<User> list = new ArrayList<User>();
            list.add(new User(100L, "u1"));
            list.add(new User(200L, "u2"));
            return list;
        }
    
        @GetMapping("test1")
        public String test1(){
            return "test1";
        }
    
        @GetMapping("test2")
        public ResponseData test2(){
            return ResponseData.success("test2");
        }
    
        @IgnorReponseAdvice
        @GetMapping("test3")
        public String test3() {
            return "test3";
        }
    
        @GetMapping("test4")
        public String test4() {
            Integer x = 1 / 0;
            return x.toString();
        }
    
        @GetMapping("test5")
        public String test5() throws Exception {
            throw new Exception("自定义异常信息");
        }
    }

    7、用Postman测试

    (1)请求http://localhost:8080/user,返回

    {
        "code": 0,
        "msg": "SUCCESS",
        "data": {
            "userId": 100,
            "userName": "u1"
        }
    }

    (2)请求http://localhost:8080/userList,返回

    {
        "code": 0,
        "msg": "SUCCESS",
        "data": [
            {
                "userId": 100,
                "userName": "u1"
            },
            {
                "userId": 200,
                "userName": "u2"
            }
        ]
    }

    (3)请求http://localhost:8080/tes1,返回

    {"msg":"SUCCESS","code":0,"data":"test1"}

    (4)请求http://localhost:8080/test2,返回

    {
        "code": 0,
        "msg": "SUCCESS",
        "data": "test2"
    }

    (5)请求http://localhost:8080/test3,返回

    test3

    (6)请求http://localhost:8080/test4,返回

    {
        "code": 1,
        "msg": "服务器异常:/ by zero",
        "data": null
    }

    (7)请求http://localhost:8080/test5,返回

    {
        "code": 1,
        "msg": "服务器异常:自定义异常信息",
        "data": null
    }

      

    参考文章:
    https://blog.csdn.net/lrt890424/article/details/83624761
    https://www.cnblogs.com/Purgeyao/p/11599810.html

  • 相关阅读:
    搭建Nginx反向代理做内网域名转发
    网站监测脚本
    Nginx启动脚本
    L2TP用户添加和删除、搜索脚本
    CentOS Linux 安装IPSec+L2TP
    Nginx认证
    Nginx配置HTTPS
    Nginx 如何处理一个请求
    HTTP协议原理
    DNS解析流程
  • 原文地址:https://www.cnblogs.com/gdjlc/p/12077593.html
Copyright © 2011-2022 走看看