威尼斯人线上娱乐

【威尼斯人线上娱乐】中http请求产生access,营造属于本人的帮衬版本迭代的Asp

11 4月 , 2019  

在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的1对了解以及必要专注的地点。

springfox大约原理

springfox的大致原理正是,在类型运转的过种中,spring上下文在伊始化的经过,框架自动跟据配置加载1些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界面包车型地铁话,也得以不要那么些,而别的本身写1套适合本身项目标界面。加入这一个依靠后,系统后会自动进入1些跟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集成起来万分简单,只要写2个类似于以下代码的类放到您的档次里就行了,代码如下:

@Configuration

@EnableWebMvc

@EnableSwagger2

publicclass ApiConfig {}

在意到,下面是1个空的java类文件,类名能够私自钦命,但必须进入上述类中标注的@Configuration、@EnableWebMvc、@EnableSwagger二多个申明,那样就到位了springmvc与springfox的主题集成,有了多个注明,项目运营后就可以直接用接近于以下的地方来查看api列表了:

那真的是3个很神奇的遵守,不难的多个注明,系统就机关展现出档次里具有Controller类的全数api了。今后,我们就以此布局类动手,简单分析它的法则。那些类中从未别的代码,很鲜明,四个申明起了重在的机能。在那之中@Configuration注明是spring框架中笔者就部分,它是贰个被@Component元评释标识的诠释,所以有了这些证明后,spring会自动把这么些类实例化成1个bean注册到spring上下文中。第1个表明@EnableWebMvc故名思义,便是启用srpingmvc了,在Eclipse中式点心到这一个评释里面差不离看一下,它正是由此元申明@Import(DelegatingWebMvcConfiguration.class)往spring
context中塞入了叁个DelegatingWebMvcConfiguration类型的bean。笔者想,那几个类的指标应该正是为swagger提供了一些springmvc方面包车型地铁布置吧。第伍个表明:@EnableSwagger二,看名字应该能够想到,是用来集成swagger
2的,他经过元注脚:@Import({Swagger二DocumentationConfiguration.class}),又引进了三个Swagger二DocumentationConfiguration类型的配备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();
 }
}

【威尼斯人线上娱乐】中http请求产生access,营造属于本人的帮衬版本迭代的Asp。以此类尾部通过壹些注解,再引进SpringfoxWebMvcConfiguration类和SwaggerCommonConfiguration类,并通过ComponentScan表明,自动扫描springfox
.swagger二相关的的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,

第1个ApiListingBuilderPlugin,它有五个落实类,分别是ApiListingReader和SwaggerApiListing里德r。个中ApiListingReader会自动跟据Controller类型生成api列表,而SwaggerApiListingReader会跟据有@Api评释标识的类生成api列表。OperationBuilderPlugin插件就是用来生成现实api文书档案的,那么些项目标插件,有诸多过多落实类,他们分别分工,各做各的事情,具体笔者并未有仔细去看,只关切了里面3个贯彻类:OperationParameterReader,那几个类是用于读取api参数的Plugin。它借助于ModelAttributeParameterExpander工具类,能够将Controller中接口方法参数中国和欧洲大致类型的指令对像自动分析它在那之中的习性得出包括全体属性的参数列表(那里存在二个或然相会世极其递归的坑,下文有介绍)。而ExpandedParameterBuilderPlugin插件,首若是用来扩张接口参数的1对功能,比如判断这么些参数的数据类型以及是或不是为这一个接口的必须参数等等。总体上说,整个springfox-swagger内部其实是由这一文山会海的plug转运起来的。他们在系统运行时,就被调起来,有个别用来围观出接口列表,有个别用来读取接口参数等等。他们一起的目地便是把系统中持有api接口都围观出来,并缓存起来供用户查看。那么,那一多元表plug到底是什么被调起来的,它们的执行入口倒底在哪?

  
大家把注意点放到上文SpringfoxWebMvcConfiguration那几个类代码底部的ComponentScan注脚内容上来,那壹段注脚中围观了3个叫springfox.documentation.spring.web.plugins的package,那么些package在springfox-spring-web-2.陆.1.jar中能够找到。那个package下,大家发现有多个11分核心的类,那正是DocumentationPluginsManager和DocumentationPluginsBootstrapper。对于第三个DocumentationPluginsManager,它是二个尚无兑现别的接口的bean,但它当中有很多PluginRegistry类型的习性,而且都以由此@Autowired注明把属性值注入进来的。接合它的类名来看,很不难想到,这一个就是治本全数plug的三个管理器了。很好驾驭,因为ComponentScan注脚的布局,全部的plug实例都会被spring实例化成2个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的大致原理。它至关心重视假设因此EnableSwagger二表明,向srping
context注入了一名目繁多bean,并在系统运转的时候自动扫描系统的Controller类,生成对应的api音讯并缓存起来。别的,它还注入了部分被@Controller表明标识的Controller类,作为ui模块访问api列表的输入。比如springfox-swagger2-2.6.一.jar包中的Swagger2Controller类。那一个Controller正是ui模块中用来拜会api列表的界面地址。在走访

叩问了springfox的原理,下边来探望springfox使用进程中,小编蒙受的怎么着坑。

springfox第一大坑:配置类生成的bean必须与spring
mvc共用同3个上下文。

前文描述了,在springmvc项目中,集成springfox是只要在档次写三个之类的未有其余事情代码的简要布置类就足以了。

@Configuration
@EnableWebMvc
@EnableSwagger2
publicclass ApiConfig {
}

因为@Configuration表明的效能,spring会自动把它实例化成二个bean注入到上下文。但切记要专注的一个坑正是:那么些bean所在的上下文必须跟spring
mvc为同多个上下文。怎么解理呢?因为在事实上的spring
mvc项目中,平日有三个上下文,贰个是跟上下文,另二个是spring
mvc(它是跟上下文的子上下文)。个中跟上下文是正是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加载起来,他普通有1个配备文件叫spring-mvc.xml。大家在写ApiConfig这些类时,借使决定用@Configuration评释来加载,那么就必须确认保障那个类所在的门路刚辛亏springmvc的component-scan的安顿的base-package范围内。因为在ApiConfig在被spring加载时,会注入一列体系的bean,而那么些bean中,为了能自动扫描出装有Controller类,有个别bean须要依靠于SpringMvc中的1些bean,要是项目把Srpingmvc的上下文与跟上下文分开来,作为跟上下文的子上下文的话。借使相当大心让这一个ApiConfig类型的bean被跟上文加载到,因为root
context中并未有spring mvc的context中的那三个配置类时就会报错。

实际上,作者并不相同情通过@Configuration注脚来陈设Swagger,因为作者觉着,Swagger的api作用对于生产类型以来是无所谓的。大家Swagger往往是用来测试环境供项近年来端团队耗费或供别的体系作接口集成使上。系统上线后,很只怕在生产系统上隐藏这几个api列表。
但假如布置是经过@Configuration注解写死在java代码里的话,那么上线的时候想去掉这么些职能的时候,那就难堪了,不得不修改java代码重新编写翻译。基于此,笔者引入的3个艺术,通过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有强劲的参数绑定机制,能够自行把请求参数绑定为3个自定义的授命对像。所以,很多开发职员在写Controller时,为了偷懒,间接把叁个实体对像作为Controller方法的1个参数。比如上面这些示例代码:

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

这是绝超越八分之四程序员喜欢在Controller中写的修改某个实体的代码。在跟swagger集成的时候,那里有多个大坑。如若MenuVo那些类中具备的天性都以着力项目,那辛亏,不会出哪些难题。但万一那一个类里面有壹些其余的自定义类型的性质,而且这天性情又一直或直接的留存它自身类型的天性,这就会出标题。例如:就算MenuVo这几个类是菜单类,在那个类时又富含MenuVo类型的1个属性parent代表它的父级菜单。那样的话,系统运行时swagger模块就因不或然加载那些api而直白报错。报错的因由就是,在加载那么些法子的经过中会解析这几个update方法的参数,发现参数MenuVo不是不难类型,则会自行以递归的不二等秘书籍诠释它有着的类属性。那样就很不难陷入至极递归的死循环。

为了化解那些标题,笔者当下只是自个儿写了二个OperationParameterReader插件达成类以及它凭借的ModelAttributeParameterExpander工具类,通过布置的点子替换掉到srpingfox原来的那五个类,偷梁换柱般的把参数解析那些逻辑替换掉,并逃脱Infiniti递归。当然,这一定于是壹种修改源码级其他措施。笔者当下还未有找到消除这一个难点的更宏观的不二法门,所以,只好提出我们在用spring-fox
Swagger的时候尽量幸免那种极端递归的境况。终究,那不符合springmvc命令对像的正式,springmvc参数的指令对像中最佳只含有不难的着力项目属性。

springfox第3大坑: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分为了两组。在那种场地下,必须给每一组钦命贰个两样的名称,比如上面代码中的”apiGroup一”和”apiGroup二”,每壹组能够用paths通过ant风格的地方表达式来钦点哪壹组管理哪些api。比如上面配置中,第3组管理地方为/sys/伊始的api第二组管理/shop/开首的api。当然,还有许多其余的过滤格局,比如跟据类评释、方法表明、地址正则表达式等等。分组后,在api
列表界面右上角的下拉选择中就足以挑选不一样的api组。那样就把项指标api列表分散到分裂的页面了。那样,即方便管理,又不致于页面因急需加载太多api而假死。

然则,同使用@Configuration壹样,小编并区别情接纳@Bean来布置Docket实例给api分组。因为如此,同样会把代码写死。所以,小编引进在xml文件中自身配置Docket实例完毕那几个类似的效应。当然,考虑到Docket中的众多性质,间接配置bean相比麻烦,能够友善为Docket写三个FactoryBean,然后在xml文件中配备FactoryBean就行了。不过将Docket配置到xml中时。又会赶上2个大坑,就那是,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来说,进入的或许同1个Controller,大家供给在同1个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,幸亏微软留了2个接口给到大家:IHttpControllerSelector。可是为了配合原先的api(有个别不在大家权力限制内的api,不加版本号的那种),大家依然一向集成DefaultHttpControllerSelector相比较好,大家给定二个平整,不负责大家版本迭代的api,就让它走原先的照射。

威尼斯人线上娱乐,百度了下,查出原因

那他们之间有啥分别呢,很简短,

思路

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

2、判断request,符合规则的,大家回去大家制订的controller。

威尼斯人线上娱乐 4

威尼斯人线上娱乐 5

威尼斯人线上娱乐 6

@SuppressLint(“NewApi”)屏蔽1切新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中才能应用的不2法门报的android lint错误

写在终极

前日大家营造了二个简易符合webapi版本号更新迭代的ControllerSelector,可是还不是很完美,因为众多都以hard
code,后边小编会做二个支撑配置的ControllerSelector放到github上。

事先一向在商讨eShopOnContrainers,最近也在钻探,可是工作真正有点忙,见谅见谅,如若大家.Net有啥难题照旧喜欢技术交友的,都得以加QQ群:37624805四

具体方法如下:

举个例子,有些方法中央银行使了api玖新参加的法子,而项目安装的android:minSdkVersion=8,此时在艺术上加@SuppressLint(“NewApi”)

Gemfile中加入

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

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

而当您在此措施中又引述了1个api1一才投入的方法时,@TargetApi(Build.VERAV肆SION_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  
            //  
}  

 


相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图