zoukankan      html  css  js  c++  java
  • Spring boot返回值封装与业务异常

    对于spring来说 返回值封装与业务异常 是一项很古老却实用的技术
    然而在我上一份工作的时候依然碰到公司的新项目没有这2步处理
    在SpringMVC时期已经可以通过xml配置达成以上目的
    不过xml配置太过繁琐而且不容易排错 远不如Spring boot的注解+java代码清爽

    以下将逐步详述配置方法

    1. 在***pom.xml中添加依赖
      <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.3</version>
      </parent>
    
        <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    
    1. 添加通用返回值的包装类Result
    import lombok.Data;
    
    @Data
    public class Result {
        private String status = "success";
        private String msg = "";
        private int code = 200;
        private Object result;
    }
    
    1. 实现自定义的ResponseBody处理类OutputProxy
    import org.springframework.core.MethodParameter;
    import org.springframework.web.context.request.NativeWebRequest;
    import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
    import org.springframework.web.method.support.ModelAndViewContainer;
    
    import demo.entity.Result;
    
    public class OutputProxy implements HandlerMethodReturnValueHandler
    {
        private HandlerMethodReturnValueHandler proxyObject;
    
        public OutputProxy(HandlerMethodReturnValueHandler proxyObject)
        {
            this.proxyObject = proxyObject;
        }
    
        @Override
        public boolean supportsReturnType(MethodParameter returnType)
        {
            return proxyObject.supportsReturnType(returnType);
        }
    
        @Override
        public void handleReturnValue(Object returnValue, MethodParameter returnType, ModelAndViewContainer mavContainer,
                NativeWebRequest webRequest) throws Exception
        {
            Result result = new Result();
            result.setResult(returnValue);
            proxyObject.handleReturnValue(result, returnType, mavContainer, webRequest);
        }
    }
    
    
    1. 将自定义的处理类作为bean提交给框架
    import java.util.ArrayList;
    import java.util.List;
    
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
    import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
    import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;
    
    @Configuration
    public class OutputConfig implements InitializingBean
    {
        @Autowired
        private RequestMappingHandlerAdapter handlerAdapter;
    
        @Override
        public void afterPropertiesSet() throws Exception
        {
            List<HandlerMethodReturnValueHandler> list = handlerAdapter.getReturnValueHandlers();
            List<HandlerMethodReturnValueHandler> newList = new ArrayList<>();
            if (null != list)
            {
                for (HandlerMethodReturnValueHandler valueHandler : list)
                {
                    if (valueHandler instanceof RequestResponseBodyMethodProcessor)
                    {
                        OutputProxy proxy = new OutputProxy(valueHandler);
                        newList.add(proxy);
                    }
                    else
                    {
                        newList.add(valueHandler);
                    }
                }
            }
            handlerAdapter.setReturnValueHandlers(newList);
        }
    }
    
    1. 添加业务异常的包装类MyException
    import javax.servlet.ServletException;
    
    public class MyException extends RuntimeException
    {
        private static final long serialVersionUID = 881236006282985783L;
    
        private static final Integer STACK_INDEX = 2;
    
        public MyException(String msg)
        {
            super(msg);
            String position = Thread.currentThread().getStackTrace()[STACK_INDEX].getClassName() + "."
                    + Thread.currentThread().getStackTrace()[STACK_INDEX].getMethodName() + "("
                    + Thread.currentThread().getStackTrace()[STACK_INDEX].getFileName() + ":"
                    + Thread.currentThread().getStackTrace()[STACK_INDEX].getLineNumber() + ")";
            System.err.println(msg + "    " + position);
        }
    
    }
    
    1. 添加业务异常处理
    import java.util.List;
    
    import org.springframework.validation.BindingResult;
    import org.springframework.validation.ObjectError;
    import org.springframework.web.bind.MethodArgumentNotValidException;
    import org.springframework.web.bind.annotation.ControllerAdvice;
    import org.springframework.web.bind.annotation.ExceptionHandler;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import demo.entity.Result;
    import demo.utils.ResultUtil;
    
    @ControllerAdvice
    public class ExceptionHandle
    {
        private static final int MSG_NUM = 501;
        private static final int VALID_NUM = 502;
        private static final int USUAL_NUM = 500;
    
        @ResponseBody
        @ExceptionHandler(Exception.class)
        public Result handle(Exception e)
        {
            if (e instanceof MyException)
            {
                return ResultUtil.error(MSG_NUM, e.getMessage());
            }
            else if (e instanceof MethodArgumentNotValidException)
            {
                BindingResult result = ((MethodArgumentNotValidException) e).getBindingResult();
                List<ObjectError> errors = result.getAllErrors();
                ObjectError error = errors.get(errors.size() - 1);
                return ResultUtil.error(VALID_NUM, error.getDefaultMessage());
            }
            else
            {
                e.printStackTrace();
                return ResultUtil.error(USUAL_NUM, e.getMessage());
            }
        }
    }
    

    小结:

    1. 通过返回值封装可以使我们的代码更简洁
      在类上添加@RestController注解
      直接返回java类(例如 一个包含元素56的数组)
      前台就可以得到如下json
    {
    	"status": "success",
    	"msg": "",
    	"code": 200,
    	"result": [56]
    }
    
    1. 通过业务异常处理可以使我们的代码逻辑更清晰 例如:
      当我们认为前台传来的某个值不应为**空*时 只要
    if (!StringUtils.hasLength(id)) {
        throw new MyException("id不应为空");
    }
    

    前台就可以得到如下json

    {
    	"status": "error",
    	"msg": "id不应为空",
    	"code": 501,
    	"result": null
    }
    
  • 相关阅读:
    Laravel 初始化
    ant design pro 左上角 logo 修改
    请求到服务端后是怎么处理的
    Websocket 知识点
    王道数据结构 (7) KMP 算法
    王道数据结构 (6) 简单的模式匹配算法
    王道数据结构 (4) 单链表 删除节点
    王道数据结构 (3) 单链表 插入节点
    王道数据结构 (2) 单链表 尾插法
    王道数据结构 (1) 单链表 头插法
  • 原文地址:https://www.cnblogs.com/cutter/p/14466154.html
Copyright © 2011-2022 走看看