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
    }
    
  • 相关阅读:
    Silverlight 2 开发环境
    Silverlight: 通过LINQ 和Isolated Storage构建客户端数据库
    奥巴马就职委员会选择微软Silverlight技术
    Silverlight 和WPF的Composite Guidance(Prism V2)发布了
    分布式计算平台:Dryad
    Ironclad
    WCF安全指南
    WPF/Silverlight中的Command
    Silverlight 2 控件 SDK 源代码
    Mono 2.2 发布了
  • 原文地址:https://www.cnblogs.com/cutter/p/14466154.html
Copyright © 2011-2022 走看看