普通返回类型处理
- 使用统一响应消息处理,我们可以不用在每个函数的返回值写上特殊的类型对象, 直接写基础类型,或者封装类型都可以。
直接上代码:
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
测试请求方法不允许