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

Springboot項目異常處理及返回結(jié)果統(tǒng)一

 更新時間:2022年08月08日 10:34:18   作者:夢想實現(xiàn)家_Z  
這篇文章主要介紹了Springboot項目異常處理及返回結(jié)果統(tǒng)一,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下

背景

在創(chuàng)建項目的初期,我們需要規(guī)范后端返回的數(shù)據(jù)結(jié)構(gòu),以便更好地與前端開發(fā)人員合作。

比如后端返回的數(shù)據(jù)為:

{
 ?"msg": "請?zhí)D(zhuǎn)登陸頁面",
}

此時前端無法確定后端服務(wù)的處理結(jié)果是成功的還是失敗的。在前端展示頁面,成功與失敗的展示是要作區(qū)分的,甚至不同的成功或失敗結(jié)果要做出不同的展現(xiàn)效果,這也就是我們?yōu)槭裁匆獙Ψ祷亟Y(jié)果做出統(tǒng)一規(guī)范的原因。

返回結(jié)果定義

public class ResultWrap<T, M> {
  //  方便前端判斷當(dāng)前請求處理結(jié)果是否正常
  private int code;
  //  業(yè)務(wù)處理結(jié)果
  private T data;
  //  產(chǎn)生錯誤的情況下,提示用戶信息
  private String message;
  //  產(chǎn)生錯誤情況下的異常堆棧,提示開發(fā)人員
  private String error;
  //  發(fā)生錯誤的時候,返回的附加信息
  private M metaInfo;
}
  • 1.為了把模糊的消息定性,我們給所有的返回結(jié)果都帶上一個code字段,前端可以根據(jù)這個字段來判斷我們的處理結(jié)果到底是成功的還是失敗的;比如code=200的時候,我們的處理結(jié)果一定是成功的,其他的code值全都是失敗的,并且我們會有多種code值,以便前端頁面可以根據(jù)不同的code值做出不同的交互動作。
  • 2.一般在處理成功的情況下,后端會返回一些業(yè)務(wù)數(shù)據(jù),比如返回訂單列表等,那么這些數(shù)據(jù)我們就放在字段data里面,只有業(yè)務(wù)邏輯處理成功的情況下,data字段里面才可能有數(shù)據(jù)。
  • 3.如若我們的處理失敗了,那么我們應(yīng)該會有對應(yīng)的消息提醒用戶為什么處理失敗了。比如文件上傳失敗了,用戶名或密碼錯誤等等,都是需要告知用戶的。
  • 4.除了需要告知用戶失敗原因,我們也需要保留一個字段給開發(fā)人員,當(dāng)錯誤是服務(wù)器內(nèi)部錯誤的時候,我們需要讓開發(fā)人員能第一時間定位是啥原因引起的,我們會把錯誤的堆棧信息給到error字段。
  • 5.當(dāng)發(fā)生異常的時候,我們還會需要返回一些額外的補充數(shù)據(jù)給前端,比如用戶登陸失敗一次和失敗多次需要不同的交互效果,此時我們會在metaInfo里面返回登陸失敗次數(shù);或者在用戶操作沒有權(quán)限的時候,根據(jù)用戶是否已登陸來確定此時是跳轉(zhuǎn)登陸頁面還是直接彈窗提示當(dāng)前操作沒有權(quán)限。

定義好返回結(jié)果后,我們和前端的交互數(shù)據(jù)結(jié)果就統(tǒng)一好了。

異常的定義

之所以定義一個統(tǒng)一的異常類,是為了把所有的異常全部匯總成一個異常,最終我們只需要在異常處理的時候單獨處理這一個異常即可。

@Data
public class AwesomeException extends Throwable {
 ?// 錯誤碼
  private int code;
 ?// 提示消息
  private String msg;
?
  public AwesomeException(int code, String msg, Exception e) {
    super(e);
    this.code = code;
    this.msg = msg;
  }
?
  public AwesomeException(int code, String msg) {
    this.code = code;
    this.msg = msg;
  }
}
  • 1.我們同樣需要一個與返回結(jié)果一致的code字段,這樣的話,我們在異常處理的時候,才能把當(dāng)前異常轉(zhuǎn)換成最終的ResultWrap結(jié)果。
  • 2.msg就是在產(chǎn)生異常的時候,需要給到用戶的提示消息。

這樣的話,我們的后端開發(fā)人員遇到異常的情況,只需要通過創(chuàng)建AwesomeException異常對象拋出即可,不需要再為創(chuàng)建什么異常而煩惱了。

異常的處理

我們下面需要針對所有拋出的異常進(jìn)行統(tǒng)一的處理:

import com.example.awesomespring.exception.AwesomeException;
import com.example.awesomespring.vo.ResultWrap;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
?
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
 * @className ExceptionHandler
 * @description:
 */
@Slf4j
@RestControllerAdvice
public class AwesomeExceptionHandler {
  /**
   * 捕獲沒有用戶權(quán)限的異常
   *
   * @return
   */
  @ExceptionHandler(AuthorizationException.class)
  public ResultWrap handleException(AuthorizationException e) {
    return ResultWrap.failure(401, "您暫時沒有訪問權(quán)限!", e);
  }
?
  /**
   * 處理AwesomeException
   *
   * @param e
   * @param request
   * @param response
   * @return
   */
  @ExceptionHandler(AwesomeException.class)
  public ResultWrap handleAwesomeException(AwesomeException e, HttpServletRequest request, HttpServletResponse response) {
    return ResultWrap.failure(e);
  }
?
  /**
   * 專門針對運行時異常
   *
   * @param e
   * @return
   */
  @ExceptionHandler(RuntimeException.class)
  public ResultWrap handleRuntimeException(RuntimeException e) {
    return ResultWrap.failure(e);
  }
}

在項目中,我們集成了shiro權(quán)限管理框架,因為它拋出的異常沒有被我們的AwesomeException包裝,所以這個AuthorizationException異常需要我們單獨處理。

AwesomeException是我們大多數(shù)業(yè)務(wù)邏輯拋出來的異常,我們根據(jù)AwesomeException里面的code、msg和它包裝的cause,封裝成一個最終的響應(yīng)數(shù)據(jù)ResultWrap。

另一個RuntimeException是必須要額外處理的,任何開發(fā)人員都無法保證自己的代碼是完全沒有bug的,任何的空指針異常都會影響用戶體驗,這種編碼性的錯誤我們需要通過統(tǒng)一的錯誤處理讓它變得更柔和一點。

返回結(jié)果的處理

我們需要針對所有的返回結(jié)果進(jìn)行檢查,如果不是ResultWrap類型的返回數(shù)據(jù),我們需要包裝一下,以便保證我們和前端開發(fā)人員達(dá)成的共識。

import com.example.awesomespring.vo.ResultWrap;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.util.Objects;
?
/**
 * @className AwesomeResponseAdvice
 * @description:
 */
@RestControllerAdvice
public class AwesomeResponseAdvice implements ResponseBodyAdvice {
  @Override
  public boolean supports(MethodParameter returnType, Class converterType) {
 ? ?// 如果返回String,那么就不包裝了。
    if (StringHttpMessageConverter.class.isAssignableFrom(converterType)) {
      return false;
    }
 ? ?// 有一些情況是不需要包裝的,比如調(diào)用第三方API返回的數(shù)據(jù),所以我們做了一個自定義注解來避免所以的結(jié)果都被包裝成ResultWrap。
    boolean ignore = false;
    IgnoreResponseAdvice ignoreResponseAdvice =
        returnType.getMethodAnnotation(IgnoreResponseAdvice.class);
 ? ?// 如果我們在方法上添加了IgnoreResponseAdvice注解,那么就不要攔截包裝了
    if (Objects.nonNull(ignoreResponseAdvice)) {
      ignore = ignoreResponseAdvice.value();
      return !ignore;
    }
 ? ?// 如果我們在類上面添加了IgnoreResponseAdvice注解,也在方法上面添加了IgnoreResponseAdvice注解,那么以方法上的注解為準(zhǔn)。
    Class<?> clazz = returnType.getDeclaringClass();
    ignoreResponseAdvice = clazz.getDeclaredAnnotation(IgnoreResponseAdvice.class);
    RestController restController = clazz.getDeclaredAnnotation(RestController.class);
    if (Objects.nonNull(ignoreResponseAdvice)) {
      ignore = ignoreResponseAdvice.value();
    } else if (Objects.isNull(restController)) {
      ignore = true;
    }
    return !ignore;
  }
?
  @Override
  public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
 ? ?// 如果返回結(jié)果為null,那么我們直接返回ResultWrap.success()
    if (Objects.isNull(body)) {
      return ResultWrap.success();
    }
 ? ?// // 如果返回結(jié)果已經(jīng)是ResultWrap,直接返回
    if (body instanceof ResultWrap) {
      return body;
    }
 ? ?// 否則我們把返回結(jié)果包裝成ResultWrap
    return ResultWrap.success(body);
  }
}
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
?
/**
 * @className IgnoreResponseAdvice
 * @description:
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreResponseAdvice {
 ?// 是否忽略ResponseAdvice;決定了是否要包裝返回數(shù)據(jù)
  boolean value() default true;
}

至此,我們把整個異常處理與返回結(jié)果的統(tǒng)一處理全部關(guān)聯(lián)起來了,我們后端的開發(fā)人員無論是返回異常還是返回ResultWrap或者其他數(shù)據(jù)結(jié)果,都能很好地保證與前端開發(fā)人員的正常協(xié)作,不必為數(shù)據(jù)結(jié)構(gòu)的變化過多地溝通。

完整代碼

ResultWrap.java

import com.example.awesomespring.exception.AwesomeException;
import com.example.awesomespring.util.JsonUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpStatus;
?
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Objects;
?
/**
 * @className ResultWrap
 * @description:
 */
@Data
@AllArgsConstructor
public class ResultWrap<T, M> {
  //  方便前端判斷當(dāng)前請求處理結(jié)果是否正常
  private int code;
  //  業(yè)務(wù)處理結(jié)果
  private T data;
  //  產(chǎn)生錯誤的情況下,提示用戶信息
  private String message;
  //  產(chǎn)生錯誤情況下的異常堆棧,提示開發(fā)人員
  private String error;
  //  發(fā)生錯誤的時候,返回的附加信息
  private M metaInfo;
?
  /**
   * 成功帶處理結(jié)果
   *
   * @param data
   * @param <T>
   * @return
   */
  public static <T> ResultWrap success(T data) {
    return new ResultWrap(HttpStatus.OK.value(), data, StringUtils.EMPTY, StringUtils.EMPTY, null);
  }
?
  /**
   * 成功不帶處理結(jié)果
   *
   * @return
   */
  public static ResultWrap success() {
    return success(HttpStatus.OK.name());
  }
?
  /**
   * 失敗
   *
   * @param code
   * @param message
   * @param error
   * @return
   */
  public static <M> ResultWrap failure(int code, String message, String error, M metaInfo) {
    return new ResultWrap(code, null, message, error, metaInfo);
  }
?
  /**
   * 失敗
   *
   * @param code
   * @param message
   * @param error
   * @param metaInfo
   * @param <M>
   * @return
   */
  public static <M> ResultWrap failure(int code, String message, Throwable error, M metaInfo) {
    String errorMessage = StringUtils.EMPTY;
    if (Objects.nonNull(error)) {
      errorMessage = toStackTrace(error);
    }
    return failure(code, message, errorMessage, metaInfo);
  }
?
  /**
   * 失敗
   *
   * @param code
   * @param message
   * @param error
   * @return
   */
  public static ResultWrap failure(int code, String message, Throwable error) {
    return failure(code, message, error, null);
  }
?
  /**
   * 失敗
   *
   * @param code
   * @param message
   * @param metaInfo
   * @param <M>
   * @return
   */
  public static <M> ResultWrap failure(int code, String message, M metaInfo) {
    return failure(code, message, StringUtils.EMPTY, metaInfo);
  }
?
  /**
   * 失敗
   *
   * @param e
   * @return
   */
  public static ResultWrap failure(AwesomeException e) {
    return failure(e.getCode(), e.getMsg(), e.getCause());
  }
?
?
  /**
   * 失敗
   *
   * @param e
   * @return
   */
  public static ResultWrap failure(RuntimeException e) {
    return failure(500, "服務(wù)異常,請稍后訪問!", e.getCause());
  }
?
  private static final String APPLICATION_JSON_VALUE = "application/json;charset=UTF-8";
?
  /**
   * 把結(jié)果寫入響應(yīng)中
   *
   * @param response
   */
  public void writeToResponse(HttpServletResponse response) {
    int code = this.getCode();
    if (Objects.isNull(HttpStatus.resolve(code))) {
      response.setStatus(HttpStatus.OK.value());
    } else {
      response.setStatus(code);
    }
    response.setContentType(APPLICATION_JSON_VALUE);
    try (PrintWriter writer = response.getWriter()) {
      writer.write(JsonUtil.obj2String(this));
      writer.flush();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
?
  /**
   * 獲取異常堆棧信息
   *
   * @param e
   * @return
   */
  private static String toStackTrace(Throwable e) {
    if (Objects.isNull(e)) {
      return StringUtils.EMPTY;
    }
    StringWriter sw = new StringWriter();
    PrintWriter pw = new PrintWriter(sw);
    try {
      e.printStackTrace(pw);
      return sw.toString();
    } catch (Exception e1) {
      return StringUtils.EMPTY;
    }
  }
}

AwesomeException.java

?import lombok.Data;
?
/**
 * @className AwesomeException
 * @description:
 */
@Data
public class AwesomeException extends Throwable {
?
  private int code;
  private String msg;
  public AwesomeException(int code, String msg, Exception e) {
    super(e);
    this.code = code;
    this.msg = msg;
  }
  public AwesomeException(int code, String msg) {
    this.code = code;
    this.msg = msg;
  }
}

AwesomeExceptionHandler.java

import com.example.awesomespring.exception.AwesomeException;
import com.example.awesomespring.vo.ResultWrap;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authz.AuthorizationException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
?
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
?
/**
 * @className ExceptionHandler
 * @description:
 */
@Slf4j
@RestControllerAdvice
public class AwesomeExceptionHandler {
  /**
   * 捕獲沒有用戶權(quán)限的異常
   *
   * @return
   */
  @ExceptionHandler(AuthorizationException.class)
  public ResultWrap handleException(AuthorizationException e) {
    return ResultWrap.failure(401, "您暫時沒有訪問權(quán)限!", e);
  }
?
  /**
   * 處理AwesomeException
   *
   * @param e
   * @param request
   * @param response
   * @return
   */
  @ExceptionHandler(AwesomeException.class)
  public ResultWrap handleAwesomeException(AwesomeException e, HttpServletRequest request, HttpServletResponse response) {
    return ResultWrap.failure(e);
  }
?
  /**
   * 專門針對運行時異常
   *
   * @param e
   * @return
   */
  @ExceptionHandler(RuntimeException.class)
  public ResultWrap handleRuntimeException(RuntimeException e) {
    return ResultWrap.failure(e);
  }
}

IgnoreResponseAdvice.java

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
?
/**
 * @className IgnoreResponseAdvice
 * @description:
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface IgnoreResponseAdvice {
?
  boolean value() default true;
}

AwesomeResponseAdvice.java

import com.example.awesomespring.vo.ResultWrap;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
?
import java.util.Objects;
?
/**
 * @className AwesomeResponseAdvice
 * @description:
 */
@RestControllerAdvice
public class AwesomeResponseAdvice implements ResponseBodyAdvice {
  @Override
  public boolean supports(MethodParameter returnType, Class converterType) {
    if (StringHttpMessageConverter.class.isAssignableFrom(converterType)) {
      return false;
    }
    boolean ignore = false;
    IgnoreResponseAdvice ignoreResponseAdvice =
        returnType.getMethodAnnotation(IgnoreResponseAdvice.class);
    if (Objects.nonNull(ignoreResponseAdvice)) {
      ignore = ignoreResponseAdvice.value();
      return !ignore;
    }
    Class<?> clazz = returnType.getDeclaringClass();
    ignoreResponseAdvice = clazz.getDeclaredAnnotation(IgnoreResponseAdvice.class);
    RestController restController = clazz.getDeclaredAnnotation(RestController.class);
    if (Objects.nonNull(ignoreResponseAdvice)) {
      ignore = ignoreResponseAdvice.value();
    } else if (Objects.isNull(restController)) {
      ignore = true;
    }
    return !ignore;
  }
?
  @Override
  public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    if (Objects.isNull(body)) {
      return ResultWrap.success();
    }
    if (body instanceof ResultWrap) {
      return body;
    }
    return ResultWrap.success(body);
  }
}

使用示例

// 這里只要返回AwesomeException,就會被ExceptionHandler處理掉,包裝成ResultWrap
@PostMapping("/image/upload")
String upload(@RequestPart("userImage") MultipartFile userImage) throws AwesomeException {
    fileService.putObject("video", userImage);
    return "success";
}
?
// 加上IgnoreResponseAdvice注解,該返回結(jié)果就不會被包裝
@IgnoreResponseAdvice
@GetMapping("/read")
Boolean read() {
    return true;
}

到此這篇關(guān)于Springboot項目異常處理及返回結(jié)果統(tǒng)一的文章就介紹到這了,更多相關(guān)Springboot異常處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java實現(xiàn)經(jīng)典游戲泡泡堂的示例代碼

    Java實現(xiàn)經(jīng)典游戲泡泡堂的示例代碼

    這篇文章將利用Java制作經(jīng)典游戲——泡泡堂,游戲設(shè)計為雙人pk積分賽模式,在這個模式里面,玩家只要率先達(dá)到一定分?jǐn)?shù)既可以贏得比賽。感興趣的可以了解一下
    2022-04-04
  • Spring Boot使用Log4j2的實例代碼

    Spring Boot使用Log4j2的實例代碼

    這篇文章主要介紹了Spring Boot使用Log4j2的實例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-07-07
  • springmvc分層領(lǐng)域模型概念詳解

    springmvc分層領(lǐng)域模型概念詳解

    本文核心為分層領(lǐng)域模型(VO , PO , BO, DAO ,POJO等)概念的個人理解,結(jié)合springmvc淺談分層領(lǐng)域模型的相關(guān)知識,感興趣的朋友跟隨小編一起看看吧
    2021-08-08
  • SpringBoot中配置多數(shù)據(jù)源的方法詳解

    SpringBoot中配置多數(shù)據(jù)源的方法詳解

    這篇文章主要為大家詳細(xì)介紹了SpringBoot中配置多數(shù)據(jù)源的方法的相關(guān)知識,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02
  • Java中的封裝、繼承和多態(tài),你真的都懂了嗎

    Java中的封裝、繼承和多態(tài),你真的都懂了嗎

    Java中的封裝、繼承和多態(tài)知識點是學(xué)習(xí)java必備的基礎(chǔ)知識,看似簡單,真正理解起來還是有一定難度的,今天小編再次通過實例代碼給大家講解java 封裝繼承多態(tài)知識,感興趣的朋友一起學(xué)習(xí)下吧
    2021-05-05
  • SpringData Repository Bean方法定義規(guī)范代碼實例

    SpringData Repository Bean方法定義規(guī)范代碼實例

    這篇文章主要介紹了SpringData Repository Bean方法定義規(guī)范代碼實例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-08-08
  • Java中操作Xml使用方法備忘錄(Hutool工具類XmlUtil、XStream)

    Java中操作Xml使用方法備忘錄(Hutool工具類XmlUtil、XStream)

    這篇文章主要給大家介紹了關(guān)于Java中操作Xml使用方法(Hutool工具類XmlUtil、XStream)的相關(guān)資料,XMLUtil是一個工具類,主要用于讀取XML配置文件并提供相應(yīng)的操作方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • Spring Boot集成Thymeleaf的方法

    Spring Boot集成Thymeleaf的方法

    這篇文章主要介紹了Spring Boot集成Thymeleaf的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-10-10
  • 關(guān)于Maven混合配置私有倉庫和公共倉庫的問題

    關(guān)于Maven混合配置私有倉庫和公共倉庫的問題

    這篇文章主要介紹了Maven混合配置私有倉庫和公共倉庫,通過實例代碼詳細(xì)介紹了私有和公共倉庫混合配置的方法,需要的朋友可以參考下
    2022-06-06
  • Java如何獲取一個IP段內(nèi)的所有IP地址

    Java如何獲取一個IP段內(nèi)的所有IP地址

    這篇文章主要為大家詳細(xì)介紹了Java如何根據(jù)起始和結(jié)束的IP地址獲取IP段內(nèi)所有IP地址,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-11-11

最新評論

河曲县| 高淳县| 当雄县| 德保县| 天全县| 崇信县| 漳州市| 信丰县| 樟树市| 铜鼓县| 铁岭县| 东乡族自治县| 五原县| 仙居县| 拜泉县| 昂仁县| 泾源县| 五寨县| 吉木萨尔县| 灌阳县| 乌海市| 栾川县| 长春市| 麻江县| 文登市| 韶山市| 大理市| 陆河县| 三穗县| 益阳市| 赣榆县| 赞皇县| 广西| 平昌县| 大冶市| 买车| 布尔津县| 莒南县| 石台县| 莆田市| 仲巴县|