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

關(guān)于注解式的分布式Elasticsearch的封裝案例

 更新時(shí)間:2021年01月25日 10:47:33   作者:蒼穹之躍  
這篇文章主要介紹了關(guān)于注解式的分布式Elasticsearch的封裝案例,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧

原生的Rest Level Client不好用,構(gòu)建檢索等很多重復(fù)操作。

對bboss-elasticsearch進(jìn)行了部分增強(qiáng):通過注解配合實(shí)體類進(jìn)行自動(dòng)構(gòu)建索引和自動(dòng)刷入文檔,復(fù)雜的業(yè)務(wù)檢索需要自己在xml中寫Dsl。用法與mybatis-plus如出一轍。

依賴

<dependency>
			<groupId>org.elasticsearch</groupId>
			<artifactId>elasticsearch</artifactId>
		</dependency>
		<dependency>
			<groupId>com.bbossgroups.plugins</groupId>
			<artifactId>bboss-elasticsearch-spring-boot-starter</artifactId>
			<version>5.9.5</version>
			<exclusions>
				<exclusion>
					<artifactId>slf4j-log4j12</artifactId>
					<groupId>org.slf4j</groupId>
				</exclusion>
			</exclusions>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.6</version>
			<scope>provided</scope>
		</dependency>

配置:

 
import com.rz.config.ElsConfig;
import org.frameworkset.elasticsearch.boot.ElasticSearchBoot;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; 
import java.util.HashMap;
import java.util.Map;
 
/**
 * 啟動(dòng)時(shí)初始化bBoss
 *
 * @author sunziwen
 * @version 1.0
 * @date 2019/12/12 16:54
 **/
@Component
@Order(value = 1)
public class StartElastic implements ApplicationRunner {
 @Autowired
 private ElsConfig config;
 
 @Override
 public void run(ApplicationArguments args) throws Exception {
 Map properties = new HashMap();
 properties.put("elasticsearch.rest.hostNames", config.getElsClusterNodes());
 ElasticSearchBoot.boot(properties);
 }
}

注解和枚舉:

package com.rz.szwes.annotations;
 
import java.lang.annotation.*;
 
/**
 * 標(biāo)識實(shí)體對應(yīng)的索引信息
 *
 * @author sunziwen
 * 2019/12/13 10:14
 * @version 1.0
 **/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ESDsl {
 /**
 * xml的位置
 */
 String value();
 
 String indexName();
 
 /**
 * elasticsearch7.x版本已經(jīng)刪除該屬性
 */
 String indexType() default "";
}
package com.rz.szwes.annotations;
 
 
import java.lang.annotation.*;
 
/**
 * 為字段指定映射類型
 *
 * @author sunziwen
 * 2019/12/14 10:06
 * @version 1.0
 **/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ESMapping {
 //映射類型
 ESMappingType value();
 
 //加權(quán)
 int boost() default 1;
 
 //分詞標(biāo)識analyzed、not_analyzed
 String index() default "analyzed";
 
 //分詞器ik_max_word、standard
 String analyzer() default "ik_max_word";
 
 //String作為分組聚合字段的時(shí)候需要設(shè)置為true
 boolean fildData() default false;
}
package com.rz.szwes.annotations;
 
/**
 * Es映射類型枚舉(定義了大部分,有缺失請使用者補(bǔ)全)當(dāng)前版本基于elasticsearch 6.8
 *
 * @author sunziwen
 * 2019/12/14 10:09
 * @version 1.0
 **/
public enum ESMappingType {
 /**
 * 全文搜索。
 */
 text("text"),
 /**
 * keyword類型適用于索引結(jié)構(gòu)化(排序、過濾、聚合),只能通過精確值搜索到。
 */
 keyword("keyword"),
 
 /
 
 /**
 * -128~127 在滿足需求的情況下,盡可能選擇范圍小的數(shù)據(jù)類型。
 */
 _byte("byte"),
 /**
 * -32768~32767
 */
 _short("short"),
 /**
 * -2^31~2^31-1
 */
 _integer("integer"),
 /**
 * -2^63~2^63-1
 */
 _long("long"),
 
 /
 /**
 * 64位雙精度IEEE 754浮點(diǎn)類型
 */
 _doule("doule"),
 /**
 * 32位單精度IEEE 754浮點(diǎn)類型
 */
 _float("float"),
 /**
 * 16位半精度IEEE 754浮點(diǎn)類型
 */
 half_float("half_float"),
 /**
 * 縮放類型的的浮點(diǎn)數(shù)
 */
 scaled_float("scaled_float"),
 
 /
 /**
 * 時(shí)間類型
 */
 date("date"),
 
 _boolean("boolean"),
 /**
 * 范圍類型
 */
 range("range"),
 /**
 * 嵌套類型
 */
 nested("nested"),
 /**
 * 地理坐標(biāo)
 */
 geo_point("geo_point"),
 /**
 * 地理地圖
 */
 geo_shape("geo_shape"),
 /**
 * 二進(jìn)制類型
 */
 binary("binary"),
 /**
 * ip 192.168.1.2
 */
 ip("ip");
 
 private String value;
 
 ESMappingType(String value) {
 this.value = value;
 }
 
 public String getValue() {
 return value;
 }
}

工具類:對HashMap進(jìn)行了增強(qiáng)

package com.rz.szwes.util; 
import java.util.HashMap;
import java.util.function.Supplier;
 
/**
 * 原始HashMap不支持Lambda表達(dá)式,特此包裝一個(gè)
 *
 * @author sunziwen
 * @version 1.0
 * @date 2019/12/13 11:09
 **/
public class LambdaHashMap<K, V> extends HashMap<K, V> { 
 public static <K, V> LambdaHashMap<K, V> builder() {
 return new LambdaHashMap<>();
 }
 
 public LambdaHashMap<K, V> put(K key, Supplier<V> supplier) {
 super.put(key, supplier.get());
 //流式
 return this;
 }
}

核心類兩個(gè):

package com.rz.szwes.core; 
import cn.hutool.core.util.ClassUtil;
import com.alibaba.fastjson.JSON;
import com.frameworkset.orm.annotation.ESId;
import com.rz.szwes.annotations.ESDsl;
import com.rz.szwes.annotations.ESMapping;
import com.rz.szwes.util.LambdaHashMap;
import org.springframework.util.StringUtils; 
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
 
/**
 * 抽象類解析泛型
 *
 * @author sunziwen
 * 2019/12/14 16:04
 * @version 1.0
 **/
public abstract class AbstractElasticBase<T> {
 { //初始化解析
 ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
 // 獲取第一個(gè)類型參數(shù)的真實(shí)類型
 Class<T> clazz = (Class<T>) pt.getActualTypeArguments()[0];
 parseMapping(clazz);
 }
 
 /**
 * 索引名稱
 */
 protected String indexName;
 /**
 * 索引類型
 */
 protected String indexType;
 /**
 * es寫dsl的文件路徑
 */
 protected String xmlPath;
 /**
 * 索引映射
 */
 protected String mapping;
 
 //將Class解析成映射JSONString
 private void parseMapping(Class<T> clazz) {
 if (clazz.isAnnotationPresent(ESDsl.class)) {
  ESDsl esDsl = clazz.getAnnotation(ESDsl.class);
  this.xmlPath = esDsl.value();
  this.indexName = esDsl.indexName();
  //如果類型為空,則采用索引名作為其類型
  this.indexType = StringUtils.isEmpty(esDsl.indexType()) ? esDsl.indexName() : esDsl.indexType();
 } else {
  throw new RuntimeException(clazz.getName() + "缺失注解[@ESDsl]");
 }
 //構(gòu)建索引映射
 LambdaHashMap<Object, Object> put = LambdaHashMap.builder()
        .put("mappings", () -> LambdaHashMap.builder()
            .put(indexType, () -> LambdaHashMap.builder()
                .put("properties", () -> {
                 Field[] fields = clazz.getDeclaredFields();
                 LambdaHashMap<Object, Object> builder = LambdaHashMap.builder();
                 for (Field field : fields) {
                 builder.put(field.getName(), () -> toEsjson(field));
                 }
                 return builder;
                })))
 ;
 this.mapping = JSON.toJSONString(put);
 }
 
 private LambdaHashMap<Object, Object> toEsjson(Field field) {
 //基本數(shù)據(jù)類型
 if (ClassUtil.isSimpleTypeOrArray(field.getType())) {
  //對字符串做大小限制、分詞設(shè)置
  if (new ArrayList<Class>(Collections.singletonList(String.class)).contains(field.getType())) {
  LambdaHashMap<Object, Object> put = LambdaHashMap.builder()
         .put("type", () -> "text")
         .put("fields", () -> LambdaHashMap.builder()
             .put("keyword", () -> LambdaHashMap.builder()
                 .put("type", () -> "keyword")
                 .put("ignore_above", () -> 256)));
  if (field.isAnnotationPresent(ESMapping.class)) {
   ESMapping esMapping = field.getAnnotation(ESMapping.class);
   //設(shè)置聚合分組
   if (esMapping.fildData()) {
   put.put("fildData", () -> true);
   }
   //設(shè)置加權(quán)
   if (esMapping.boost() != 1) {
   put.put("boost", esMapping::boost);
   }
   //設(shè)置是否進(jìn)行分詞
   if (!"analyzed".equals(esMapping.index())) {
   put.put("analyzed", esMapping::analyzer);
   }
   //分詞器
   put.put("analyzer", esMapping::analyzer);
  }
  return put;
  }
  //設(shè)置默認(rèn)類型
  return LambdaHashMap.builder().put("type", () -> {
  if (field.isAnnotationPresent(ESMapping.class)) {
   ESMapping esMapping = field.getAnnotation(ESMapping.class);
   return esMapping.value().getValue();
  }
  if (new ArrayList<Class>(Arrays.asList(byte.class, Byte.class, short.class, Short.class, int.class, Integer.class, long.class, Long.class)).contains(field.getType())) {
   return "long";
  } else if (new ArrayList<Class>(Arrays.asList(double.class, Double.class, float.class, Float.class)).contains(field.getType())) {
   return "double";
  } else if (new ArrayList<Class>(Arrays.asList(Date.class, java.sql.Date.class, LocalDate.class, LocalDateTime.class, LocalTime.class)).contains(field.getType())) {
   return "date";
  } else if (new ArrayList<Class>(Arrays.asList(boolean.class, Boolean.class)).contains(field.getType())) {
   return "boolean";
  }
  return "text";
  });
 } else {
  //設(shè)置對象類型
  LambdaHashMap<Object, Object> properties = LambdaHashMap.builder()
         .put("properties", () -> {
         Field[] fields = field.getType().getDeclaredFields();
         LambdaHashMap<Object, Object> builder = LambdaHashMap.builder();
         for (Field field01 : fields) {
          builder.put(field01.getName(), toEsjson(field01));
         }
         return builder;
         });
  if (field.isAnnotationPresent(ESMapping.class)) {
  ESMapping esMapping = field.getAnnotation(ESMapping.class);
  properties.put("type", esMapping.value().getValue());
  }
  return properties;
 }
 } 
}
package com.rz.szwes.core; 
import lombok.extern.slf4j.Slf4j;
import org.frameworkset.elasticsearch.boot.BBossESStarter;
import org.frameworkset.elasticsearch.client.ClientInterface;
import org.frameworkset.elasticsearch.client.ClientUtil;
import org.springframework.beans.factory.annotation.Autowired; 
import java.util.*;
 
/**
 * Elastic基礎(chǔ)函數(shù)
 *
 * @author sunziwen
 * @version 1.0
 * @date 2019/12/13 9:56
 **/
@Slf4j
public class ElasticBaseService<T> extends AbstractElasticBase<T> {
 
 @Autowired
 private BBossESStarter starter;
 
 /**
 * Xml創(chuàng)建索引
 */
 protected String createIndexByXml(String xmlName) {
 ClientInterface restClient = starter.getConfigRestClient(xmlPath);
 boolean existIndice = restClient.existIndice(this.indexName);
 if (existIndice) {
  restClient.dropIndice(indexName);
 }
 return restClient.createIndiceMapping(indexName, xmlName);
 }
 
 /**
 * 自動(dòng)創(chuàng)建索引
 */
 protected String createIndex() {
 ClientInterface restClient = starter.getRestClient();
 boolean existIndice = restClient.existIndice(this.indexName);
 if (existIndice) {
  restClient.dropIndice(indexName);
 }
 log.debug("創(chuàng)建索引:" + this.mapping);
 return restClient.executeHttp(indexName, this.mapping, ClientUtil.HTTP_PUT);
 }
 
 /**
 * 刪除索引
 */
 protected String delIndex() {
 return starter.getRestClient().dropIndice(this.indexName);
 }
 
 /**
 * 添加文檔
 *
 * @param t 實(shí)體類
 * @param refresh 是否強(qiáng)制刷新
 */
 protected String addDocument(T t, Boolean refresh) {
 return starter.getRestClient().addDocument(indexName, indexType, t, "refresh=" + refresh);
 }
 
 /**
 * 添加文檔
 *
 * @param ts 實(shí)體類集合
 * @param refresh 是否強(qiáng)制刷新
 */
 protected String addDocuments(List<T> ts, Boolean refresh) {
 return starter.getRestClient().addDocuments(indexName, indexType, ts, "refresh=" + refresh);
 }
 
 /**
 * 分頁-添加文檔集合
 *
 * @param ts 實(shí)體類集合
 * @param refresh 是否強(qiáng)制刷新
 */
 protected void addDocumentsOfPage(List<T> ts, Boolean refresh) {
 this.delIndex();
 this.createIndex();
 int start = 0;
 int rows = 100;
 Integer size;
 do {
  List<T> list = pageDate(start, rows);
  if (list.size() > 0) {
  //批量同步信息
  starter.getRestClient().addDocuments(indexName, indexType, ts, "refresh=" + refresh);
  }
  size = list.size();
  start += size;
 } while (size > 0);
 }
 
 /**
 * 使用分頁添加文檔必須重寫該類
 *
 * @param start 起始
 * @param rows 項(xiàng)數(shù)
 * @return
 */
 protected List<T> pageDate(int start, int rows) {
 return null;
 }
 
 /**
 * 刪除文檔
 *
 * @param id id
 * @param refresh 是否強(qiáng)制刷新
 * @return
 */
 protected String delDocument(String id, Boolean refresh) {
 return starter.getRestClient().deleteDocument(indexName, indexType, id, "refresh=" + refresh);
 }
 
 /**
 * 刪除文檔
 *
 * @param ids id集合
 * @param refresh 是否強(qiáng)制刷新
 * @return
 */
 protected String delDocuments(String[] ids, Boolean refresh) {
 return starter.getRestClient().deleteDocumentsWithrefreshOption(indexName, indexType, "refresh=" + refresh, ids);
 }
 
 /**
 * id獲取文檔
 *
 * @param id
 * @return
 */
 protected T getDocument(String id, Class<T> clazz) {
 return starter.getRestClient().getDocument(indexName, indexType, id, clazz);
 }
 
 /**
 * id更新文檔
 *
 * @param t 實(shí)體
 * @param refresh 是否強(qiáng)制刷新
 * @return
 */
 protected String updateDocument(String id, T t, Boolean refresh) {
 return starter.getRestClient().updateDocument(indexName, indexType, id, t, "refresh=" + refresh);
 }
}

寫復(fù)雜Dsl的xml:(如何寫Dsl請參考bBoss-elasticsearch文檔,用法類似mybatis標(biāo)簽)

<properties> 
</properties>

框架集成完畢,以下是使用示例:

定義數(shù)據(jù)模型:

package com.rz.dto;
 
import com.frameworkset.orm.annotation.ESId;
import com.rz.szwes.annotations.ESDsl;
import com.rz.szwes.annotations.ESMapping;
import com.rz.szwes.annotations.ESMappingType;
import lombok.Data; 
import java.util.List;
 
/**
 * 對應(yīng)elasticsearch服務(wù)器的數(shù)據(jù)模型
 *
 * @author sunziwen
 * @version 1.0
 * @date 2019/12/16 11:08
 **/
@ESDsl(value = "elasticsearch/zsInfo.xml", indexName = "zsInfo")
@Data
public class ElasticZsInfoDto {
 @ESMapping(ESMappingType._byte)
 private int least_hit;
 private int is_must_zz;
 private int zs_level;
 private int cur_zs_ct;
 private int least_score_yy;
 private int least_score_yw;
 private int area_id;
 private String coll_name;
 private String coll_code;
 private long coll_pro_id;
 private int is_must_wl;
 private int cur_year;
 private int is_two;
 private long logo;
 @ESId
 private int id;
 private String area;
 private int college_id;
 private String is_must_yy;
 private int is_double;
 private int least_score_zz;
 private int least_score_wl;
 private String grade;
 private int is_nine;
 private String pro_name;
 private int least_score_sx;
 private int relevanceSort;
 private int pre_avg;
 private String is_must_dl;
 private String profession_code;
 private int least_score_sw;
 private String is_must_ls;
 private int grade_zk;
 private int least_score_wy;
 private int is_must_hx;
 private int profession_id;
 private String is_grad;
 private String is_must_yw;
 private int is_must_sw;
 private int least_score_ls;
 private int least_score_dl;
 private String zs_memo;
 private String is_must_sx;
 private String introduce;
 private int is_must_wy;
 private int grade_bk;
 private String pre_name;
 private int least_score_hx;
 private String coll_domain;
 private int pre_wch;
 private List<String> courses;
}

定義服務(wù)

package com.rz.service; 
import com.rz.dto.ElasticZsInfoDto;
import com.rz.szwes.core.ElasticBaseService; 
 
/**
 * 招生索引操作服務(wù)
 *
 * @author sunziwen
 * @version 1.0
 * @date 2019/12/16 11:02
 **/
public class ElasticZsInfoService extends ElasticBaseService<ElasticZsInfoDto> { 
}

完畢。

已經(jīng)可以進(jìn)行索引和文檔的crud操作了,至于復(fù)雜的檢索操作就需要在xml中定義了。這里只介紹了我增強(qiáng)的功能,大部分功能都在bBoss中定義好了,讀者可以去看bBoss文檔(筆者認(rèn)為的他的唯一缺陷是不能通過實(shí)體配合注解實(shí)現(xiàn)自動(dòng)索引,還要每次手動(dòng)指定xml位置,手動(dòng)寫mapping是很痛苦的事情,特此進(jìn)行了增強(qiáng))。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章

  • JVM知識總結(jié)之垃圾收集算法

    JVM知識總結(jié)之垃圾收集算法

    本博客為讀書筆記,讀的是《深入理解Java虛擬機(jī)》一書,在看這個(gè)書的時(shí)候,最大的一個(gè)感受便是“當(dāng)初怎么就沒有好好學(xué)習(xí)操作系統(tǒng)呢,不然也不會(huì)有這么多看的云里霧里的地方了”,不過那都是過去的事了,學(xué)習(xí)最好的時(shí)刻便是現(xiàn)在,需要的朋友可以參考下
    2021-06-06
  • SpringBoot中的@EnableConfigurationProperties注解原理及用法

    SpringBoot中的@EnableConfigurationProperties注解原理及用法

    在SpringBoot中,@EnableConfigurationProperties注解是一個(gè)非常有用的注解,它可以用于啟用對特定配置類的支持,在本文中,我們將深入探討@EnableConfigurationProperties注解,包括它的原理和如何使用,需要的朋友可以參考下
    2023-06-06
  • 200行Java代碼編寫一個(gè)計(jì)算器程序

    200行Java代碼編寫一個(gè)計(jì)算器程序

    本篇文章給大家分享的只用200行java代碼,實(shí)現(xiàn)一個(gè)計(jì)算器程序,不僅能夠計(jì)算加減乘除,還能夠匹配小括號。實(shí)現(xiàn)代碼超簡單,需要的朋友參考下吧
    2017-12-12
  • java 單例模式和工廠模式實(shí)例詳解

    java 單例模式和工廠模式實(shí)例詳解

    這篇文章主要介紹了Java設(shè)計(jì)模式編程中的單例模式和簡單工廠模式以及實(shí)例,使用設(shè)計(jì)模式編寫代碼有利于團(tuán)隊(duì)協(xié)作時(shí)程序的維護(hù),需要的朋友可以參考下
    2017-04-04
  • IDEA 中創(chuàng)建SpringBoot 父子模塊的實(shí)現(xiàn)

    IDEA 中創(chuàng)建SpringBoot 父子模塊的實(shí)現(xiàn)

    這篇文章主要介紹了IDEA 中創(chuàng)建SpringBoot 父子模塊的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Spring Data Jpa 復(fù)合主鍵的實(shí)現(xiàn)

    Spring Data Jpa 復(fù)合主鍵的實(shí)現(xiàn)

    這篇文章主要介紹了Spring Data Jpa 復(fù)合主鍵的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Java高性能實(shí)體類轉(zhuǎn)換工具M(jìn)apStruct的使用教程詳解

    Java高性能實(shí)體類轉(zhuǎn)換工具M(jìn)apStruct的使用教程詳解

    MapStruct 是一個(gè)代碼生成器,它基于約定優(yōu)于配置的方法,極大地簡化了 Java bean 類型之間的映射實(shí)現(xiàn),本文主要介紹了MapStruct的具體使用以及如何進(jìn)行實(shí)體類轉(zhuǎn)換,感興趣的可以了解下
    2024-03-03
  • 二進(jìn)制中1的個(gè)數(shù)

    二進(jìn)制中1的個(gè)數(shù)

    這篇文章介紹了二進(jìn)制中1的個(gè)數(shù),有需要的朋友可以參考一下
    2013-09-09
  • 了解Java線程池創(chuàng)建過程

    了解Java線程池創(chuàng)建過程

    那么有沒有一種辦法使得線程可以復(fù)用,就是執(zhí)行完一個(gè)任務(wù),并不被銷毀,而是可以繼續(xù)執(zhí)行其他的任務(wù)?在Java中可以通過線程池來達(dá)到這樣的效果。下面我們來詳細(xì)了解一下吧
    2019-05-05
  • Springboot項(xiàng)目的搭建教程(分離出common父依賴)

    Springboot項(xiàng)目的搭建教程(分離出common父依賴)

    這篇文章主要介紹了Springboot項(xiàng)目的搭建教程(分離出common父依賴),具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-01-01

最新評論

富民县| 邳州市| 弥渡县| 镇雄县| 墨竹工卡县| 吉首市| 湘潭市| 习水县| 老河口市| 武平县| 宣恩县| 湘潭县| 南安市| 定南县| 福建省| 鲁山县| 平邑县| 黄浦区| 左权县| 新竹市| 宜君县| 铁力市| 西城区| 汉源县| 遂昌县| 本溪| 富平县| 舒兰市| 贵南县| 新田县| 九台市| 胶州市| 绥江县| 霍城县| 湘乡市| 岗巴县| 乡宁县| 仪陇县| 库尔勒市| 周口市| 徐闻县|