添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Swagger2的/v2/api-docs接口是如何对第三方项目暴露的呢?也就是说jar包中如何暴露接口给第三方应用?

答案是:HandlerMapping

swagger2实现了自己的HandlerMapping,在实现类PropertySourcedRequestMappingHandlerMapping中,把/v2/api-docs接口保存到了handlerMethods
集合。然后提供了访问/v2/api-docs接口的方法lookupHandlerMethod(String urlPath, HttpServletRequest request),这样请求过来的时候,就可以
根据接口路径找到对应的控制器Swagger2Ctroller.class

OK,接下来,我们细看。

第一步:实现HandlerMapper接口

Swagger2的实现类是PropertySourcedRequestMappingHandlerMapping,其实就是HandlerMapping的实现。

PropertySourcedRequestMappingHandlerMapping的核心是2个方法:initHandlerMethods和lookupHandlerMethod

initHandlerMethods:把接口路径和HandlerMethod存放到spring boot webmvc的集合。

lookupHandlerMethod:提供根据接口路径查找处理类controller的功能。

package springfox.documentation.spring.web;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import org.springframework.web.util.UriTemplate;
public class PropertySourcedRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
    private final Map<String, HandlerMethod> handlerMethods = new LinkedHashMap();
    private final Environment environment;
    private final Object handler;
    public PropertySourcedRequestMappingHandlerMapping(Environment environment, Object handler) {
        this.environment = environment;
        this.handler = handler;
    protected void initHandlerMethods() {
        this.logger.debug("initialising the handler methods");
        this.setOrder(-2147482648);
        Class<?> clazz = this.handler.getClass();
        if (this.isHandler(clazz)) {
            Method[] var2 = clazz.getMethods();
            int var3 = var2.length;
            for(int var4 = 0; var4 < var3; ++var4) {
                Method method = var2[var4];
                PropertySourcedMapping mapper = (PropertySourcedMapping)AnnotationUtils.getAnnotation(method, PropertySourcedMapping.class);
                if (mapper != null) {
                    RequestMappingInfo mapping = this.getMappingForMethod(method, clazz);
                    HandlerMethod handlerMethod = this.createHandlerMethod(this.handler, method);
                    String mappingPath = this.mappingPath(mapper);
                    if (mappingPath != null) {
                        this.logger.info(String.format("Mapped URL path [%s] onto method [%s]", mappingPath, handlerMethod.toString()));
                        this.handlerMethods.put(mappingPath, handlerMethod);
                    } else {
                        Iterator var10 = mapping.getPatternsCondition().getPatterns().iterator();
                        while(var10.hasNext()) {
                            String path = (String)var10.next();
                            this.logger.info(String.format("Mapped URL path [%s] onto method [%s]", path, handlerMethod.toString()));
                            this.handlerMethods.put(path, handlerMethod);
    private String mappingPath(PropertySourcedMapping mapper) {
        final String key = mapper.propertyKey();
        final String target = mapper.value();
        return (String)Optional.fromNullable(this.environment.getProperty(key)).transform(new Function<String, String>() {
            public String apply(String input) {
                return target.replace(String.format("${%s}", key), input);
        }).orNull();
    protected boolean isHandler(Class<?> beanType) {
        return AnnotationUtils.findAnnotation(beanType, Controller.class) != null || AnnotationUtils.findAnnotation(beanType, RequestMapping.class) != null;
    protected HandlerMethod lookupHandlerMethod(String urlPath, HttpServletRequest request) {
        this.logger.debug("looking up handler for path: " + urlPath);
        HandlerMethod handlerMethod = (HandlerMethod)this.handlerMethods.get(urlPath);
        if (handlerMethod != null) {
            return handlerMethod;
        } else {
            Iterator var4 = this.handlerMethods.keySet().iterator();
            String path;
            UriTemplate template;
                if (!var4.hasNext()) {
                    return null;
                path = (String)var4.next();
                template = new UriTemplate(path);
            } while(!template.matches(urlPath));
            request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, template.match(urlPath));
            return (HandlerMethod)this.handlerMethods.get(path);

第二步:提供配置类Swagger2DocumentationConfiguration

装配PropertySourcedRequestMappingHandlerMapping到IOC容器。这里很好理解,因为是在jar包中对外部第三方应用提供服务,需要先把我们的

service注入到本地项目的Spring IOC容器中。

package springfox.documentation.swagger2.configuration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.Environment;
import org.springframework.web.servlet.HandlerMapping;
import springfox.documentation.spring.web.DocumentationCache;
import springfox.documentation.spring.web.PropertySourcedRequestMappingHandlerMapping;
import springfox.documentation.spring.web.SpringfoxWebMvcConfiguration;
import springfox.documentation.spring.web.json.JacksonModuleRegistrar;
import springfox.documentation.spring.web.json.JsonSerializer;
import springfox.documentation.swagger.configuration.SwaggerCommonConfiguration;
import springfox.documentation.swagger2.mappers.ServiceModelToSwagger2Mapper;
import springfox.documentation.swagger2.web.Swagger2Controller;
@Configuration
@Import({SpringfoxWebMvcConfiguration.class, SwaggerCommonConfiguration.class})
@ComponentScan(
    basePackages = {"springfox.documentation.swagger2.mappers"}
@ConditionalOnWebApplication
public class Swagger2DocumentationConfiguration {
    public Swagger2DocumentationConfiguration() {
    @Bean
    public JacksonModuleRegistrar swagger2Module() {
        return new Swagger2JacksonModule();
    @Bean
    public HandlerMapping swagger2ControllerMapping(Environment environment, DocumentationCache documentationCache, ServiceModelToSwagger2Mapper mapper, JsonSerializer jsonSerializer) {
        return new PropertySourcedRequestMappingHandlerMapping(environment, new Swagger2Controller(environment, documentationCache, mapper, jsonSerializer));

接下来,就是把Swagger2DocumentationConfiguration配置类作为starter,提供给第三方应用了。这里不再赘述,如果我们开发自己的jar包,没有maven远程仓库支持的话,

也可以通过spring.factories的方式,把配置类提供给本地应用使用。

好了,看完这篇文章,我们就可以轻松实现在jar包中暴露接口的功能了。后续会写一篇我自己的一个demo,是我在CR949开源项目中的一个实现。目前这个项目已经贡献给了

中国的开源社区,gitee,大家直接搜索CR949,就可以找到我的开源项目。欢迎大家关注交流,一起技术进步。

欢迎大家关注后续文章。

Swagger2的/v2/api-docs接口是如何对第三方项目暴露的呢?也就是说jar包中如何暴露接口给第三方应用?答案是:HandlerMappingswagger2实现了自己的HandlerMapping,在实现类PropertySourcedRequestMappingHandlerMapping中,把/v2/api-docs接口保存到了handlerMethods集合。然后提供了访问/v2/api-docs接口的方法lookupHandlerMethod(String urlPath, Bokun API的文档,采用Open API格式(以前是大张旗鼓)。 安装swagger命令行界面 swagger-cli可以验证yaml文件swagger validate [file] 。 并将它们捆绑为自包含的json文件,以与Swagger代码生成器结合使用, swagger bundle [file] 。 npm install -g swagger-cli 开发人员工作流程 在API中进行更改后,编辑bokun.yaml以反映更改,然后通过运行./generate.sh {prod | test}分别将其转换为json来生成生产和测试swagger文件。 在将更改提交到swagger-prod.json和swagger-test.json之前,将更改还原到主机位置 import io.swagger.models.Swagger; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springfr. 与DOCKER图像一起运行 $ docker build -f Dockerfile -t docker-image-name。 $ docker运行它-d -p主机端口:DOCKER端口docker-image-name $ docker build -f Dockerfile -t api-doc。 $ docker run -p 8080:8080 api-doc $ docker ps -a $ docker stop容器ID 列出所有图像 $泊坞窗图片 列出所有过程 $ docker ps -a 删除所有的容器 阅读API文档,以了解您可以对应用程序执行的操作。 所有URL均以https://api.tiendanube.com/v1/{store_id}或https://api.nuvemshop.com.br/v1/{store_id}开头。 仅SSL 。 该路径以商店ID和API版本为前缀。 如果我们以向后不兼容的方式更改API,我们将破坏版本标记并保持对旧URL的稳定支持。 因此,如果您想通过API访问ID为123456的商店,则URL为ht
之前在SpringBoot项目中一直使用的是SpringFox提供的Swagger库,上了下官网发现已经有接近两年没出新版本了!前几天升级了SpringBoot 2.6.x 版本,发现这个库的兼容性也越来越不好了,有的常用注解属性被废弃了居然都没提供替代!无意中发现了另一款SwaggerSpringDoc,试用了一下非常不错,推荐给大家! SpringDoc简介 SpringDoc是一款可以结合SpringBoot使用的API文档生成工具,基于OpenAPI 3,目前在Github上已有1.7K+.
public Docket loginApi() { return new Docket(DocumentationType.SWAGGER_2) .groupName("登录管理") .apiInfo(apiInfo() 遍历所有API接口,自动填充参数 尝试 GET / POST 所有接口,返回 Response Code / Content-Type / Content-Length ,用于分析接口是否可以未授权访问利用 分析接口是否存在敏感参数,例如url参数,容易引入外网的SSRF漏洞 检测 API认证绕过漏洞 在本地监听一个Web Server,打开Swagger UI界面,供分析接口使用
您可以通过在Linux系统中配置Nginx或Apache服务器来禁止访问swagger-ui.html和/v2/api-docs。具体方法如下: 1. 配置Nginx或Apache服务器,将swagger-ui.html和/v2/api-docs的访问权限设置为拒绝。 2. 在Nginx或Apache服务器的配置文件中添加以下代码: location /swagger-ui.html { deny all; location /v2/api-docs { deny all; 3. 保存并重启Nginx或Apache服务器,使配置生效。 这样就可以禁止访问swagger-ui.html和/v2/api-docs了。