当前位置:   article > 正文

springboot后台统一返回处理_springboot中前后端不分离的项目中后端怎么返回响应

springboot中前后端不分离的项目中后端怎么返回响应

后台在接收前端请求数据的时候,后端处理完需要对前端请求的ajax或者H5页面的跳转做统一的返回处理,同时也需要对可能造成的异常进行全局统一处理,使当程序运行异常的时候ajax返回统一的异常码,H5请求跳转到统一的错误提示页面。

1、先对全局正常返回类进行包装


@RestControllerAdvice(basePackages = {"com.xxx.xxx.v2"})
public class ControllerResponseAdvice implements ResponseBodyAdvice<Object> {

    private static final Logger logger = LoggerFactory.getLogger(ControllerResponseAdvice.class);


    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        // response是ResultVo类型,或者注释了NotControllerResponseAdvice都不进行包装
        return !(methodParameter.getParameterType().isAssignableFrom(ResultVo.class)
                || methodParameter.hasMethodAnnotation(NotControllerResponseAdvice.class));
    }

    @Override
    public Object beforeBodyWrite(Object data, MethodParameter returnType, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        // String类型不能直接包装
        if (returnType.getGenericParameterType().equals(String.class)) {
            ObjectMapper objectMapper = new ObjectMapper();
            try {
                // 将数据包装在ResultVo里后转换为json串进行返回
                return objectMapper.writeValueAsString(new ResultVo(data));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // 否则直接包装成ResultVo返回
        return new ResultVo(data);
    }
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

ResultVo 为统一返回的包装类方便前台统一解析。



public class ResultVo {

    // 状态码
    private int code;

    // 状态信息
    private String msg;

    // 返回对象
    private Object data;

    // 手动设置返回vo
    public ResultVo(int code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    // 默认返回成功状态码,数据对象
    public ResultVo(Object data) {
        this.code = ResultCode.SUCCESS.getCode();
        this.msg = ResultCode.SUCCESS.getMsg();
        this.data = data;
    }

    // 返回指定状态码,数据对象
    public ResultVo(ResultCode resultCode, Object data) {
        this.code = resultCode.getCode();
        this.msg = resultCode.getMsg();
        this.data = data;
    }

    // 只返回状态码
    public ResultVo(ResultCode resultCode) {
        this.code = resultCode.getCode();
        this.msg = resultCode.getMsg();
        this.data = null;
    }

//省略get set方法
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

NotControllerResponseAdvice.class 这个类是一个注解,意思是忽略返回包装类,大概类似通信接口直接返回 success 就行了,需要要状态吗和返回数据体。注解这边写的可以先忽略注释掉。

这样的话当请求一个controller的时候在没有成功异常返回的都是正常的统一包装体了

@RestController
@RequestMapping("/textApi")
public class TextApi {

    @Autowired
    LoanService loanService;

    @RequestMapping("/queryLoan")
    public Loan queryLoan(){
        //int i = 1/0;
        return loanService.queryById(40L);
    }
    @RequestMapping("/queryPage")
    public ModelAndView queryPage(){
        //int i = 1/0;
        return new ModelAndView("/error");
    }

}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

在这里插入图片描述
可以看到代码里面直接返回的实体类,但前端接口返回的是在面自动加了ResultVo。

后面还需要对可能的异常做一下统一返回的处理,模拟逻辑错误可以把
int i = 1/0;这行代码的注释放开进行模拟。
首先创建一个全局异常类的拦截处理,对异常进项包装返回前端

@Slf4j
@RestControllerAdvice(basePackages = {"com.xxx.xxx.v2"})
public class GlobalExceptionHandlerV2 {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandlerV2.class);

    /**
     * 请求格式为json
     */
    private static final String APPLICATION_JSON = "application/json";
    /**
     * 请求格式为xml
     */
    private static final String XML_HTTP_REQUEST = "XMLHttpRequest";
    /**
     * json后缀
     */
    private static final String JSON_SUFFIX = ".json";
    /**
     * xml后缀
     */
    private static final String XML_SUFFIX = ".xml";
    /**
     * 索引越界
     */
    private static final int INDEX_NOT_FOUND = -1;


    @ExceptionHandler(value = Exception.class)
    ModelAndView MethodArgumentNotValidExceptionHandler(Exception e, HttpServletRequest request){
        //ajax 请求异常返回统一的错误码
        if(isAjaxRequest(request)){
            ModelAndView modelAndView=new ModelAndView(new MappingJackson2JsonView());
            modelAndView.addObject(new ResultVo(ResultCode.VALIDATE_ERROR, e.getMessage()));
            e.printStackTrace();
            return modelAndView;
        }else{
            //H5页面报错返回统一的样式
            ModelAndView modelAndView = new ModelAndView();
            modelAndView.addObject("msg",e.getMessage());
            modelAndView.setViewName("/error");
            e.printStackTrace();
            return modelAndView;
        }

    }

    /**
     * 是否是Ajax异步请求
     *
     * @param request 客户端请求
     * @return boolean
     */
    public static boolean isAjaxRequest(HttpServletRequest request) {
        String accept = request.getHeader("accept");
        if (accept != null && accept.contains(APPLICATION_JSON)) {
            return true;
        }

        String xRequestedWith = request.getHeader("X-Requested-With");
        if (xRequestedWith != null && xRequestedWith.contains(XML_HTTP_REQUEST)) {
            return true;
        }

        String uri = request.getRequestURI();
        if (inStringIgnoreCase(uri, JSON_SUFFIX, XML_SUFFIX)) {
            return true;
        }

        String ajax = request.getParameter("__ajax");
        return inStringIgnoreCase(ajax, "json", "xml");
    }


    /**
     * 是否包含字符串(不区分大小写)
     *
     * @param str           验证字符串
     * @param searchStrings 字符串组
     * @return boolean
     */
    public static boolean inStringIgnoreCase(String str, String... searchStrings) {
        if (str != null && searchStrings != null) {
            for (String s : searchStrings) {
                if (str.equalsIgnoreCase(StringUtils.trim(s))) {
                    return true;
                }
            }
        }
        return false;
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94

这里面进行了请求是否为ajax的判断,若是前端为ajax则返回统一的JSON格式,若是H5的页面跳转则跳到统一的error页面,其中 MappingJackson2JsonView这个类需要了解一下。

在这里插入图片描述
这个就进行的错误的统一返回包装了,前端获取到数据判断下code 不为约定的成功就是代表数据有问题了。

这个总体可以理解为两个流程:
1、先实现数据的统一返回。
2、全局controller的异常处理。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/652297
推荐阅读
相关标签
  

闽ICP备14008679号