如何让Springfox生成Swagger文档时序列化JAXB注解模型?
针对你遇到的两个核心问题(JAXB模型无法序列化到Swagger文档、Swagger注解导致类找不到),我整理了几个实际项目里验证过的可行方案:
一、让Springfox支持JAXB注解的只读模型
Springfox默认只解析Jackson、Spring Validation这类注解,对JAXB注解(比如@XmlRootElement、@XmlElement)没有原生支持,而你的模型是Maven依赖里的只读文件没法修改,所以得通过自定义Springfox扩展来处理:
- 编写自定义
ModelBuilderPlugin实现类
这个插件会扫描JAXB注解,把它们转换成Swagger能识别的模型元数据:
import org.springframework.plugin.core.Plugin; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.schema.ModelBuilderPlugin; import springfox.documentation.spi.schema.contexts.ModelContext; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import java.lang.reflect.Field; public class JaxbModelBuilderPlugin implements ModelBuilderPlugin { @Override public void apply(ModelContext context) { Class<?> modelClass = context.getType().getErasedType(); // 处理@XmlRootElement作为ApiModel的名称 XmlRootElement rootElement = modelClass.getAnnotation(XmlRootElement.class); if (rootElement != null) { context.getBuilder().name(rootElement.name().isEmpty() ? modelClass.getSimpleName() : rootElement.name()); } // 处理@XmlElement作为ApiModelProperty for (Field field : modelClass.getDeclaredFields()) { XmlElement xmlElement = field.getAnnotation(XmlElement.class); if (xmlElement != null) { context.getBuilder() .property(field.getName()) .description(xmlElement.name()) .required(xmlElement.required()); } } } @Override public boolean supports(DocumentationType delimiter) { return DocumentationType.SWAGGER_2.equals(delimiter); } }
- 把这个插件注册为Spring Bean
在你的Swagger配置类里添加:
@Bean public JaxbModelBuilderPlugin jaxbModelBuilderPlugin() { return new JaxbModelBuilderPlugin(); }
这样Springfox就会在构建模型时自动解析JAXB注解了。
二、解决Swagger注解的类找不到异常
你提到添加Swagger注解后出现“无法找到Api类”的异常,大概率是依赖版本不兼容或者缺少必要的依赖包:
如果你用的是Springfox 2.x版本:
确保你的Maven依赖里包含swagger-annotations(版本要和Springfox匹配,比如Springfox 2.9.2对应swagger-annotations 1.5.21):<dependency> <groupId>io.swagger</groupId> <artifactId>swagger-annotations</artifactId> <version>1.5.21</version> </dependency>控制器上的注解用
io.swagger.annotations.Api、io.swagger.annotations.ApiOperation这些。如果你用的是Springfox 3.x版本:
虽然3.x兼容旧的Swagger 2注解,但更推荐用Springfox自带的注解(springfox.documentation.annotations.Api),或者直接引入完整的starter依赖:<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-boot-starter</artifactId> <version>3.0.0</version> </dependency>这个starter已经包含了所有必要的依赖,不会出现类找不到的问题。
三、备选方案:手动定义Swagger模型(适合快速解决)
如果上面的扩展方案太复杂,你可以跳过自动解析,手动在控制器里定义模型结构:
比如在返回JAXB模型的接口上,用@ApiOperation的response参数指定手动定义的DTO类,再用@ApiModel和@ApiModelProperty描述字段:
@ApiModel(value = "UserModel", description = "用户模型") public class UserModelDto { @ApiModelProperty(value = "用户ID", required = true) private String userId; @ApiModelProperty(value = "用户名") private String username; // 字段和JAXB模型一一对应即可 } @RestController @Api(tags = "用户接口") public class UserController { @ApiOperation(value = "获取用户信息", response = UserModelDto.class) @GetMapping("/user") public UserJaxbModel getUser() { // 返回实际的JAXB模型 return new UserJaxbModel(); } }
这种方式不需要修改原JAXB模型,也能让Swagger显示正确的文档结构。
内容的提问来源于stack exchange,提问作者nsid44

