SPRING REST API 返回结果处理和异常处理

原创
2017/06/29 16:04
阅读数 7.2K

包装正常返回结果

Spring 提供了 ResponseBodyAdvice interface, 处理ResonseEntity 返回值,这个接口实现了两个方法,可以实现返回结果的自定义处理

@ControllerAdvice(annotations = {RestController.class})
public class ApiResponseAdvice implements ResponseBodyAdvice {


    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {

        if (selectedContentType.includes(MediaType.APPLICATION_JSON) ||
                selectedContentType.includes(MediaType.APPLICATION_JSON_UTF8)) {
            if (!response.getHeaders().containsKey(SDKConstant.NOT_TRANSFORM_BODY)) {  //有些错误已经格式化为指定的返回类型
                Map<String, Object> map = new HashMap<>();
                map.put("errorCode", 200);
                map.put("message", "success");
                map.put("data", body);
                return map;
            } else {
                return body;
            }
        }
        return body;
    }
}

  1. @ControllerAdvice 这个Annotation 是指定要处理的Controller, 这个处理所有带 @RestController 的Controller.

  2. supports(...) 方法,可以指定需要处理的方法

  3. beforeBodyWrite(...) 方法,进一步过滤处理最后的结果

Controller 异常处理

@ControllerAdvice(annotations = {RestController.class})
  public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler{
        
                @ExceptionHandler(value = ScBaseException.class)
                public void exceptionHandle(...){
                    // 这里你可以返回新的body
                }
}

  1. @ExceptionHandle 这个新增的注解就是用来处理最后抛到Controller的异常,这个也是自定义可以控制的地方非常多,比如我们自定的异常

  2. 但是这个好像捕获不了参数校验等异常,所以再加上第三步

Validator 异常 和 参数错误等校验异常处理

在RestController 中, Validator 异常 和 参数错误等校验异常处理,会重定向至 /error 的请求,所以我们会在这里做处理

Validator 异常


@RequestMapping(value = "/search/code", method = RequestMethod.GET)
public ResponseEntity<Object> getCompanyCodeSearchResult(@Valid CompanyCodeReq companyCodeReq,
 BindingResult result, HttpServletResponse response) {

        // 处理 Validator 出错的情况
        if(result.hasErrors()){
            Map<String, Object> errorMap = ResponseUtil.buildFieldBindErrorMap(result.getFieldError().getDefaultMessage());
            response.addHeader(SDKConstant.NOT_TRANSFORM_BODY, HttpStatus.BAD_REQUEST.toString());
            return ResponseEntity.badRequest().body(errorMap);
        }
        CompanyCodeResp searchResult = companyApiService.getCodeSearchResult();

        return new ResponseEntity<>(searchResult, HttpStatus.OK);
    }


  1. 在Controller 中获取 BindingResult 的结果,并在其中获取出错的消息,返回异常的结果
  2. ResponseEntity.badRequest().body(errorMap) ,这个方法就可以放回指定的结果了,这里设置了 header,用于上面的 ControllerAdvice 做过滤使用。

参数错误等校验异常处理

@RequestMapping(path = "/error", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    @ResponseBody
    public Map<String, Object> handle(HttpServletRequest request) {

        Map<String, Object> map = new HashMap<>();
        map.put("errorCode",request.getAttribute("javax.servlet.error.status_code"));
        if (StringUtils.isNoneBlank(request.getAttribute("javax.servlet.error.message").toString())) {
            map.put("message", request.getAttribute("javax.servlet.error.message"));
        } else {
            map.put("message", "请求参数或方法错误");
        }
        map.put("data", null);
        return map;
    }

这个就相当于 做 Spring MVC 的时候,View 的功能

<error-page>
    <location>/error</location>
</error-page>

参考

spring doc

展开阅读全文
打赏
0
41 收藏
分享
加载中
OrangeJoke博主

引用来自“448540132”的评论

建议errorCode换个名称,比如code或retCode,这样的话不但可以表示错误状态码,也可以表示其他状态码,灵活度更高

good suggestion, thank you回复@448540132 :
2017/07/07 10:16
回复
举报
建议errorCode换个名称,比如code或retCode,这样的话不但可以表示错误状态码,也可以表示其他状态码,灵活度更高
2017/07/03 15:10
回复
举报
更多评论
打赏
2 评论
41 收藏
0
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部