最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

通過Spring Boot整合Mybatis分析自動配置詳解

 更新時間:2019年07月03日 08:22:57   作者:ksfzhaohui  
這篇文章主要給大家介紹了關于如何通過Spring Boot整合Mybatis分析自動配置的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Spring Boot具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧

前言

SpringBoot憑借"約定大于配置"的理念,已經(jīng)成為最流行的web開發(fā)框架,所以有必須對其進行深入的了解;本文通過整合Mybatis類來分析SpringBoot提供的自動配置(AutoConfigure)功能,在此之前首先看一個整合Mybatis的實例。

SpringBoot整合Mybatis

提供SpringBoot整合Mybatis的實例,通過Mybatis實現(xiàn)簡單的增刪改查功能;

1.表數(shù)據(jù)

CREATE TABLE `role` (
 `note` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
 `role_name` varchar(255) DEFAULT NULL,
 `id` bigint(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8

提供創(chuàng)建role表相關的sql,對表進行增刪改查操作;

2.整合Mybatis的依賴

主要是mybatis-spring-boot-starter和使用的mysql驅動:

<dependency>
  <groupId>org.mybatis.spring.boot</groupId>
  <artifactId>mybatis-spring-boot-starter</artifactId>
  <version>2.0.1</version>
</dependency>
<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.29</version>
</dependency>

3.配置application.properties

提供連接mysql相關的信息:url,驅動,用戶名,密碼;

spring.datasource.url=jdbc:mysql://localhost/mybatis
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

4.提供bean和Dao

分別提供表對應的bean類和操作數(shù)據(jù)庫的dao類;

public class Role {

  private long id;
  private String roleName;
  private String note;
  //省略get/set方法
}
@Mapper
public interface RoleDao {

  @Select("SELECT id,role_name as roleName,note FROM role WHERE id = #{id}")
  Role findRoleById(@Param("id") long id);
}

5.提供Service和Controller

public interface RoleService {

  public Role findRoleById(long roleId);

}

@Service
public class RoleServiceImpl implements RoleService {

  @Autowired
  private RoleDao roleDao;

  @Override
  public Role findRoleById(long roleId) {
    return roleDao.findRoleById(roleId);
  }

}
@RestController
public class RoleController {

  @Autowired
  private RoleService roleService;

  @RequestMapping("/role")
  public String getRole(long id) {
    return roleService.findRoleById(id).toString();
  }

}

啟動服務,進行簡單的測試:http://localhost:8888/role?id=111

結果如下:

Role [id=111, roleName=zhaohui, note=hello]

6.提出問題

如上實例中,我們使用了很少的配置,就通過mybatis實現(xiàn)了操作數(shù)據(jù)庫;正常使用mybatis需要的SqlSessionFactory和SqlSession沒有看到被實例化,同時mybatis依賴的數(shù)據(jù)源也沒有看到被引用,那SpringBoot是如何幫我們自動配置的,下面重點分析一下;

SpringBoot自動配置

1.自動配置注解

要想使用自動配置功能,SpringBoot提供了注解@EnableAutoConfiguration,當然不需要我們配置因為在@SpringBootApplication注解中默認以及啟用了;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
    @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
//...省略...
}

可以看到@SpringBootApplication注解本身也有注解@EnableAutoConfiguration:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
//...省略...
}

在注解@EnableAutoConfiguration中重點看一下@Import注解中使用的AutoConfigurationImportSelector類,此類是自動注解的核心類,會有條件的加載我們默認指定的配置類;這里有兩個概念一個是有條件,一個是配置類,分別簡單介紹一下:配置類可以簡單理解就是相關組件對接SpringBoot的對接類,此類可以做一些初始化的工作;有條件表示并不是有配置類就能被對接上,是有條件的,SpringBoot默認提供了大量配置類,但并不是所有配置類都能被加載初始化的,是有條件的,比如mybatis在沒有數(shù)據(jù)源的情況下,沒有mybatis基礎包的情況下是不能被對接的;下面首先看一下SpringBoot提供的哪些條件類;

2.條件類

SpringBoot提供了很多條件類,可以在配置中上配置注解條件類,相關條件類可以在spring-boot-autoconfigure包下的org.springframework.boot.autoconfigure.condition下找到,主要包含如下:

  • ConditionalOnBean:當前容器有指定Bean的條件下;
  • ConditionalOnClass:當前類路徑下有指定類的條件下;
  • ConditionalOnCloudPlatform:當指定了云平臺的時候;
  • ConditionalOnExpression:SpEL表達式作為判斷條件;
  • ConditionalOnJava:JVM版本作為判斷條件;
  • ConditionalOnJndi:在JNDI存在的條件下查找指定的位置;
  • ConditionalOnMissingBean:當容器里沒有指定Bean的情況下;
  • ConditionalOnMissingClass:當類路徑下沒有指定的類的條件下;
  • ConditionalOnNotWebApplication:當前項目不是WEB項目的條件下;
  • ConditionalOnProperty:當前應用是否配置了指定屬性指定的值;
  • ConditionalOnResource:只有當指定的資源位于類路徑下;
  • ConditionalOnSingleCandidate:bean工廠中只有一個或者有多個情況下是主要的候選bean;
  • ConditionalOnWebApplication:當前項目是WEB項目的條件下。

以上是注解類,注解本身沒有功能,只是提供標記的功能,具體功能在@Conditional中指定的,比如ConditionalOnBean注解如下所示:

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnBeanCondition.class)
public @interface ConditionalOnBean {
//...省略...
}

相關功能的實現(xiàn)就在OnBeanCondition類中,同樣其他注解類的實現(xiàn)類也在包org.springframework.boot.autoconfigure.condition下找到;

3.自動配置過程

Springboot應用啟動過程中使用ConfigurationClassParser分析配置類,此類中有一個processImports方法,此方法用來處理@Import注解,在@EnableAutoConfiguration注解存在@Import注解,這時候會實例化注解中的AutoConfigurationImportSelector,在其內部有一個AutoConfigurationGroup內部類,內部類有兩個核心方法分別是:process和selectImports;

    @Override
    public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
      Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
          () -> String.format("Only %s implementations are supported, got %s",
              AutoConfigurationImportSelector.class.getSimpleName(),
              deferredImportSelector.getClass().getName()));
      AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
          .getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
      this.autoConfigurationEntries.add(autoConfigurationEntry);
      for (String importClassName : autoConfigurationEntry.getConfigurations()) {
        this.entries.putIfAbsent(importClassName, annotationMetadata);
      }
    }

此方法主要獲取經(jīng)過條件過濾之后可用的自動配置類,主要調用AutoConfigurationImportSelector中的getAutoConfigurationEntry完成的:

  protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
      AnnotationMetadata annotationMetadata) {
    if (!isEnabled(annotationMetadata)) {
      return EMPTY_ENTRY;
    }
    AnnotationAttributes attributes = getAttributes(annotationMetadata);
    List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
    configurations = removeDuplicates(configurations);
    Set<String> exclusions = getExclusions(annotationMetadata, attributes);
    checkExcludedClasses(configurations, exclusions);
    configurations.removeAll(exclusions);
    configurations = filter(configurations, autoConfigurationMetadata);
    fireAutoConfigurationImportEvents(configurations, exclusions);
    return new AutoConfigurationEntry(configurations, exclusions);
  }

首先獲取了所有備選的自動配置類,然后刪除了重復和被排除的類,最后通過條件進行篩選出可用的配置類,下面分別看一下,首先看一下如何獲取所有備選的配置類:

  protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
        getBeanClassLoader());
    Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
        + "are using a custom packaging, make sure that file is correct.");
    return configurations;
  }

通過SpringFactoriesLoader獲取類路徑下META-INF/spring.factories文件中key為org.springframework.boot.autoconfigure.EnableAutoConfiguration的配置類,可以看一下spring-boot-autoconfigure.jar中的spring.factories內容:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration,\
org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration,\
org.springframework.boot.autoconfigure.cloud.CloudServiceConnectorsAutoConfiguration,\
//...以下省略...

當然這里只是截取了其中一個類路徑jar下的部分配置,獲取所有配置類之后進行去重,去被排除的類,然后進行條件過濾,下面重點看一下:

private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) {
    long startTime = System.nanoTime();
    String[] candidates = StringUtils.toStringArray(configurations);
    boolean[] skip = new boolean[candidates.length];
    boolean skipped = false;
    for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) {
      invokeAwareMethods(filter);
      boolean[] match = filter.match(candidates, autoConfigurationMetadata);
      for (int i = 0; i < match.length; i++) {
        if (!match[i]) {
          skip[i] = true;
          candidates[i] = null;
          skipped = true;
        }
      }
    }
    if (!skipped) {
      return configurations;
    }
    List<String> result = new ArrayList<>(candidates.length);
    for (int i = 0; i < candidates.length; i++) {
      if (!skip[i]) {
        result.add(candidates[i]);
      }
    }
    if (logger.isTraceEnabled()) {
      int numberFiltered = configurations.size() - result.size();
      logger.trace("Filtered " + numberFiltered + " auto configuration class in "
          + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
    }
    return new ArrayList<>(result);
  }

此方法大致就是首先獲取配置的AutoConfigurationImportFilter ,然后對之前獲取的所有配置類進行過濾,最后返回過濾之后的配置類;AutoConfigurationImportFilter同樣也是通過SpringFactoriesLoader類進行加載類路徑下META-INF/spring.factories,只不過當前的key是:org.springframework.boot.autoconfigure.AutoConfigurationImportFilter,可以看一下SpringBoot默認配置的filter:

# Auto Configuration Import Filters
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

可以看到Filter其實就是上文介紹的條件類,這里默認了OnBeanCondition,OnClassCondition以及OnWebApplicationCondition,已這里使用的Mybatis為例看一下MybatisAutoConfiguration的注解:

@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration implements InitializingBean {
//...以下省略...
}

可以看到其中有用到@ConditionalOnClass,表示必須提供SqlSessionFactory和SqlSessionFactoryBean類的情況下才加載此配置類,而整兩個是正式Mybatis基礎包中提供的;有了基礎包還不行,還需要DataSource,而且DataSource必須在MybatisAutoConfiguration實例化之前初始化好,SpringBoot是如何實現(xiàn),繼續(xù)看另外一個核心方法selectImports():

    @Override
    public Iterable<Entry> selectImports() {
      if (this.autoConfigurationEntries.isEmpty()) {
        return Collections.emptyList();
      }
      Set<String> allExclusions = this.autoConfigurationEntries.stream()
          .map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
      Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
          .map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
          .collect(Collectors.toCollection(LinkedHashSet::new));
      processedConfigurations.removeAll(allExclusions);

      return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
          .map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
          .collect(Collectors.toList());
    }

    private List<String> sortAutoConfigurations(Set<String> configurations,
        AutoConfigurationMetadata autoConfigurationMetadata) {
      return new AutoConfigurationSorter(getMetadataReaderFactory(), autoConfigurationMetadata)
          .getInPriorityOrder(configurations);
    }

首先是對被排除類的一個過濾,然后接下來重點看一下對配置類進行排序的一個方法,具體操作在類AutoConfigurationSorter中進行的,具體方法為getInPriorityOrder():

  public List<String> getInPriorityOrder(Collection<String> classNames) {
    AutoConfigurationClasses classes = new AutoConfigurationClasses(this.metadataReaderFactory,
        this.autoConfigurationMetadata, classNames);
    List<String> orderedClassNames = new ArrayList<>(classNames);
    // Initially sort alphabetically
    Collections.sort(orderedClassNames);
    // Then sort by order
    orderedClassNames.sort((o1, o2) -> {
      int i1 = classes.get(o1).getOrder();
      int i2 = classes.get(o2).getOrder();
      return Integer.compare(i1, i2);
    });
    // Then respect @AutoConfigureBefore @AutoConfigureAfter
    orderedClassNames = sortByAnnotation(classes, orderedClassNames);
    return orderedClassNames;
  }

首先使用order進行排序,然后使用@AutoConfigureBefore和@AutoConfigureAfter就行排序;order其實就是通過注解@AutoConfigureOrder進行排序的,值是一個整數(shù),結構類似如下:

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)

@AutoConfigureBefore和@AutoConfigureAfter字面意思也很好理解,指定在其他配置類之前和之后,所以可以看到在MybatisAutoConfiguration中有如下配置:

@AutoConfigureAfter(DataSourceAutoConfiguration.class)

表示在DataSourceAutoConfiguration配置類加載之后才會加載Mybatis配置類,這樣就解決了依賴關系;還有上文提到的Mybatis操作數(shù)據(jù)庫依賴的SqlSessionFactory和SqlSession,都在MybatisAutoConfiguration進行了初始化操作;SpringBoot本身其實以及提供了大量常用組件的自動配置類,我們只需要提供滿足的特定條件,SpringBoot自動會幫我加載初始化等操作,但是肯定也有自定義配置類的需求,下面用一個簡單的實例來看看如何自定義一個自動配置類;

自定義配置類

接下來我們用很簡單的實例來看一下自定義的流程,一個格式化大寫消息的實例;

1.pom文件引入依賴

<groupId>com.format</groupId>
<artifactId>format-spring-boot-starter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>format-spring-boot-starter</name>
<url>http://maven.apache.org</url>

<properties>
  <java.version>1.8</java.version>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-autoconfigure</artifactId>
  </dependency>
</dependencies>

<dependencyManagement>
  <dependencies>
    <dependency>
      <!-- Import dependency management from Spring Boot -->
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>1.5.2.RELEASE</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

Spring 官方 Starter通常命名為spring-boot-starter-{name}如 spring-boot-starter-web,Spring官方建議非官方Starter命名應遵循{name}-spring-boot-starter的格式;

2.服務類和屬性配置類

@ConfigurationProperties("format.service")
public class FormatServiceProperties {
  private String type;
  //...get/set省略...
}

public class FormatService {
  private String type;

  public FormatService(String type) {
    this.type = type;
  }

  public String wrap(String word) {
    if(type.equalsIgnoreCase("Upper")){//大寫
      return word.toUpperCase();
    }else if(type.equalsIgnoreCase("Lower")){//小寫
      return word.toLowerCase();
    }
    return word;
  }
}

屬性類提供了type參數(shù)可以在application.properties中配置,可配置值包括:upper,lower;

3.自動配置類和創(chuàng)建spring.factories文件

@Configuration
@ConditionalOnClass(FormatService.class)
@EnableConfigurationProperties(FormatServiceProperties.class)
public class FormatAutoConfigure {

  @Autowired
  private FormatServiceProperties properties;

  @Bean
  @ConditionalOnMissingBean
  FormatService formatService() {
    return new FormatService(properties.getType());
  }

}

這個就是自定義的自動配置類,SpringBoot啟動的時候會根據(jù)條件自動初始化;最后在resources/META-INF/下創(chuàng)建spring.factories文件:

org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.format.FormatAutoConfigure

4.測試

在其他SpringBoot中可以引入上面創(chuàng)建的項目,引入方式也很簡單:

<dependency>
  <groupId>com.format</groupId>
  <artifactId>format-spring-boot-starter</artifactId>
  <version>0.0.1-SNAPSHOT</version>
</dependency>

同時在application.properties配置格式化類型:

format.service.type=upper

啟動應用,瀏覽器訪問http://localhost:8888/format?word=hello,結果為:HELLO

總結

本文從使用SpringBoot整合Mybatis開始,然后提出使用中產(chǎn)生的疑問,進而通過分析源碼的方式來理解SpringBoot的自動配置機制,最后自定義了一個自動配置類來看看具體如何使用;SpringBoot通過自動配置的方式幫助開發(fā)者減少了很大的工作量,達到開箱即用的效果;但是另一方面如果出現(xiàn)問題需要調試可能不是那么好定位。

示例代碼地址

https://github.com/ksfzhaohui...

  • [springboot]
  • [format-spring-boot-starter]

好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對腳本之家的支持。

相關文章

  • 詳解基于MVC的數(shù)據(jù)查詢模塊進行模糊查詢

    詳解基于MVC的數(shù)據(jù)查詢模塊進行模糊查詢

    這篇文章主要介紹了Java基于MVC的數(shù)據(jù)查詢模塊進行模糊查詢,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-01-01
  • Java 給圖片和動圖添加水印的方法

    Java 給圖片和動圖添加水印的方法

    本篇文章主要介紹了Java 給圖片和動圖添加水印的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-04-04
  • Java泛型映射不同的值類型詳解及實例代碼

    Java泛型映射不同的值類型詳解及實例代碼

    這篇文章主要介紹了Java泛型映射不同的值類型詳解及實例代碼的相關資料,需要的朋友可以參考下
    2017-02-02
  • 2023年IDEA最新永久激活教程(親測可用)

    2023年IDEA最新永久激活教程(親測可用)

    打開電腦,發(fā)現(xiàn)?IDEA?又更新了一個小版本,2022.3.2?版本來了,真的是非常高興,那么這么新的版本怎么激活使用呢?下面小編給大家?guī)砹薸dea2023年最新永久激活方法,感興趣的朋友一起看看吧
    2023-04-04
  • Java實現(xiàn)簡單的銀行管理系統(tǒng)的示例代碼

    Java實現(xiàn)簡單的銀行管理系統(tǒng)的示例代碼

    這篇文章主要介紹了如何利用Java實現(xiàn)簡單的銀行管理系統(tǒng),可以實現(xiàn)存款,取款,查詢等功能,文中的示例代碼講解詳細,感興趣的可以了解一下
    2022-09-09
  • springMVC自定義注解,用AOP來實現(xiàn)日志記錄的方法

    springMVC自定義注解,用AOP來實現(xiàn)日志記錄的方法

    下面小編就為大家分享一篇springMVC自定義注解,用AOP來實現(xiàn)日志記錄的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-01-01
  • 解析Java的設計模式編程之解釋器模式的運用

    解析Java的設計模式編程之解釋器模式的運用

    這篇文章主要介紹了解析Java的設計模式編程之解釋器模式的運用,文中對解釋器模式的優(yōu)缺點及適用場景作出了分析,需要的朋友可以參考下
    2016-02-02
  • Java關鍵字volatile詳析

    Java關鍵字volatile詳析

    這篇文章主要介紹了Java關鍵字volatile,volatile關鍵字可以說是Java虛擬機提供的最輕量級的同步機制,但對于為什么它只能保證可見性,不保證原子性,它又是如何禁用指令重排的,還有很多同學沒徹底理解,文章會讓大家牢掌握一個Java核心知識點
    2022-01-01
  • Java實現(xiàn)修改PDF文件MD5值且保持內容不變

    Java實現(xiàn)修改PDF文件MD5值且保持內容不變

    在某些場景中,我們可能需要改變PDF文件的MD5值,而又不希望改變文件的可視內容,本文詳細介紹了如何實現(xiàn)這一目標,并提供了具體的Java實現(xiàn)示例,需要的可以參考下
    2023-10-10
  • Spring Data JPA踩坑記錄(@id @GeneratedValue)

    Spring Data JPA踩坑記錄(@id @GeneratedValue)

    這篇文章主要介紹了Spring Data JPA踩坑記錄(@id @GeneratedValue),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07

最新評論

石景山区| 新巴尔虎左旗| 讷河市| 宜兴市| 罗平县| 唐海县| 桂林市| 金山区| 高雄市| 仙居县| 桂阳县| 东明县| 凭祥市| 寿阳县| 鄢陵县| 英德市| 祁连县| 永康市| 林甸县| 北票市| 南昌市| 蚌埠市| 陕西省| 莒南县| 芜湖县| 娄底市| 大渡口区| 台州市| 仪陇县| 恩平市| 洪江市| 杂多县| 棋牌| 顺义区| 营口市| 集贤县| 汉中市| 嵊泗县| 湾仔区| 工布江达县| 甘孜|