-
问题
集成springdoc出现以下这个界面:
image.png
当前使用版本:
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>2.8.8</version>
</dependency>
这是自动跳转到示例数据了:
<hgroup class="main" style="box-sizing: inherit; margin: 0px 0px 20px; color: rgb(59, 65, 81); font-family: sans-serif; font-size: medium; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(250, 250, 250); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;">
## Swagger Petstore <small style="box-sizing: inherit; font-size: 10px; background: rgb(125, 132, 146); border-radius: 57px; display: inline-block; margin: 0px 0px 0px 5px; padding: 2px 4px; position: relative; top: -5px; vertical-align: super;"><pre class="version" style="box-sizing: border-box; font-family: sans-serif; font-size: 14px; color: rgb(255, 255, 255); margin: 0px; padding: 0px;"> 1.0.7 </pre></small> <small class="version-stamp" style="box-sizing: inherit; font-size: 10px; background: rgb(137, 191, 4); border-radius: 57px; display: inline-block; margin: 0px 0px 0px 5px; padding: 2px 4px; position: relative; top: -5px; vertical-align: super;"><pre class="version" style="box-sizing: border-box; font-family: sans-serif; font-size: 14px; color: rgb(255, 255, 255); margin: 0px; padding: 0px;">OAS 2.0</pre></small>
<pre class="base-url" style="box-sizing: border-box; font-family: monospace; font-size: 12px; color: rgb(59, 65, 81); margin: 0px; font-weight: 300 !important;">[ Base URL: petstore.swagger.io/v2 ]</pre>
[https://petstore.swagger.io/v2/swagger.json](https://petstore.swagger.io/v2/swagger.json)</hgroup>
This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io/) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.
[Terms of service](http://swagger.io/terms/)
[Contact the developer](mailto:apiteam@swagger.io)
[Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0.html)
[Find out more about Swagger](http://swagger.io/)
- 自定义统一处理API返回格式注解
/*
* Copyright [2025-present] [Liu Rongming]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wewetea.open.weadmin.common.aspect.api;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreRestFulAPI {
}
- 自定义注解实现:
/*
* Copyright [2025-present] [Liu Rongming]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wewetea.open.weadmin.common.aspect.api;
import com.alibaba.fastjson.JSON;
import com.wewetea.open.weadmin.model.dto.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
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;
@Slf4j
@RestControllerAdvice
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
log.debug("GlobalResponseAdvice supports: " +returnType.getDeclaringClass().getName());
// 如果已经是 Result 包装过的就跳过
// 如果标注有 @IgnoreResponseBody 注解的也跳过
// 如果是springdoc的也跳过,目的为了去兼容swagger3
return !(returnType.getParameterType().isAssignableFrom(Result.class)
|| returnType.hasMethodAnnotation(IgnoreRestFulAPI.class)
|| returnType.getDeclaringClass().getName().contains("springdoc")
);
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
log.debug("GlobalResponseAdvice beforeBodyWrite: " +returnType.getDeclaringClass().getName());
// String类型不能直接包装
// warning: RestController方法上返回值类型为String时,默认响应的Content-Type是text/plain,
// 需要手动指定为application/json 才能对结果进行包装成 json
if (returnType.getParameterType().isAssignableFrom(String.class)) {// 将数据包装在Result里后转换为json串进行返回
return JSON.toJSONString(Result.success(body));
} else if (returnType.getParameterType().isAssignableFrom(Void.TYPE)) { // 如果返回值是void类型,直接返回200状态信息
return Result.success();
} else { // 其他情况也都返回一下信息
return Result.success(body);
}
}
}
- 解决问题
/*
* Copyright [2025-present] [Liu Rongming]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wewetea.open.weadmin.common.aspect.api;
import com.alibaba.fastjson.JSON;
import com.wewetea.open.weadmin.model.dto.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
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;
@Slf4j
@RestControllerAdvice
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> {
@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
log.debug("GlobalResponseAdvice supports: " +returnType.getDeclaringClass().getName());
// 如果已经是 Result 包装过的就跳过
// 如果标注有 @IgnoreResponseBody 注解的也跳过
// 如果是springdoc的也跳过,目的为了去兼容swagger3
return !(returnType.getParameterType().isAssignableFrom(Result.class)
|| returnType.hasMethodAnnotation(IgnoreRestFulAPI.class)
|| returnType.getDeclaringClass().getName().contains("springdoc")
);
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
log.debug("GlobalResponseAdvice beforeBodyWrite: " +returnType.getDeclaringClass().getName());
// String类型不能直接包装
// warning: RestController方法上返回值类型为String时,默认响应的Content-Type是text/plain,
// 需要手动指定为application/json 才能对结果进行包装成 json
if (returnType.getParameterType().isAssignableFrom(String.class)) {// 将数据包装在Result里后转换为json串进行返回
return JSON.toJSONString(Result.success(body));
} else if (returnType.getParameterType().isAssignableFrom(Void.TYPE)) { // 如果返回值是void类型,直接返回200状态信息
return Result.success();
} else { // 其他情况也都返回一下信息
return Result.success(body);
}
}
}
处理很简单,就是把它跳过不处理:
- 其中关键的代码:
||returnType.getDeclaringClass().getName().contains("springdoc")
这样,就可以兼容处理了。