Springboot 统一响应消息处理

普通返回类型处理

  • 使用统一响应消息处理,我们可以不用在每个函数的返回值写上特殊的类型对象, 直接写基础类型,或者封装类型都可以。

直接上代码:
1.首先得使用 fastjson 作为统一消息转换器

@Configuration

public class GlobalConfigimplements WebMvcConfigurer {
    /**
     *  配置消息转换器
     *
     * @return: void
     */
    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {

        FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
        // 设置默认编码
        converter.setDefaultCharset(StandardCharsets.UTF_8);
        // 设置类型
        converter.setSupportedMediaTypes(Collections.singletonList(MediaType.APPLICATION_JSON));
        // 清除所有转换器
        converters.clear();
        converters.add(converter);
    }
}

2.定义格式化返回类

@Data
@ApiModel("统一数据返回模型")
public class Result<T> {

    @ApiModelProperty(value = "响应值")
    private int status;

    @ApiModelProperty(value = "请求是否成功")
    private boolean success;

    @ApiModelProperty(value = "响应信息")
    private String msg;

    @ApiModelProperty(value = "响应数据")
    private T data;
}

3.创建统一响应处理注解

/**
 * 统一响应处理注解
 * @author: enncy
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ResponseHandler {
}

4.在你想要处理的类上面增加注解
在这里插入图片描述

5.使用 RestControllerAdvice环绕增强,同时继承 ResponseBodyAdvice,处理响应信息

@Slf4j
@RestControllerAdvice
public class ResponseInterceptor implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {

        Result<Object> result = new Result<>();
        // 设置响应码
        result.setStatus(200);
        Method method = methodParameter.getMethod();
        if (method == null) {
            return o;
        } else {
            // 如果存在 Api 注释,则返回注释和其他信息,否则返回简单的"请求" 描述 请求成功或者失败
            String preMsg = Optional.ofNullable(method.getAnnotation(ApiOperation.class)).map(ApiOperation::value).orElse("请求");
            //设置响应信息
            result.setMsg( preMsg + "成功");
            // 设置响应数据
            result.setData(o);
            result.setSuccess(o!=null);
            return result;
        }
    }
}

异常返回类型处理

  • 将一个空的 ErrorController 接口当做 Bean,以便可以覆盖 Spring boot 的默认异常处理
  • 然后在Spring 配置类中实现 ErrorPageRegistrar 接口将指定的异常信息传递到每个异常接口上。
  • 最后指定一个规则,如果函数的返回值是 Throwable 或者子类,我们当做异常信息处理

1.封装错误的请求响应码
复制粘贴这篇文章的工具类 HttpErrorStateConverter 即可
https://blog.csdn.net/qq_31254489/article/details/119772129

2.配置错误页面

@Configuration
public class GlobalConfig  implements ErrorPageRegistrar {
    /**
     * 配置错误页面
     *
     * @return: org.springframework.boot.web.servlet.error.ErrorController
     */
    @Override
    public void registerErrorPages(ErrorPageRegistry registry) {
        registry.addErrorPages(Arrays.stream(HttpErrorStateConverter.values())
                .map(c->c.status)
                .map(s->new ErrorPage(s, "/error?status=" + s.value()))
                .toArray(ErrorPage[]::new));
    }
}

**3.创建一个异常控制器 MyErrorController **

  • 只要实现了 ErrorController 接口, Springboot 的默认错误页面就会被移除。
@RestController
@ResponseHandler
public class MyErrorController implements ErrorController {

    @RequestMapping("/error")
    public String handle(@RequestParam("status") int status) {
  
        HttpStatus httpStatus = HttpStatus.resolve(status);
        if (httpStatus != null) {
            // 返回转换过的响应信息
            HttpErrorStateConverter resolver = HttpErrorStateConverter.resolve(httpStatus.value());
            return resolver == null ? httpStatus.toString() : resolver.description;
        } else {
            // 返回 404 信息
            return HttpErrorStateConverter.NOT_FOUND.description;
        }
    }
}

4.最后修改我们的 ResponseInterceplter

@Slf4j
@RestControllerAdvice
public class ResponseInterceptor implements ResponseBodyAdvice<Object> {

    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @Autowired
    HttpServletResponse response;

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
    	// 通过相应码去判断是否为错误信息
        HttpStatus status = Optional.ofNullable(HttpStatus.resolve(response.getStatus())).orElse(HttpStatus.NOT_FOUND);

        Result<Object> result = new Result<>();
        // 设置响应码
        result.setStatus(response.getStatus());
        boolean error = status.isError();
        // 设置请求是否成功
        result.setSuccess(!error);
 
        if (error) {
            // 响应数据置空
            result.setData(null);
            // 响应错误信息
            result.setMsg(o.toString());
            return result;
        } else if (methodParameter.getDeclaringClass().isAnnotationPresent(ResponseHandler.class)) {

            Method method = methodParameter.getMethod();
            if (method == null) {
                return o;
            } else {
                // 如果存在 Api 注释,则返回注释和其他信息,否则返回简单的"请求" 描述 请求成功或者失败
                String preMsg = Optional.ofNullable(method.getAnnotation(ApiOperation.class)).map(ApiOperation::value).orElse("请求");
                //设置响应信息
                result.setMsg(preMsg + "成功");
                // 设置响应数据
                result.setData(o);

                System.out.println(result);

                return result;
            }

        } else {
            return o;
        }
    }
}

处理服务器内部错误

只要配置好之前的东西,做这个就很简单
只需要修改我们的 MyErrorController
添加一个 @RestControllerAdvice 环绕增强注解
然后添加 @ExceptionHandler 注解到我们的方法上去处理异常即可

@RestController
@ResponseHandler
@RestControllerAdvice
@Api(tags = "統一错误请求控制")
public class MyErrorController implements ErrorController {

    /**
     *  1.处理指定的抛出异常 , 这里不要指定 Exception , 范围太大, 很多东西不好处理
     *  2.设置响应码为 500  —— @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
     * @return: java.lang.String
     */
    @ExceptionHandler(value = {HttpMessageNotReadableException.class})
    @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
    public String error(HttpMessageNotReadableException e, HttpServletResponse response){
        return findCause(e).getMessage();
    }

    /*
     *  递归查找原因
     */
    public <T extends Throwable> Throwable findCause(T throwable){
        return throwable.getCause() != null ? findCause(throwable.getCause()) : throwable;
    }

    public <T extends Throwable> Throwable findCause(T throwable){
        return throwable.getCause() != null ? findCause(throwable.getCause()) : throwable;
    }


    @RequestMapping(value = "/error", method = {RequestMethod.GET, RequestMethod.POST})
    @ApiOperation("错误显示")
    public String handle(@RequestParam("status") int status) {

        HttpStatus httpStatus = HttpStatus.resolve(status);
        if (httpStatus != null) {
            // 返回转换过的响应信息
            HttpErrorStateConverter resolver = HttpErrorStateConverter.resolve(httpStatus.value());
            return resolver == null ? httpStatus.toString() : resolver.description;
        } else {
            // 返回 404 信息
            return HttpErrorStateConverter.NOT_FOUND.description;
        }
    }
}

测试

测试服务器内部错误
在这里插入图片描述

在这里插入图片描述

测试 404
在这里插入图片描述

测试请求方法不允许

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值