中http诉求发生access,swagger原精通析与行使进程中

在api项目中 本地品种不可能访谈服务器api

在Android代码中,大家不时会动用比大家在AndroidManifest中设置的android:minSdkVersion版本越来越高的形式,那时编写翻译器会提示警报,

浅谈springfox-swagger原理深入分析与行使进度中相遇的坑,

swagger简介

swagger确实是个好东西,可以跟据业务代码自动生成相关的api接口文书档案,尤其用于restful风格中的项目,开采职员大约能够绝不特别去维护rest api,那个框架能够自行为你的作业代码生成restfut风格的api,而且还提供对应的测量试验分界面,自动展现json格式的响应。大大方便了后台开辟职员与后面三个的维系与联调成本。

springfox-swagger简介

签于swagger的强有力作用,java开源界大拿spring框架火速跟上,它丰富利用自已的优势,把swagger集成到谐和的等级次序里,整了四个spring-swagger,后来便衍形成springfox。springfox本身只是利用自个儿的aop的特点,通过plug的诀窍把swagger集成了进来,它自个儿对事情api的浮动,如故凭仗swagger来完成。

有关那么些框架的文书档案,英特网的质地少之又少,超越二分之一是入门级的大约利用。自个儿在合龙那几个框架到自身项目标长河中,碰到了广大埔滘,为了解决这么些坑,小编不能不扒开它的源码来看个究竟。此文,正是记述自己在运用springfox进度中对springfox的生龙活虎部分精通以致要求留意的位置。

springfox大约原理

springfox的大意原理正是,在类型运维的过种中,spring上下文在起首化的进程,框架自动跟据配置加载一些swagger相关的bean到当前的上下文中,并自行扫描系统中也许供给生成api文书档案那些类,并转移对应的音讯缓存起来。假若项目MVC调整层用的是springMvc那么会自行扫描全体Controller类,跟据这么些Controller类中的方法生成对应的api文书档案。

因自家的类型便是SpringMvc,所以此文就以Srping mvc集成springfox为例来钻探springfox的行使与原理。

SpringMvc集成springfox的步骤

率先,项目须要步入以下多个依据:

<!-- sring mvc依赖 -->

   <dependency>

     <groupId>org.springframework</groupId>

     <artifactId>spring-webmvc</artifactId>

     <version>4.2.8.RELEASE</version>

   </dependency>

<!-- swagger2核心依赖 -->

   <dependency>

     <groupId>io.springfox</groupId>

     <artifactId>springfox-swagger2</artifactId>

     <version>2.6.1</version>

   </dependency>

   <!-- swagger-ui为项目提供api展示及测试的界面 -->

   <dependency>

     <groupId>io.springfox</groupId>

     <artifactId>springfox-swagger-ui</artifactId>

     <version>2.6.1</version>

   </dependency>

地点四个依据是项目集成springmvc及springfox最基本的依据,其它的凭仗这里大约。个中第二个是springmvc的中央凭借,第三个是swagger依赖,第八个是分界面相关的依赖,那么些不是必得的,要是您不想用springfox自带的api分界面包车型客车话,也能够不要那些,而除此以外自身写风流浪漫套相符本身项目标分界面。参加那多少个依赖后,系统后会自动步向一些跟springfox及swagger相关jar包,作者轻松看了瞬间,首要有以下那样几个:

springfox-swagger2-2.6.1.jar

swagger-annotations-1.5.10.jar

swagger-models-1.5.10.jar

springfox-spi-2.6.1.jar

springfox-core-2.6.1.jar

springfox-schema-2.6.1.jar

springfox-swagger-common-2.6.1.jar

springfox-spring-web-2.6.1.jar

guava-17.0.jar

spring-plugin-core-1.2.0.RELEASE.jar

spring-plug-metadata-1.2.0.RELEASE.jar

spring-swagger-ui-2.6.1.jar

jackson-databind-2.2.3.jar

jackson-annotations-2.2.3.jar

地方是本人经过目测感到springfox或许须求的jar,恐怕未有完全例出springfox所需的有着jar。从地点jar可以看见pringfox除了依赖swagger之外,它还索要guava、spring-plug、jackson等注重包(注意jackson是用以生成json必需的jar包,若是项目里本人未有参预那个依据,为了集成swagger的话一定要附加再步入这些依靠卡塔尔。

springfox的大致利用

生龙活虎旦只用springfox的私下认可的布置来讲,与springmvc集成起来特别简单,只要写二个相似于以下代码的类放到你的花色里就能够了,代码如下:

@Configuration

@EnableWebMvc

@EnableSwagger2

publicclass ApiConfig {}

小心到,上边是四个空的java类文件,类名能够轻易钦定,但必须投入上述类中标注的@Configuration、@EnableWebMvc、@EnableSwagger2三个注明,那样就变成了springmvc与springfox的着力集成,有了多个评释,项目运维后就能够直接用接近于以下的地点来查看api列表了:

那确实是叁个很奇妙的机能,轻巧的四个注解,系统就自动呈现出档案的次序里具备Controller类的富有api了。今后,大家就以此布局类入手,简单解析它的规律。那个类中绝非其余代码,很分明,四个申明起了主要的职能。在那之中@Configuration表明是spring框架中自作者就有个别,它是多个被@Component元声明标志的申明,所以有了那么些证明后,spring会自动把这些类实例化成二个bean注册到spring上下文中。第3个表明@EnableWebMvc故名思义,就是启用srpingmvc了,在Eclipse中式点心到那些评释里面大致看一下,它就是透过元注明@Import(DelegatingWebMvcConfiguration.class)往spring context中塞入了一个DelegatingWebMvcConfiguration类型的bean。笔者想,那个类的指标应该正是为swagger提供了部分springmvc方面包车型地铁布置吧。第三个申明:@EnableSwagger2,看名字应该能够想到,是用来集成swagger 2的,他因此元注解:@Import({Swagger2DocumentationConfiguration.class}),又引进了贰个Swagger2DocumentationConfiguration类型的配置bean,而以此便是Swagger的基本配置了。它当中的代码如下:

@Configuration
@Import({ SpringfoxWebMvcConfiguration.class, SwaggerCommonConfiguration.class })
@ComponentScan(basePackages = {
 "springfox.documentation.swagger2.readers.parameter",
  "springfox.documentation.swagger2.web",
  "springfox.documentation.swagger2.mappers"
})

publicclassSwagger2DocumentationConfiguration {
 @Bean
 public JacksonModuleRegistrar swagger2Module() {
  returnnewSwagger2JacksonModule();
 }
}

其风流洒脱类尾部通过有些疏解,再引进SpringfoxWebMvcConfiguration类和SwaggerCommonConfiguration类,并由此ComponentScan注明,自动扫描springfox .swagger2相关的的bean到spring context中。这里,作者最感兴趣的是SpringfoxWebMvcConfiguration这些类,这一个类小编猜应该就是springfox集成mvc相比基本的布署了,点进去,见到以下代码:

@Configuration
@Import({ModelsConfiguration.class })
@ComponentScan(basePackages = {
  "springfox.documentation.spring.web.scanners",
"springfox.documentation.spring.web.readers.operation","springfox.documentation.spring.web.readers.parameter","springfox.documentation.spring.web.plugins","springfox.documentation.spring.web.paths"
})

@EnablePluginRegistries({ DocumentationPlugin.class,
  ApiListingBuilderPlugin.class,
  OperationBuilderPlugin.class,
  ParameterBuilderPlugin.class,
  ExpandedParameterBuilderPlugin.class,
  ResourceGroupingStrategy.class,
  OperationModelsProviderPlugin.class,
  DefaultsProviderPlugin.class,
  PathDecorator.class
})
publicclassSpringfoxWebMvcConfiguration {}

那一个类中上面包车型大巴代码,无非正是经过@Bean注明再踏入一些新的Bean,作者对它的志趣不是十分大,小编最感兴趣的是头部通过@EnablePluginRegistries参与的那一个东西。springfox是借助spring-plug的体制结合swagger的,spring-plug具体是怎么贯彻的,笔者有时还不曾时间去探究spring-plug的准则。但在下文种提到自身写一个plug插件来扩充swagger的职能。上边通过@EnablePluginRegistries参预的plug中,还并未有的时候间去看它全体的代码,近日本身看过的代码首要有ApiListingBuilderPlugin.class, OperationBuilderPlugin.class,ParameterBuilderPlugin.class, ExpandedParameterBuilderPlugin.class,

首先个ApiListingBuilderPlugin,它有多少个落到实处类,分别是ApiListingReader和SwaggerApiListingReader。当中ApiListingReader会自动跟据Controller类型生成api列表,而SwaggerApiListingReader会跟据有@Api表明标志的类生成api列表。OperationBuilderPlugin插件就是用来生成现实api文档的,那些项指标插件,有成都百货上千居多完成类,他们各自分工,各做各的事务,具体笔者向来不细心去看,只关切了内部一个落到实处类:OperationParameter里德r,那个类是用以读取api参数的Plugin。它依靠于ModelAttributeParameterExpander工具类,能够将Controller中接口方法参数中国和北美洲差不离类型的下令对像自动深入分析它当中的质量得出包括全数属性的参数列表(这里存在一个大概会并发非常递归的坑,下文有介绍卡塔尔国。而ExpandedParameterBuilderPlugin插件,主要是用以扩大接口参数的黄金年代对效用,比如判定那几个参数的数据类型以至是还是不是为那个接口的总得参数等等。总体上说,整个springfox-swagger内部其实是由那意气风发雨后春笋的plug转运起来的。他们在系统运营时,就被调起来,有个别用来围观出接口列表,某些用来读取接口参数等等。他们合营的目地正是把系统中享有api接口都围观出来,并缓存起来供客户查看。那么,那生机勃勃多级表plug到底是怎么着被调起来的,它们的进行入口倒底在哪?

   我们把注意点放到上文SpringfoxWebMvcConfiguration那些类代码头部的ComponentScan申明内容上来,那意气风发段注解中围观了一个叫springfox.documentation.spring.web.plugins的package,那个package在springfox-spring-web-2.6.1.jar中得以找到。这一个package下,大家发掘存七个极度宗旨的类,那就是DocumentationPluginsManager和DocumentationPluginsBootstrapper。对于第一个DocumentationPluginsManager,它是三个尚无兑现其他接口的bean,但它里面有不菲PluginRegistry类型的品质,并且都以通过@Autowired注明把属性值注入进来的。接合它的类名来看,非常轻便想到,这一个就是治本所有plug的叁个微处理器了。很好驾驭,因为ComponentScan注明的配置,全数的plug实例都会被spring实例化成三个bean,然后被注入到这么些DocumentationPluginsManager实例中被联合保管起来。在此个package中的另三个要害的类DocumentationPluginsBootstrapper,看名字就足以猜到,他恐怕就是plug的开发银行类了。点走入看具体时就足以窥见,他果然是三个被@Component标记了的组件,而且它的构造方法中注入了正要描述的DocumentationPluginsManager实例,而且最器重的,它还达成了斯马特Lifecycle接口。对spring bean生命周期有所通晓的人的都知道,这一个组件在被实例化为二个bean归入srping context中被拘押起来的时候,会自动调用它的start()方法。点到start()中看代码时就能够意识,它有大器晚成行代码scanDocumentation(buildContext(each));正是用来扫描api文书档案的。进一步追踪那些点子的代码,就足以窥见,这几个主意最终会通过它的DocumentationPluginsManager属性把拥有plug调起一同扫描整个系列并生成api文书档案。扫描的结果,缓存在DocumentationCache那个类的一个map属性中。

   以上正是,srpingMvc整合springfox的光景原理。它至关主如若通过EnableSwagger2评释,向srping context注入了黄金时代密密层层bean,并在系统运行的时候自动扫描系统的Controller类,生成对应的api新闻并缓存起来。此外,它还注入了意气风发部分被@Controller证明标记的Controller类,作为ui模块访谈api列表的入口。譬喻springfox-swagger2-2.6.1.jar包中的Swagger2Controller类。这么些Controller正是ui模块中用来访谈api列表的分界面地址。在拜候

刺探了springfox的法规,下边来会见springfox使用进度中,小编遇上的什么样坑。

springfox第意气风发黄石码头:配置类生成的bean必需与spring mvc共用同二个上下文。

前文描述了,在springmvc项目中,集成springfox是只要在档期的顺序写贰个之类的没有任何业务代码的粗略布置类就足以了。

@Configuration
@EnableWebMvc
@EnableSwagger2
publicclass ApiConfig {
}

因为@Configuration注明的成效,spring会自动把它实例化成贰个bean注入到上下文。但切记要小心的多少个坑就是:那一个bean所在的上下文必得跟spring mvc为同贰个上下文。怎么解理呢?因为在实际的spring mvc项目中,平常有七个上下文,一个是跟上下文,另三个是spring mvc(它是跟上下文的子上下文卡塔 尔(英语:State of Qatar)。此中跟上下文是正是web.xml文件中跟spring相关的极其org.springframework.web.context.request.RequestContextListener监听器,加载起来的上下文,平日大家会写贰个叫spring-contet.xml的布署文件,那此中的bean最后会先河化到跟上下文中,它至关心爱戴要回顾系统之中的service,dao等bean,也包蕴数据源、事物等等。而另叁个上下文是就是spring mvc了,它经过web.xml中跟spring mvc相关的老大org.springframework.web.servlet.DispatcherServlet加载起来,他平日常有三个安顿文件叫spring-mvc.xml。大家在写ApiConfig那几个类时,如果断定用@Configuration注脚来加载,那么就非得确认保障那些类所在的路线适逢其时在springmvc的component-scan的布署的base-package范围内。因为在ApiConfig在被spring加载时,会注入一列种类的bean,而这一个bean中,为了能自动扫描出全数Controller类,有些bean供给依附于SpringMvc中的一些bean,假使项目把Srpingmvc的上下文与跟上下文分开来,作为跟上下文的子上下文的话。如果相当大心让那一个ApiConfig类型的bean被跟上文加载到,因为root context中平素不spring mvc的context中的那个配置类时就能够报错。

事实上,小编并不赞同通过@Configuration注明来布局Swagger,因为自个儿感觉,Swagger的api功能对于生产类型以来是不在意的。大家Swagger往往是用来测量试验情形供项近期端团队开销或供别的系统作接口集成使上。系统上线后,很或然在生产系统上隐讳这个api列表。 但假若安顿是因而@Configuration注明写死在java代码里的话,那么上线的时候想去掉那个效果的时候,那就狼狈了,一定要修正java代码重新编写翻译。基于此,我推荐的一个主意,通过spring最传统的xml文件配置情势。具体做法正是去掉@Configuration注明,然后它写多个临近于<bean class="com.jad.web.mvc.swagger.conf.ApiConfig"/>那样的bean配置到spring的xml配置文件中。在root context与mvc的context分开的门类中,直接配备到spring-mvc.xml中,那样就确认保证了它跟springmvc 的context一定处于同二个context中。

springfox第二上下邨:Controller类的参数,注意制止现身Infiniti递归的情景。

Spring mvc有举世无敌的参数绑定机制,可以自动把央求参数绑定为二个自定义的命令对像。所以,超级多开荒职员在写Controller时,为了偷懒,直接把多个实体对像作为Controller方法的二个参数。比方上边这么些示例代码:

@RequestMapping(value = "update")
public String update(MenuVomenuVo, Model model){
}

那是大多数程序员喜欢在Controller中写的改造某些实体的代码。在跟swagger集成的时候,这里有三个深井。假使MenuVo这几个类中具有的属性都是中央类型,那万幸,不会出如何难题。但假使那些类里面有局地其余的自定义类型的习性,并且以此本性又径直或直接的留存它自个儿类型的属性,那就能出标题。举例:假使MenuVo这一个类是菜单类,在此个类时又饱含MenuVo类型的八特性质parent代表它的父级菜单。那样的话,系统运营时swagger模块就因不可能加载这几个api而直白报错。报错的原因就算,在加载这一个方式的历程中会剖析这几个update方法的参数,开采参数MenuVo不是简单类型,则会自行以递归的点子批注它富有的类属性。那样就很容易陷于极其递归的死循环。

为了消除这一个难点,我眼下只是本人写了三个OperationParameterReader插件完毕类以至它借助的ModelAttributeParameterExpander工具类,通过配备的不二等秘书技替换掉到srpingfox原本的那五个类,冯谖三窟般的把参数深入分析这些逻辑替换掉,并逃脱Infiniti递归。当然,这一定于是黄金时代种订正源码等级的法子。作者日前还尚无找到消除这些难点的更周全的点子,所以,只好提出大家在用spring-fox Swagger的时候尽量避免这种极端递归的气象。终归,那不相符springmvc命令对像的规范,springmvc参数的吩咐对像中最棒只包括简单的中坚项目属性。

springfox第三土瓜湾:api分组相关,Docket实例不可能顺延加载

springfox私下认可会把具有api分成风姿罗曼蒂克组,那样经过相符于:

@EnableWebMvc
@EnableSwagger2
publicclass ApiConfig {
@Bean
 public Docket customDocket() {
    return newDocket(DocumentationType.SWAGGER_2).apiInfo(apiInfo());
  }
}

上述代码中经过@Bean注入二个Docket,那么些布局并非必得的,若无这么些布局,框架会和煦生成三个暗许的Docket实例。那个Docket实例的效果正是钦点全部它能管住的api的公共音讯,比方api版本、小编等等基本音信,以至钦点只列出如何api(通过api地址或申明过滤卡塔 尔(阿拉伯语:قطر‎。

Docket实例能够有三个,比方如下代码:

@EnableWebMvc
@EnableSwagger2
publicclass ApiConfig {
@Bean
 public Docket customDocket1() {
    return newDocket(DocumentationType.SWAGGER_2)
.groupName("apiGroup1").apiInfo(apiInfo()).select()

.paths(PathSelectors.ant("/sys/**"));

  }

@Bean
 public Docket customDocket2() {
    return newDocket(DocumentationType.SWAGGER_2)
.groupName("apiGroup2").apiInfo(apiInfo())
.select()
.paths(PathSelectors.ant("/shop/**"));
  }
}

当在品种中安排了多少个Docket实例时,也就足以对api实行分组了,比方上边代码将api分为了两组。在这种场合下,必得给每风华正茂组内定三个不一样的名号,举个例子上边代码中的"apiGroup1"和"apiGroup2",每后生可畏组能够用paths通过ant风格的地址表达式来钦命哪大器晚成组处理哪些api。举例上面配置中,第风流倜傥组管理地点为/sys/初阶的api第二组管理/shop/开头的api。当然,还会有好些个其余的过滤方式,比方跟据类表明、方法注脚、地址正则表明式等等。分组后,在api 列表分界面右上角的下拉选拔中就能够选取分歧的api组。那样就把品种的api列表分散到不同的页面了。那样,即方便管理,又不致于页面因急需加载太多api而假死。

不过,同使用@Configuration同样,笔者并不支持选拔@Bean来陈设Docket实例给api分组。因为这么,相似会把代码写死。所以,作者引入在xml文件中本人铺排Docket实例达成那一个相像的效应。当然,构思到Docket中的众多质量,直接配置bean比较费心,能够和睦为Docket写八个FactoryBean,然后在xml文件中布署FactoryBean就能够了。可是将Docket配置到xml中时。又会遇见叁个青龙头,就那是,spring对bean的加载格局私下认可是延迟加载的,在xml中直接配备这个Docket实例Bean后。你会开采,未有一点点效果与利益,页面左上角的下拉列表中跟本未有您的分组项。

其大器晚成标题曾苦恼过自家一点个小时,后来凭阅世臆度出可能是因为sping bean暗中同意延迟加载,这几个Docket实例还未加载到spring context中。实事注明,作者的估算是对的。笔者不晓得那到底springfox的叁个bug,照旧因为本人跟本不应当把对Docket的布置从原来的java代码中搬到xml配置文件中来。

springfox其余的坑:springfox还某些此外的坑,比如@ApiOperation证明中,即使不点名httpMethod属性具体为某个get或post方法时,api列表中,会它get,post,delete,put等富有办法都列出来,搞到api列表重复的太多,比好丑。别的,还会有在测量试验时,蒙受登入权限难点,等等。这一群堆的可比轻易消除的小坑,因为篇幅有限,作者就非常少说了。还应该有诸如@Api、@ApiOperation及@ApiParam等等注明的用法,网络海人民广播广播台湾大学这方面包车型地铁文书档案,小编就不另行了。

上述正是本文的全体内容,希望对大家的上学抱有利于,也期望大家多都赐教帮客之家。

swagger简介swagger确实是个好东西,能够跟据业务代码自动生成相关的api接口文书档案,特别...

    在当下的主流架构中,我们更扩充的见到web Api的留存,小巧,灵活,基于Http合同,使它在更加多的微服务项目大概移动项目充任很好的service endpoint。

图片 1

化解方式是在点子上增加@SuppressLint("NewApi"卡塔尔国或许@TargetApi()。

问题

    以Asp.Net Web Api 为例,随着业务的扩展,产物的迭代,咱们的web api也在紧接着转移,比超多时候会并发多少个本子共存的境况,这时大家就须要规划二个帮忙版本号的web api link,譬如:

原先:

如今:

在大家刚设计的时候,有十分的大恐怕未有构思版本的主题材料,笔者见到相当多的类型都会在link后投入三个“?version=”的主意,这种艺术真的能够缓慢解决难点,但对Asp.Net Web Api来讲,走入的或许同三个Controller,大家需求在同八个Action中开展判别版本号,例如:

]

public class BlogsController : ApiController
{
    // GET api/<controller>
    public IEnumerable<string> Get([FromUri]string version = "")
    {
        if (!String.IsNullOrEmpty(version))
        {
            return new string[] { $"{version} blog1", $"{version} blog2" };
        }
        return new string[] { "blog1", "blog2" };
    }
}

我们看见我们经过判别url中的version参数举办对应的回到,为了确认保障原先接口的可用,大家需求对参数赋上暗许值,即便能够化解大家的版本迭代难点,但随着版本的不断更新,你会意识那一个Controller会越来越肥胖,维护越来越困难,因为这种改过已经严重违反了OCP(Open-Closed Principle卡塔尔国,最佳的法子是不修正原先的Controller,而是新建新的Controller,放在对应的目录中(大概项目中卡塔尔,举个例子:

图片 2

为了不影响原来的项目,我们尽量不要修正原Controller的Namespace,除非你有丰裕的握住未有影响,不然请尽大概只是活动到目录。

ok,为了保持原接口的投射,大家需求在WebApiConfig.Register中注册帮衬版本号的Route映射:

config.Routes.MapHttpRoute(
    name: "DefaultVersionApi",
    routeTemplate: "api/{version}/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

打开浏览器如故postman,输入原先的api url,你会发觉那样的大错特错:

图片 3

那是因为web api 查找Controller的时候,只会凭借ClassName进行查找的,当现身相符ClassName的时候,就能够报这些错误,这时大家就要求成立和睦的Controller Selector,辛亏微软留了一个接口给到咱们:IHttpControllerSelector。可是为了同盟原先的api(有个别不在我们权力限定内的api,不加版本号的这种卡塔尔国,大家依然直接集成DefaultHttpControllerSelector相比较好,大家给定三个规行矩步,不担任大家版本迭代的api,就让它走原先的照耀。

百度了下,查出原因

那她们中间有哪些差异吗,很简单,

思路

1、项目运维的时候,先把符合条件的Controller参加到叁个字典中

2、决断request,符合准绳的,大家回去我们制定的controller。

图片 4

图片 5

图片 6

@SuppressLint("NewApi"卡塔尔国屏蔽一切新api中本事使用的主意报的android lint错误

创立归属本人的Selector

思路有了,那更正起来也很简单,几眼前大家先做贰个大致的,等一时间改成可配备的。

第一步,大家先成立二个Selector类,世袭自DefaultHttpControllerSelector,然后初叶化的时候成立一个归属大家和睦的字典:

public class VersionHttpControllerSelector : DefaultHttpControllerSelector
{
    private readonly HttpConfiguration _configuration;
    private readonly Lazy<Dictionary<string, HttpControllerDescriptor>> _lazyMappingDictionary;
    private const string DefaultVersion = "v1"; //默认版本号,因为之前的api我们没有版本号的概念
    private const string DefaultNamespaces = "WebApiVersions.Controllers"; //为了演示方便,这里就用到一个命名空间
    private const string RouteVersionKey = "version"; //路由规则中Version的字符串
    private const string DictKeyFormat = "{0}.{1}";
    public VersionHttpControllerSelector(HttpConfiguration configuration):base(configuration)
    {
        _configuration = configuration;
        _lazyMappingDictionary = new Lazy<Dictionary<string, HttpControllerDescriptor>>(InitializeControllerDict);
    }

    private Dictionary<string, HttpControllerDescriptor> InitializeControllerDict()
    {
        var result = new Dictionary<string, HttpControllerDescriptor>(StringComparer.OrdinalIgnoreCase);
        var assemblies = _configuration.Services.GetAssembliesResolver();
        var controllerResolver = _configuration.Services.GetHttpControllerTypeResolver();
        var controllerTypes = controllerResolver.GetControllerTypes(assemblies);

        foreach(var t in controllerTypes)
        {
            if (t.Namespace.Contains(DefaultNamespaces)) //符合NameSpace规则
            {
                var segments = t.Namespace.Split(Type.Delimiter);
                var version = t.Namespace.Equals(DefaultNamespaces, StringComparison.OrdinalIgnoreCase) ?
                    DefaultVersion : segments[segments.Length - 1];
                var controllerName = t.Name.Remove(t.Name.Length - DefaultHttpControllerSelector.ControllerSuffix.Length);
                var key = string.Format(DictKeyFormat, version, controllerName);
                if (!result.ContainsKey(key))
                {
                    result.Add(key, new HttpControllerDescriptor(_configuration, t.Name, t));
                }
            }
        }

        return result;
    }
}

有了字典接下去就好办了,只必要深入分析request就好了,切合大家版本须要的,就从大家的字典中寻觅对应的Descriptor,假设找不到,就走暗许的,这里大家要求重写SelectController方法:

public override HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
    IHttpRouteData routeData = request.GetRouteData();
    if (routeData == null)
        throw new HttpResponseException(HttpStatusCode.NotFound);

    var controllerName = GetControllerName(request);
    if (String.IsNullOrEmpty(controllerName))
        throw new HttpResponseException(HttpStatusCode.NotFound);

    var version = DefaultVersion;
    if (IsVersionRoute(routeData, out version))
    {
        var key = String.Format(DictKeyFormat, version, controllerName);
        if (_lazyMappingDictionary.Value.ContainsKey(key))
        {
            return _lazyMappingDictionary.Value[key];
        }

        throw new HttpResponseException(HttpStatusCode.NotFound);
    }

    return base.SelectController(request);
}

private bool IsVersionRoute(IHttpRouteData routeData, out string version)
{
    version = String.Empty;
    var prevRouteTemplate = "api/{controller}/{id}";
    object outVersion;
    if(routeData.Values.TryGetValue(RouteVersionKey, out outVersion))   //先找符合新规则的路由版本
    {
        version = outVersion.ToString();
        return true;
    }

    if (routeData.Route.RouteTemplate.Contains(prevRouteTemplate))  //不符合再比对是否符合原先的api路由
    {
        version = DefaultVersion;
        return true;
    }

    return false;
}

达成这么些类后,大家去WebApiConfig.Register中张开沟通操作:

config.Services.Replace(typeof(IHttpControllerSelector), new VersionHttpControllerSelector(config));

ok,再一次展开浏览器,输入 和 ,当时应该能看出科学的实行:

图片 7

图片 8

进而找到rails项指标解决方法,安装rack-cors那几个gem包

@TargetApi() 只屏蔽某意气风发新api中才干接收的法子报的android lint错误

写在最终

今日我们创制了叁个简练相符webapi版本号更新换代的ControllerSelector,可是还不是很全面,因为不菲皆以hard code,后边我会做三个体协会助配置的ControllerSelector放到github上。

前边向来在商量eShopOnContrainers,近些日子也在研商,不过职业真正有一些忙,见谅见谅,若是大家.Net有怎么着难点只怕喜欢本领交友的,都得以加QQ群:376248054

具体方法如下:

譬喻,有些方法中动用了api9新加盟的措施,而项目设置的android:minSdkVersion=8,那时候在点子上加@SuppressLint("NewApi"卡塔 尔(英语:State of Qatar)

Gemfile中加入

和@TargetApi(Build.VERSION_CODES.GINGERBREAD)都足以,以上是通用的事态。

gem 'rack-cors', :require => 'rack/cors'

而当您在这里格局中又引述了贰个api11才出席的秘诀时,@TargetApi(Build.VE奥迪Q5SION_CODES.GINGERBREAD)评释的不二秘籍又报错了,而

  终端运营  bundle

@SuppressLint("NewApi"卡塔尔国不会报错,那就是分别。

在application.rb中参加以下代码

 

config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins '*'
        resource '*',
                 :headers => :any,
                 :methods => :any,
                 :expose => ['access-token', 'expiry', 'token-type', 'uid', 'client']
      end
 end

理所必然,不管您利用了哪位声明,成效只是是屏蔽android lint错误,所以在点子中还要决断版本做差异的操作,举个例子:

 重启项目就可以缓和此问题

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {  
            //  
} else {// Pre GINGERBREAD  
            //  
}  

 

本文由星彩网app下载发布于计算机编程,转载请注明出处:中http诉求发生access,swagger原精通析与行使进程中

TAG标签: 星彩网app下载
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。