Spring Boot应用暴露Spring REST Docs生成的HTML文档端点的最佳方案
其实这个需求在Spring Boot项目里挺常见的,我整理了几个靠谱的方案,你可以根据自己的场景选:
方案一:利用Spring Boot静态资源映射(最简单)
Spring Boot默认会自动映射classpath:/static/、classpath:/public/等目录下的静态资源,所以我们只需要把Asciidoctor生成的HTML文档放到这些目录里,就能直接通过URL访问了。
步骤1:配置构建工具(Maven/Gradle),把生成的HTML复制到静态资源目录
以Maven为例,在pom.xml里配置asciidoctor-maven-plugin,让它在构建时把生成的HTML复制到target/classes/static/docs(避免污染源码目录):
<plugin> <groupId>org.asciidoctor</groupId> <artifactId>asciidoctor-maven-plugin</artifactId> <version>2.2.6</version> <!-- 可替换为最新稳定版 --> <executions> <execution> <id>generate-docs</id> <phase>prepare-package</phase> <!-- 打包前执行文档生成 --> <goals> <goal>process-asciidoc</goal> </goals> <configuration> <sourceDirectory>src/main/asciidoc</sourceDirectory> <outputDirectory>target/generated-docs</outputDirectory> <backend>html</backend> </configuration> </execution> </executions> </plugin> <!-- 复制生成的HTML及关联资源到静态目录 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <version>3.3.1</version> <executions> <execution> <id>copy-docs</id> <phase>prepare-package</phase> <goals> <goal>copy-resources</goal> </goals> <configuration> <outputDirectory>${project.build.outputDirectory}/static/docs</outputDirectory> <resources> <resource> <directory>target/generated-docs</directory> <includes> <include>**/*.html</include> <include>**/*.css</include> <!-- 样式文件不能漏 --> <include>**/*.js</include> <include>**/*.png</include> <!-- 如果有图片也要复制 --> </includes> </resource> </resources> </configuration> </execution> </executions> </plugin>
步骤2:直接访问文档
启动应用后,你就能通过http://localhost:8080/docs/index.html访问生成的HTML文档了,完全不需要额外写代码。
方案二:自定义控制器(更灵活,适合权限控制或自定义逻辑场景)
如果需要对文档访问加一些特殊逻辑(比如权限校验、动态路由),可以写一个简单的Spring MVC控制器来处理:
步骤1:确保HTML被打包到Jar的classpath下
用上面的Maven配置,把HTML复制到target/classes/docs目录(或者其他自定义classpath目录,比如classpath:/META-INF/docs/)。
步骤2:编写控制器
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class DocsController { // 访问文档首页,直接返回index.html @GetMapping(value = "/docs", produces = MediaType.TEXT_HTML_VALUE) public Resource getDocsIndex() { return new ClassPathResource("docs/index.html"); } // 处理文档里的其他关联资源(样式、图片、子页面等) @GetMapping("/docs/{resource:.+}") public Resource getDocsResource(@PathVariable String resource) { return new ClassPathResource("docs/" + resource); } }
这样访问http://localhost:8080/docs就会直接返回首页,相关资源也能正常加载。
方案三:配置WebMvcConfigurer扩展静态资源路径
如果不想把文档放到默认的静态目录,也可以自定义静态资源映射路径:
import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 把classpath:/generated-docs/下的资源映射到/docs/**路径 registry.addResourceHandler("/docs/**") .addResourceLocations("classpath:/generated-docs/"); } }
只要确保Asciidoctor生成的HTML被打包到classpath:/generated-docs/目录下,就能通过http://localhost:8080/docs/index.html访问了。
额外提示:权限控制
如果你的应用用了Spring Security,记得要允许访问文档端点,比如在Security配置里加:
@Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/docs/**").permitAll() // 允许所有用户访问文档 .anyRequest().authenticated(); }
内容的提问来源于stack exchange,提问作者Игорь Кравченко

