项目基于springboot构建,为了和前端交互接口,后台中集成了swagger。具体swagger如何使用可以另开一篇去说。
在进行项目优化的时候,为了让controller接口的返回值语义比较清晰,而不是统一返回ApiResult,类似于上图中的结构(请忽略背景图)。在项目中引入了以下代码
package com.yizhun.label.user.config;
import com.yizhun.auth.model.ApiResult;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import springfox.documentation.spring.web.json.Json;
import springfox.documentation.swagger.web.SwaggerResource;
import springfox.documentation.swagger.web.UiConfiguration;
import java.util.ArrayList;
/**
* @author alex
* @version 1.0
* @date 2021-01-18 下午9:58
*/
@RestControllerAdvice
public class GlobalResponseBodyAdvice implements ResponseBodyAdvice<Object> {
@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) {
// 这里需要过滤掉swagger的相关返回
if (body instanceof ApiResult)
return body;
return new ApiResult(body);
}
}
在配置完以后偶然发现项目集成的swagger无法显示,由于当时代码改动比较多,第一时间并没有想到是因为配置了全局响应的这个advice导致的问题。由于一直无法解决swagger失效的问题,无奈的只能把所有的code回滚,本着一步一个脚印的原则,改动一点代码就run下看swagger是否正常,一直到加了上述配置以后才发现问题所在。
在没有增加全局响应以前,所有的接口都是直接返回各自的内容,增加了全局响应以后,相当于对返回值做了一层封装,导致swagger相关接口返回结构发生变化,导致swagger失效。于是修改了override的beforeBodyWrite方法
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
// 这里需要过滤掉swagger的相关返回
if (body instanceof ApiResult || body instanceof Json || body instanceof UiConfiguration || (body instanceof ArrayList && ((ArrayList) body).get(0) instanceof SwaggerResource))
return body;
return new ApiResult(body);
}
swagger涉及到三个接口,分别是
- {domain}/swagger-resources/configuration/ui
- {domain}/swagger-resources
- {domain}/v2/api-docs 三个接口到达beforeBodyWrite方法时返回值body的类型分别是
- UiConfiguration
- ArrayList
- Json 这里为了单独处理swagger-resources返回的ArrayList,又加了层判断,如果body的类型是ArrayList并且它第一个元素的类型是SwaggerResource则直接跳过,解决的code如下:
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
// 这里需要过滤掉swagger的相关返回
if (body instanceof ApiResult || body instanceof Json || body instanceof UiConfiguration || (body instanceof ArrayList && ((ArrayList) body).get(0) instanceof SwaggerResource))
return body;
return new ApiResult(body);
}
基于以上代码,处理项目配置全局响应导致swagger失效的问题。