统一出参管理

统一出参只要实现 ResponseBodyAdvice 接口,并且注解增强 @RestControllerAdvice 就可以了。

实现类:

/**
 * @Description:
 * @author: LinQin
 * @date: 2020/01/08
 */
@RestControllerAdvice
public class GlobalResponseBodyAdvice implements ResponseBodyAdvice<Object> {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        if (methodParameter.getMethod().getName().equals("login")) {
            return true;
        }
        return false;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        if (o instanceof ResultModel) {
            ((ResultModel) o).setPath(serverHttpRequest.getURI().getPath());
            return o;
        }
        // 这里进行封装返回
        ResultModel resultModel = new ResultModel();
        if (isPrimitiveOrVoid(methodParameter.getParameterType())) {
            ObjectNode resultNode = objectMapper.createObjectNode();
            resultNode.putPOJO("result", o);
            o = resultNode;
        }
        resultModel.setData(o);

        String result = null;
        try {
            result = objectMapper.writeValueAsString(resultModel);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        boolean isString = methodParameter.getParameterType() == String.class;
        //当返回值为字符串时,springMVC会使用StringHttpMessageConverter来处理,返回值必须为String,否则会转换异常
        if (isString) {
            serverHttpResponse.getHeaders().add("Content-Type",
                    "application/json;charset=UTF-8");
            return result;
        }

        return resultModel;
    }

    private boolean isPrimitiveOrVoid(Class<?> returnType) {
        return returnType.isPrimitive()
                || Number.class.isAssignableFrom(returnType)
                || CharSequence.class.isAssignableFrom(returnType)
                || Character.class.equals(returnType)
                || Boolean.class.equals(returnType);
    }
}

**注意:**异常处理后的也会入到经过出参,意味着如果统一异常处理过程中进行了封装,到这里还会执行一次。因此会有封装了两层的报文,但是正常情况是正确的这种现象。

解决方案:

增加一个判断返回即可。

   if (o instanceof ResultModel) {
            ((ResultModel) o).setPath(serverHttpRequest.getURI().getPath());
            return o;
        }

项目地址:GitHub

上次更新时间: 2024/5/7 05:59:02