1. 概述
现代 Web 应用普遍采用前后端分离架构,后端通常以 REST API 形式对外提供服务。在这种模式下,API 的清晰、准确、可读性强的文档就显得尤为重要。
更关键的是:API 变了,文档必须同步更新。靠人工维护不仅效率低,还容易出错。因此,自动化文档生成工具成了刚需。
本文将带你使用 Springfox 实现的 Swagger 2 规范,为 Spring REST 服务生成 API 文档。
✅ 重要提示:
目前 Swagger 规范的最新版本是 OpenAPI 3.0,它由 Springdoc 项目支持得更好,推荐用于新项目(可参考 Spring REST OpenAPI 文档指南)。⚠️ Spring Boot 3 已不再支持 Springfox,本文内容适用于 Spring Boot 2.x 及以下版本。
2. 目标项目
本文不涉及 REST 服务的创建过程。如果你已有项目,可直接使用;如果没有,可参考以下资源快速搭建:
3. 添加 Maven 依赖
我们使用 Springfox 作为 Swagger 2 的实现。最新版本可在 Maven Central 查询。
在 pom.xml
中添加以下依赖:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>3.0.0</version>
</dependency>
3.1 Spring Boot 项目依赖
如果你使用的是 Spring Boot,只需引入一个 starter 即可:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
同时确保你的项目继承了 Spring Boot 的 parent,以获得版本管理:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.1.5</version>
</dependency>
4. 集成 Swagger 2 到项目
4.1 Java 配置
Swagger 的核心配置围绕 Docket
Bean 展开:
@Configuration
public class SpringFoxConfig {
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}
Docket
是 Swagger 的配置入口。select()
返回ApiSelectorBuilder
,用于控制哪些接口暴露给 Swagger。RequestHandlerSelectors.any()
表示扫描所有 Controller。PathSelectors.any()
表示匹配所有路径。
4.2 非 Spring Boot 项目的配置
在纯 Spring 项目中,需要显式启用 Swagger 2:
@Configuration
@EnableSwagger2
public class SpringFoxConfig {
}
此外,还需手动配置资源处理器,因为 Spring Boot 的自动配置不可用:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
4.3 验证集成是否成功
启动应用后,访问:
http://localhost:8080/v2/api-docs
你会看到一个庞大的 JSON 响应。虽然机器可读,但对人类不友好。接下来,我们用 Swagger UI 来可视化它。
5. Swagger UI
Swagger UI 是一个内置的 UI 工具,让开发者可以直观地浏览和测试 API。
5.1 启用 Springfox 的 Swagger UI
添加以下依赖:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>3.0.0</version>
</dependency>
访问:
http://localhost:8080/swagger-ui/
你应该能看到类似下面的界面:
5.2 探索 Swagger 文档
Swagger 会自动列出应用中所有的 Controller。点击任一 Controller,可查看其支持的 HTTP 方法(如 GET、POST 等)。
展开具体方法,可看到:
- 响应状态码
- 内容类型(Content-Type)
- 参数列表
- 在线试用功能(Try it out)
Swagger 的核心优势是与代码实时同步。例如,新增一个 Controller:
@RestController
public class CustomController {
@RequestMapping(value = "/custom", method = RequestMethod.POST)
public String custom() {
return "custom";
}
}
刷新 Swagger UI,你会发现 custom-controller
已出现在列表中,且只暴露了 POST 方法。
6. Spring Data REST 支持
Springfox 通过 springfox-data-rest
模块支持 Spring Data REST。
✅ 若使用 Spring Boot,只要引入 spring-boot-starter-data-rest
,Spring Boot 会自动完成配置。
创建一个 User
实体:
@Entity
public class User {
@Id
private Long id;
private String firstName;
private int age;
private String email;
// getters and setters
}
创建 UserRepository
以启用 CRUD 操作:
@Repository
public interface UserRepository extends CrudRepository<User, Long> {
}
在 SpringFoxConfig
中导入 Spring Data REST 配置:
@EnableSwagger2
@Import(SpringDataRestConfiguration.class)
public class SpringFoxConfig {
//...
}
⚠️ 注意:
@EnableSwagger2WebMvc
在 Springfox 3.x 中已废弃,请使用@EnableSwagger2
。
重启应用,Swagger UI 将自动生成 /users
的 CRUD 接口文档:
7. Bean Validation 支持
Springfox 可通过 springfox-bean-validators
模块解析 JSR-303 注解。
添加依赖:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-bean-validators</artifactId>
<version>2.9.2</version>
</dependency>
✅ Spring Boot 项目通常无需显式添加此依赖。
为 User
实体添加校验注解:
@Entity
public class User {
//...
@NotNull(message = "First Name cannot be null")
private String firstName;
@Min(value = 15, message = "Age should not be less than 15")
@Max(value = 65, message = "Age should not be greater than 65")
private int age;
}
在 SpringFoxConfig
中启用 Bean Validator 插件:
@EnableSwagger2
@Import(BeanValidatorPluginsConfiguration.class)
public class SpringFoxConfig {
//...
}
Swagger UI 将显示校验规则:
firstName
标记为必填(* required)age
显示最小值 15,最大值 65
8. 自定义插件
Springfox 提供 SPI 机制,允许通过插件扩展功能。常见插件接口包括:
ModelBuilderPlugin
:模型构建ModelPropertyBuilderPlugin
:属性构建ApiListingBuilderPlugin
:接口列表构建
示例:为 @Email 注解添加 pattern 和 example
创建 EmailAnnotationPlugin
:
@Component
@Order(Validators.BEAN_VALIDATOR_PLUGIN_ORDER)
public class EmailAnnotationPlugin implements ModelPropertyBuilderPlugin {
@Override
public boolean supports(DocumentationType delimiter) {
return true;
}
@Override
public void apply(ModelPropertyContext context) {
Optional<Email> email = annotationFromBean(context, Email.class);
if (email.isPresent()) {
context.getSpecificationBuilder().facetBuilder(StringElementFacetBuilder.class)
.pattern(email.get().regexp());
context.getSpecificationBuilder().example("user@example.com");
}
}
}
为 User
的 email
字段添加 @Email
注解:
@Entity
public class User {
//...
@Email(regexp=".*@.*\\..*", message = "Email should be valid")
private String email;
}
在 SpringFoxConfig
中注册插件 Bean:
@Import({BeanValidatorPluginsConfiguration.class})
public class SpringFoxConfig {
//...
@Bean
public EmailAnnotationPlugin emailPlugin() {
return new EmailAnnotationPlugin();
}
}
效果如下:
pattern
显示正则表达式example
显示示例邮箱
9. 高级配置
9.1 过滤 API
并非所有接口都需要暴露文档。可通过 apis()
和 paths()
精确控制:
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.controller"))
.paths(PathSelectors.ant("/foos/*"))
.build();
}
basePackage
:仅扫描指定包下的 Controllerant("/foos/*")
:仅包含/foos
开头的路径
9.2 自定义 API 信息
使用 apiInfo()
方法替换默认的文档元信息:
@Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.example.controller"))
.paths(PathSelectors.ant("/foos/*"))
.build()
.apiInfo(apiInfo());
}
private ApiInfo apiInfo() {
return new ApiInfo(
"My REST API",
"Some custom description of API.",
"API TOS",
"Terms of service",
new Contact("John Doe", "www.example.com", "john.doe@example.com"),
"License of API", "https://example.com/license", Collections.emptyList());
}
9.3 全局覆盖响应消息
通过 globalResponses()
统一修改 HTTP 方法的默认响应描述:
.useDefaultResponseMessages(false)
.globalResponses(HttpMethod.GET, newArrayList(
new ResponseBuilder().code("500")
.description("服务器内部错误").build(),
new ResponseBuilder().code("403")
.description("禁止访问").build()
));
效果如下:
10. Swagger UI 接入 OAuth2 安全接口
当 API 受 OAuth2 保护时,Swagger UI 需要能获取 Token 才能调用。以下是基于 Authorization Code 模式的配置。
10.1 安全配置 Bean
@Bean
public SecurityConfiguration security() {
return SecurityConfigurationBuilder.builder()
.clientId("my-client-id")
.clientSecret("my-client-secret")
.scopeSeparator(" ")
.useBasicAuthenticationWithAccessCodeGrant(true)
.build();
}
10.2 SecurityScheme
定义 OAuth2 安全方案:
private SecurityScheme securityScheme() {
GrantType grantType = new AuthorizationCodeGrantBuilder()
.tokenEndpoint(new TokenEndpoint("http://auth-server/token", "oauthtoken"))
.tokenRequestEndpoint(
new TokenRequestEndpoint("http://auth-server/authorize", "my-client-id", "my-client-secret"))
.build();
SecurityScheme oauth = new OAuthBuilder().name("spring_oauth")
.grantTypes(Arrays.asList(grantType))
.scopes(Arrays.asList(scopes()))
.build();
return oauth;
}
private AuthorizationScope[] scopes() {
AuthorizationScope[] scopes = {
new AuthorizationScope("read", "for read operations"),
new AuthorizationScope("write", "for write operations"),
new AuthorizationScope("foo", "Access foo API") };
return scopes;
}
10.3 SecurityContext
定义安全上下文,指定哪些路径需要认证:
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(
Arrays.asList(new SecurityReference("spring_oauth", scopes())))
.forPaths(PathSelectors.regex("/foos.*"))
.build();
}
✅
spring_oauth
必须与SecurityScheme
中的 name 一致。
10.4 测试
访问 Swagger UI:
http://localhost:8080/swagger-ui/
你会看到 Authorize 按钮:
点击后可输入客户端信息并选择权限:
认证后,受保护的接口会显示锁图标:
⚠️ 重要提醒:生产环境务必谨慎暴露 Swagger UI,避免敏感信息泄露。
11. 总结
本文完整演示了如何在 Spring REST 项目中集成 Swagger 2,涵盖:
- 基础配置与 UI 集成
- Spring Data REST 和 Bean Validation 支持
- 自定义插件开发
- 高级过滤与信息定制
- OAuth2 安全接口接入
虽然 Springfox 在新项目中已被 Springdoc 取代,但理解其原理对维护旧项目仍有价值。对于新项目,建议直接使用 Springdoc + OpenAPI 3。