欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

springboot統(tǒng)一接口返回數(shù)據(jù)的實(shí)現(xiàn)

 更新時間:2020年09月15日 10:31:22   作者:liangshui999  
這篇文章主要介紹了springboot統(tǒng)一接口返回數(shù)據(jù)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

一,沒有異常的情況,正常返回數(shù)據(jù)

希望接口統(tǒng)一返回的數(shù)據(jù)格式如下:

{
  "status": 0,
  "msg": "成功",
  "data": null
}

和接口數(shù)據(jù)對應(yīng)的bean

/**
 * 統(tǒng)一返回結(jié)果的實(shí)體
 * @param <T>
 */
public class Result<T> implements Serializable {

  private static final long serialVersionUID = 1L;

  /**
   * 錯誤碼
   */
  private int status;

  /**
   * 提示消息
   */
  private String msg;

  /**
   * 返回的數(shù)據(jù)體
   */
  private T data;

  public int getStatus() {
    return status;
  }

  public void setStatus(int status) {
    this.status = status;
  }

  public String getMsg() {
    return msg;
  }

  public void setMsg(String msg) {
    this.msg = msg;
  }

  public T getData() {
    return data;
  }

  public void setData(T data) {
    this.data = data;
  }
}

操作Result實(shí)體的工具類

/**
 * 生成result的工具類,避免重復(fù)代碼
 */
public class ResultUtils {

  /**
   * 成功時生成result的方法,有返回數(shù)據(jù)
   */
  public static <T> Result<T> success(T t){
    Result<T> result = new Result<>();
    result.setStatus(ResultEnum.SUCCESS.getCode());
    result.setMsg(ResultEnum.SUCCESS.getMsg());
    result.setData(t);
    return result;
  }

  /**
   * 成功時生成result的方法,無返回數(shù)據(jù)
   */
  public static <T> Result<T> success(){
    return success(null);
  }

  /**
   * 失敗時生成result的方法
   */
  public static <T> Result<T> error(int status, String msg){
    Result<T> result = new Result<>();
    result.setStatus(status);
    result.setMsg(msg);
    return result;
  }
}

封裝錯誤碼和錯誤消息的枚舉類

/**
 * 所有返回結(jié)果的枚舉
 */
public enum ResultEnum {

  UNKNOWN_ERROR(-1, "未知錯誤"),
  SUCCESS(0, "成功"),
  BASIC_INFO_ID_IS_EMPTY(600, "基本信息中BasicInfoId為空"),
  BASIC_INFO_ADD_TO_DATABASE_FAILURE(601, "向數(shù)據(jù)庫添加基本信息失敗"),
  DETAILS_DATA_BASIC_INFO_ID_IS_EMPTY(602, "測試數(shù)據(jù)中BasicInfoId為空"),
  DETAILS_DATA_ADD_TO_DATABASE_FAILURE(603, "向數(shù)據(jù)庫添加測試數(shù)據(jù)失敗");

  ResultEnum(int code, String msg) {
    this.code = code;
    this.msg = msg;
  }

  private int code;

  private String msg;

  public int getCode() {
    return code;
  }

  public void setCode(int code) {
    this.code = code;
  }

  public String getMsg() {
    return msg;
  }

  public void setMsg(String msg) {
    this.msg = msg;
  }

  @Override
  public String toString() {
    return "ResultEnum{" +
        "code=" + code +
        ", msg='" + msg + '\'' +
        '}';
  }
}

統(tǒng)一封裝返回結(jié)果的切面

之所以需要這個切面,是為了避免每個Controller方法中都要調(diào)用ResultUtils.success()。有了這個切面,Controller可以和原來一樣正常返回對象,字符串,void,在切面里面將結(jié)果封裝成Result實(shí)體,而不需要每個Controller方法都返回Result實(shí)體。

/**
 * 統(tǒng)一處理返回結(jié)果的切面,避免每個controller方法里面都要調(diào)用ResultUtils.success()這句話
 * 統(tǒng)一在這個切面里面調(diào)用
 */
@ControllerAdvice
public class MyResponseAdvice implements ResponseBodyAdvice<Object> {

  @Autowired
  private ObjectMapper objectMapper;

  /**
   * Whether this component supports the given controller method return type
   * and the selected {@code HttpMessageConverter} type.
   *
   * @param returnType  the return type
   * @param converterType the selected converter type
   * @return {@code true} if {@link #beforeBodyWrite} should be invoked;
   * {@code false} otherwise
   */
  @Override
  public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
    return true;
  }

  /**
   * Invoked after an {@code HttpMessageConverter} is selected and just before
   * its write method is invoked.
   *
   * @param body         the body to be written
   * @param returnType      the return type of the controller method
   * @param selectedContentType  the content type selected through content negotiation
   * @param selectedConverterType the converter type selected to write to the response
   * @param request        the current request
   * @param response       the current response
   * @return the body that was passed in or a modified (possibly new) instance
   */
  @Override
  public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
    if(body instanceof Result){ //發(fā)生異常之后,異常處理器里面返回的已經(jīng)是Result了
      return body;
    }else if(body instanceof String){ //String屬于特殊情況,需要單獨(dú)處理,否則會報錯
      try {
        return objectMapper.writeValueAsString(ResultUtils.success(body));
      } catch (JsonProcessingException e) {
        e.printStackTrace();
        return ResultUtils.error(ResultEnum.UNKNOWN_ERROR.getCode(), e.getMessage());
      }
    }
    return ResultUtils.success(body);
  }
}

二,有異常的情況下

    service層為了自動回滾事務(wù),會拋出一些自定義的RuntimeException。默認(rèn)情況下,只有RuntimeException才會回滾事務(wù)。如果Controller里面直接處理service層拋出的異常,則Controller里面到處都是try catch塊,代碼會很難看。將異常集中在一個地方處理會好很多。

    springboot中是通過@ControllerAdvice和@ExceptionHandler來完成統(tǒng)一異常處理的。這2個注解只能處理Controller和攔截器中拋出的異常,其他地方拋出的異常(比如Filter中拋出的異常),無法捕獲。其他地方拋出的異常會轉(zhuǎn)到/error的Controller方法來處理,默認(rèn)是BasicErrorController來處理,為了能處理其他地方拋出的異常,我們會自定義ErrorController。

統(tǒng)一的異常處理類,處理Controller和攔截器拋出的異常

/**
 * 統(tǒng)一的異常處理類
 */
@ControllerAdvice
public class MyExceptionHandler {

  /**
   * 轉(zhuǎn)發(fā)到/error,表示由BasicErrorController處理,
   * BasicErrorController是由springboot自動裝配到容器中的
   */
  /*@ExceptionHandler(BasicInfoException.class)
  public String handleException(Exception ex, HttpServletRequest request){
    request.setAttribute("javax.servlet.error.status_code", 401);
    request.setAttribute("exMsg", ex.getMessage());
    return "forward:/error";
  }*/


  /**
   * 處理基本信息相關(guān)的異常
   */
  @ExceptionHandler(BasicInfoException.class)
  @ResponseBody
  public Result handleBasicInfoException(BasicInfoException ex){
    return ResultUtils.error(ex.getCode(), ex.getMessage());
  }

  /**
   * 處理測試數(shù)據(jù)相關(guān)的異常
   */
  @ExceptionHandler(DetailsDataException.class)
  @ResponseBody
  public Result handleDetailsDataException(DetailsDataException ex){
    return ResultUtils.error(ex.getCode(), ex.getMessage());
  }


  /**
   * 處理未知異常
   */
  @ExceptionHandler(Exception.class)
  @ResponseBody
  public Result handleUnKnowException(Exception ex){
    return ResultUtils.error(ResultEnum.UNKNOWN_ERROR.getCode(), ex.getMessage());
  }

}

自定義的異常類示例

public class BasicInfoException extends RuntimeException {

  private int code;

  public BasicInfoException(int code, String msg){
    super(msg);
    this.code = code;
  }

  public int getCode() {
    return code;
  }
}

處理其他地方拋出的異常(不是Controller和攔截器拋出的異常),自定義ErrorController

/**
 * 自定義ErrorController,處理其他地方拋出的異常(不是Controller和攔截器拋出的異常)
 */
@Controller
public class MyBasicErrorController extends AbstractErrorController {

  private Logger logger = LoggerFactory.getLogger(this.getClass());

  /**
   * 可以通過@Value獲取到
   */
  @Value("${server.error.path}")
  private String myPath;

  private final ErrorProperties errorProperties;

  private ErrorAttributes mErrorAttributes;

  public MyBasicErrorController(ErrorAttributes errorAttributes, ServerProperties serverProperties) {
    super(errorAttributes);
    this.errorProperties = serverProperties.getError();
    this.mErrorAttributes = errorAttributes;
  }

  //@RequestMapping(value = "/error")
  @RequestMapping("${server.error.path}") //從properties文件中獲取
  @ResponseBody
  public Result<Object> error(HttpServletRequest request) throws Throwable {
    logger.debug("myPath = " + myPath);

    //發(fā)生錯誤之后直接將異常拋出去,異常會到統(tǒng)一異常處理器中處理
    WebRequest webRequest = new ServletWebRequest(request);
    Throwable throwable = this.mErrorAttributes.getError(webRequest).getCause();
    throw throwable;
    /*UserException ex;
    if(throwable instanceof UserException){
      ex = (UserException) throwable;
      throw ex;
    }else{
      throw throwable;
    }*/
    /*HttpStatus status = getStatus(request);
    if (status == HttpStatus.NO_CONTENT) {
      return ResultUtils.error(status.value(), status.name());
    }
    Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
    return ResultUtils.error((Integer) body.get("status"), (String)body.get("message"));*/
  }

  /**
   * Determine if the stacktrace attribute should be included.
   * @param request the source request
   * @param produces the media type produced (or {@code MediaType.ALL})
   * @return if the stacktrace attribute should be included
   */
  private boolean isIncludeStackTrace(HttpServletRequest request, MediaType produces) {
    ErrorProperties.IncludeStacktrace include = getErrorProperties().getIncludeStacktrace();
    if (include == ErrorProperties.IncludeStacktrace.ALWAYS) {
      return true;
    }
    if (include == ErrorProperties.IncludeStacktrace.ON_TRACE_PARAM) {
      return getTraceParameter(request);
    }
    return false;
  }

  /**
   * Provide access to the error properties.
   * @return the error properties
   */
  private ErrorProperties getErrorProperties() {
    return this.errorProperties;
  }


  /**
   * Returns the path of the error page.
   *
   * @return the error path
   */
  @Override
  public String getErrorPath() {
    return this.errorProperties.getPath();
  }
}

自定義ErrorController中錯誤處理的方法中,也可以直接將異常拋出,這樣異常就會交給統(tǒng)一異常處理器進(jìn)行處理。

 //@RequestMapping(value = "/error")
  @RequestMapping("${server.error.path}") //從properties文件中獲取
  @ResponseBody
  public Result<Object> error(HttpServletRequest request) throws Throwable {
    logger.debug("myPath = " + myPath);

    //發(fā)生錯誤之后直接將異常拋出去,異常會到統(tǒng)一異常處理器中處理
    WebRequest webRequest = new ServletWebRequest(request);
    Throwable throwable = this.mErrorAttributes.getError(webRequest).getCause();
    UserException ex;
    if(throwable instanceof UserException){
      ex = (UserException) throwable;
      throw ex;
    }else{
      throw throwable;
    }
    /*HttpStatus status = getStatus(request);
    if (status == HttpStatus.NO_CONTENT) {
      return ResultUtils.error(status.value(), status.name());
    }
    Map<String, Object> body = getErrorAttributes(request, isIncludeStackTrace(request, MediaType.ALL));
    return ResultUtils.error((Integer) body.get("status"), (String)body.get("message"));*/
  }

到此這篇關(guān)于springboot統(tǒng)一接口返回數(shù)據(jù)的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)springboot統(tǒng)一接口返回數(shù)據(jù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 如何基于java或js獲取URL返回狀態(tài)碼

    如何基于java或js獲取URL返回狀態(tài)碼

    這篇文章主要介紹了如何基于java或js獲取URL返回狀態(tài)碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • springboot使用CommandLineRunner解決項(xiàng)目啟動時初始化資源的操作

    springboot使用CommandLineRunner解決項(xiàng)目啟動時初始化資源的操作

    這篇文章主要介紹了springboot使用CommandLineRunner解決項(xiàng)目啟動時初始化資源的操作,幫助大家更好的理解和學(xué)習(xí)使用springboot框架,感興趣的朋友可以了解下
    2021-02-02
  • idea使用Vim的技巧大全分享

    idea使用Vim的技巧大全分享

    vim是一個高度可配置的文本編輯器,非常穩(wěn)定,可以高效的創(chuàng)建任何文本、持久的、多級撤銷樹、支持?jǐn)?shù)百種變成語言和格式、與許多工具集成,本文給大家分享了idea使用Vim的技巧大全,需要的朋友可以參考下
    2024-05-05
  • springboot中縮短一個url鏈接的實(shí)現(xiàn)

    springboot中縮短一個url鏈接的實(shí)現(xiàn)

    縮短 URL 是現(xiàn)代應(yīng)用程序中常見的需求,通常用于減少長 URL 的長度,使其更易于分享,URL 縮短服務(wù)的核心思路是將長 URL 映射到一個唯一的短代碼,本文主要介紹了springboot中縮短一個url鏈接的實(shí)現(xiàn),感興趣的可以了解一下
    2024-09-09
  • FileUtils擴(kuò)展readURLtoString讀取url內(nèi)容

    FileUtils擴(kuò)展readURLtoString讀取url內(nèi)容

    這篇文章主要介紹了FileUtils擴(kuò)展readURLtoString使用其支持讀取URL內(nèi)容為String,支持帶POST傳大量參數(shù),大家參考使用吧
    2014-01-01
  • Java Socket編程(三) 服務(wù)器Sockets

    Java Socket編程(三) 服務(wù)器Sockets

    Java Socket編程(三) 服務(wù)器Sockets...
    2006-12-12
  • spring AOP實(shí)現(xiàn)@Around輸出請求參數(shù)和返回參數(shù)

    spring AOP實(shí)現(xiàn)@Around輸出請求參數(shù)和返回參數(shù)

    這篇文章主要介紹了spring AOP實(shí)現(xiàn)@Around輸出請求參數(shù)和返回參數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Protostuff序列化和反序列化的使用說明

    Protostuff序列化和反序列化的使用說明

    今天小編就為大家分享一篇關(guān)于Protostuff序列化和反序列化的使用說明,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • Java中zip文件壓縮與解壓之ZipInputStream和ZipOutputStream

    Java中zip文件壓縮與解壓之ZipInputStream和ZipOutputStream

    這篇文章主要給大家介紹了關(guān)于Java中zip文件壓縮與解壓之ZipInputStream和ZipOutputStream的相關(guān)資料,ZipInputStream 和 ZipOutputStream 可以用于處理 ZIP文件格式,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • java定義受限制的類型參數(shù)操作

    java定義受限制的類型參數(shù)操作

    這篇文章主要介紹了java定義受限制的類型參數(shù)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08

最新評論