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

淺談springmvc 通過異常增強返回給客戶端統(tǒng)一格式

 更新時間:2020年09月26日 14:34:54   作者:nosqlcoco  
這篇文章主要介紹了淺談springmvc 通過異常增強返回給客戶端統(tǒng)一格式。具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

在springmvc開發(fā)中,我們經(jīng)常遇到這樣的問題;邏輯正常執(zhí)行時返回客戶端指定格式的數(shù)據(jù),比如json,但是遇NullPointerException空指針異常,NoSuchMethodException調用的方法不存在異常,返回給客戶端的是服務端異常堆棧信息,導致客戶端不能正常解析數(shù)據(jù);這明顯不是我們想要的。

幸好從spring3.2提供的新注解@ControllerAdvice,從名字上可以看出大體意思是控制器增強。原理是使用AOP對Controller控制器進行增強(前置增強、后置增強、環(huán)繞增強,AOP原理請自行查閱);那么我沒可以自行對控制器的方法進行調用前(前置增強)和調用后(后置增強)的處理。

spring提供了@ExceptionHandler異常增強注解。程序如果在執(zhí)行控制器方法前或執(zhí)行時拋出異常,會被@ExceptionHandler注解了的方法處理。

配置applicationContext-mvc.xml:

<!-- 使用Annotation自動注冊Bean,掃描@Controller和@ControllerAdvice-->
<context:component-scan base-package="com.drskj.apiservice" use-default-filters="false">
  <!-- base-package 如果多個,用“,”分隔 -->
  <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
  <!--控制器增強,使一個Contoller成為全局的異常處理類,類中用@ExceptionHandler方法注解的方法可以處理所有Controller發(fā)生的異常-->
  <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" />
</context:component-scan>

全局異常處理類:

package com.drskj.apiservice.handler;
import java.io.IOException;
import org.springframework.beans.ConversionNotSupportedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.HttpMessageNotWritableException;
import org.springframework.web.HttpMediaTypeNotAcceptableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import com.drskj.apiservice.common.utils.ReturnFormat;
/**
 * 異常增強,以JSON的形式返回給客服端 * 異常增強類型:NullPointerException,RunTimeException,ClassCastException,         NoSuchMethodException,IOException,IndexOutOfBoundsException         以及springmvc自定義異常等,如下:SpringMVC自定義異常對應的status code 
      Exception            HTTP Status Code 
ConversionNotSupportedException     500 (Internal Server Error)
HttpMessageNotWritableException     500 (Internal Server Error)
HttpMediaTypeNotSupportedException   415 (Unsupported Media Type)
HttpMediaTypeNotAcceptableException   406 (Not Acceptable)
HttpRequestMethodNotSupportedException 405 (Method Not Allowed)
NoSuchRequestHandlingMethodException  404 (Not Found) 
TypeMismatchException          400 (Bad Request)
HttpMessageNotReadableException     400 (Bad Request)
MissingServletRequestParameterException 400 (Bad Request)
 *
 */
@ControllerAdvice
public class RestExceptionHandler{
  //運行時異常
  @ExceptionHandler(RuntimeException.class) 
  @ResponseBody 
  public String runtimeExceptionHandler(RuntimeException runtimeException) { 
    return ReturnFormat.retParam(1000, null);
  } 
  //空指針異常
  @ExceptionHandler(NullPointerException.class) 
  @ResponseBody 
  public String nullPointerExceptionHandler(NullPointerException ex) { 
    ex.printStackTrace();
    return ReturnFormat.retParam(1001, null);
  }  
  //類型轉換異常
  @ExceptionHandler(ClassCastException.class) 
  @ResponseBody 
  public String classCastExceptionHandler(ClassCastException ex) { 
    ex.printStackTrace();
    return ReturnFormat.retParam(1002, null); 
  } 
  //IO異常
  @ExceptionHandler(IOException.class) 
  @ResponseBody 
  public String iOExceptionHandler(IOException ex) { 
    ex.printStackTrace();
    return ReturnFormat.retParam(1003, null); 
  } 
  //未知方法異常
  @ExceptionHandler(NoSuchMethodException.class) 
  @ResponseBody 
  public String noSuchMethodExceptionHandler(NoSuchMethodException ex) { 
    ex.printStackTrace();
    return ReturnFormat.retParam(1004, null);
  } 
  //數(shù)組越界異常
  @ExceptionHandler(IndexOutOfBoundsException.class) 
  @ResponseBody 
  public String indexOutOfBoundsExceptionHandler(IndexOutOfBoundsException ex) { 
    ex.printStackTrace();
    return ReturnFormat.retParam(1005, null);
  }
  //400錯誤
  @ExceptionHandler({HttpMessageNotReadableException.class})
  @ResponseBody
  public String requestNotReadable(HttpMessageNotReadableException ex){
    System.out.println("400..requestNotReadable");
    ex.printStackTrace();
    return ReturnFormat.retParam(400, null);
  }
  //400錯誤
  @ExceptionHandler({TypeMismatchException.class})
  @ResponseBody
  public String requestTypeMismatch(TypeMismatchException ex){
    System.out.println("400..TypeMismatchException");
    ex.printStackTrace();
    return ReturnFormat.retParam(400, null);
  }
  //400錯誤
  @ExceptionHandler({MissingServletRequestParameterException.class})
  @ResponseBody
  public String requestMissingServletRequest(MissingServletRequestParameterException ex){
    System.out.println("400..MissingServletRequest");
    ex.printStackTrace();
    return ReturnFormat.retParam(400, null);
  }
  //405錯誤
  @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
  @ResponseBody
  public String request405(){
    System.out.println("405...");
    return ReturnFormat.retParam(405, null);
  }
  //406錯誤
  @ExceptionHandler({HttpMediaTypeNotAcceptableException.class})
  @ResponseBody
  public String request406(){
    System.out.println("404...");
    return ReturnFormat.retParam(406, null);
  }
  //500錯誤
  @ExceptionHandler({ConversionNotSupportedException.class,HttpMessageNotWritableException.class})
  @ResponseBody
  public String server500(RuntimeException runtimeException){
    System.out.println("500...");
    return ReturnFormat.retParam(406, null);
  }
}

以上包括了常見的服務端異常類型,@ResponseBody表示以json格式返回客戶端數(shù)據(jù)。我們也可以自定義異常類(這里我把它叫做MyException)并且繼承RunTimeException,并且在全局異常處理類新增一個方法來處理異常,使用@ExceptionHandler(MyException.class)注解在方法上實現(xiàn)自定義異常增強。

格式化response數(shù)據(jù)類ReturnFormat:

package com.drskj.apiservice.common.utils;
import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.fastjson.JSON;import com.google.common.collect.Maps;
//格式化返回客戶端數(shù)據(jù)格式(json)
public class ReturnFormat {
  private static Map<String,String>messageMap = Maps.newHashMap();
  //初始化狀態(tài)碼與文字說明
  static {
    messageMap.put("0", "");
    messageMap.put("400", "Bad Request!");
    messageMap.put("401", "NotAuthorization");
    messageMap.put("405", "Method Not Allowed");
    messageMap.put("406", "Not Acceptable");
    messageMap.put("500", "Internal Server Error");
    messageMap.put("1000", "[服務器]運行時異常");
    messageMap.put("1001", "[服務器]空值異常");
    messageMap.put("1002", "[服務器]數(shù)據(jù)類型轉換異常");
    messageMap.put("1003", "[服務器]IO異常");
    messageMap.put("1004", "[服務器]未知方法異常");
    messageMap.put("1005", "[服務器]數(shù)組越界異常");
    messageMap.put("1006", "[服務器]網(wǎng)絡異常");
    messageMap.put("1010", "用戶未注冊");
    messageMap.put("1011", "用戶已注冊");
    messageMap.put("1012", "用戶名或密碼錯誤");
    messageMap.put("1013", "用戶帳號凍結");
    messageMap.put("1014", "用戶信息編輯失敗");
    messageMap.put("1015", "用戶信息失效,請重新獲取");
    messageMap.put("1020", "驗證碼發(fā)送失敗");
    messageMap.put("1021", "驗證碼失效");
    messageMap.put("1022", "驗證碼錯誤");
    messageMap.put("1023", "驗證碼不可用");
    messageMap.put("1029", "短信平臺異常");
    messageMap.put("1030", "周邊無店鋪");
    messageMap.put("1031", "店鋪添加失敗");
    messageMap.put("1032", "編輯店鋪信息失敗");
    messageMap.put("1033", "每個用戶只能添加一個商鋪");
    messageMap.put("1034", "店鋪不存在");
    messageMap.put("1040", "無瀏覽商品");
    messageMap.put("1041", "添加失敗,商品種類超出上限");
    messageMap.put("1042", "商品不存在");
    messageMap.put("1043", "商品刪除失敗");
    messageMap.put("2010", "缺少參數(shù)或值為空");
    
    messageMap.put("2029", "參數(shù)不合法");
    messageMap.put("2020", "無效的Token");
    messageMap.put("2021", "無操作權限");
    messageMap.put("2022", "RSA解密失敗,密文數(shù)據(jù)已損壞");
    messageMap.put("2023", "請重新登錄");
  }
  public static String retParam(int status,Object data) {
    OutputJson json = new OutputJson(status, messageMap.get(String.valueOf(status)), data);
    return json.toString();
  }
}

返回格式實體類OutPutJson;這里用到了知名的fastjson將對象轉json:

package com.drskj.apiservice.common.utils;
import java.io.Serializable;
import com.alibaba.fastjson.JSON;
public class OutputJson implements Serializable{
  /**
   * 返回客戶端統(tǒng)一格式,包括狀態(tài)碼,提示信息,以及業(yè)務數(shù)據(jù)
   */
  private static final long serialVersionUID = 1L;
  //狀態(tài)碼
  private int status;
  //必要的提示信息
  private String message;
  //業(yè)務數(shù)據(jù)
  private Object data;
  public OutputJson(int status,String message,Object data){
    this.status = status;
    this.message = message;
    this.data = data;
  }
  public int getStatus() {
    return status;
  }
  public void setStatus(int status) {
    this.status = status;
  }
  public String getMessage() {
    return message;
  }
  public void setMessage(String message) {
    this.message = message;
  }
  public Object getData() {
    return data;
  }
  public void setData(Object data) {
    this.data = data;
  }
  public String toString(){
    if(null == this.data){
      this.setData(new Object());
    }
    return JSON.toJSONString(this);
  }
}

實例:CodeController繼承自BaseController,有一個sendMessage方法調用Service層發(fā)送短信驗證碼;

1.如果客戶端請求方式為非POST,否則拋出HttpMediaTypeNotSupportedException異常;

2.如果username、forType或userType沒傳,則拋出MissingServletRequestParameterException異常;

3.如果springmvc接收無法進行類型轉換的字段,會報TypeMismatchException異常;

.....

大部分的請求異常,springmvc已經(jīng)為我們定義好了,為我們開發(fā)restful應用提高了測試效率,方便排查問題出在哪一環(huán)節(jié)。

@RestController@RequestMapping("/api/v1/code")
public class CodeController extends BaseController {
  @Autowired
  private CodeService codeService;
  
  /**
   * 發(fā)送短信
   * @param username 用戶名
   * @param type register/backpwd
   * @return
   * status: 0 2010 2029 1011 1010 1006 1020 
   */
  @RequestMapping(value="/sendMessage",method=RequestMethod.POST,produces="application/json")
  public String sendMessage(@RequestParam(value="username",required=true)String username,
      @RequestParam(value="forType",required=true)String forType,
      @RequestParam(value="userType",required=true)String userType){
    if(null == username || "".equals(username)){
      return retContent(2010, null);
    }
    if(!"user".equals(userType) && !"merchant".equals(userType)){
      return retContent(2029, null);
    }
    if(!"register".equals(forType) && !"backpwd".equals(forType)){
      return retContent(2029, null);
    }
    return codeService.sendMessage(username, forType, userType);
  }
}
public abstract class BaseController {
  protected String retContent(int status,Object data) {
    return ReturnFormat.retParam(status, data);
  }
}

最終,不管是正常的業(yè)務邏輯還是服務端異常,都會調用ReturnFormat.retParam(int status,Object data)方法返回格式統(tǒng)一的數(shù)據(jù)。

以上這篇淺談springmvc 通過異常增強返回給客戶端統(tǒng)一格式就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關文章

  • java二維數(shù)組遍歷的2種代碼

    java二維數(shù)組遍歷的2種代碼

    這篇文章主要介紹了java二維數(shù)組遍歷的2種代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-07-07
  • 初探Java中的泛型

    初探Java中的泛型

    這篇文章主要介紹了Java中泛型的相關資料,幫助大家更好的理解和學習Java,感興趣的朋友可以了解下
    2020-08-08
  • IDEA 2020.3.X 創(chuàng)建scala環(huán)境的詳細教程

    IDEA 2020.3.X 創(chuàng)建scala環(huán)境的詳細教程

    這篇文章主要介紹了IDEA 2020.3.X 創(chuàng)建scala環(huán)境的詳細教程,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-04-04
  • 拳皇(Java簡單的小程序)代碼實例

    拳皇(Java簡單的小程序)代碼實例

    這篇文章主要介紹了拳皇Java簡單小程序,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-03-03
  • 詳解SpringBoot封裝使用JDBC

    詳解SpringBoot封裝使用JDBC

    這篇文章主要介紹了SpringBoot封裝JDBC使用教程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-12-12
  • Java實現(xiàn)圖章或簽名插在pdf的固定位置

    Java實現(xiàn)圖章或簽名插在pdf的固定位置

    使用Java技術在word轉換成pdf過程中實現(xiàn)將圖章或者簽名插入在pdf中,并生成帶圖章或者簽名的pdf,來完成某些特定場景的需求,文中有詳細的代碼示例,需要的朋友可以參考下
    2023-10-10
  • SpringBoot自動裝配原理詳解

    SpringBoot自動裝配原理詳解

    這篇文章主要介紹了SpringBoot自動裝配原理的相關資料,幫助大家更好的理解和學習使用SpringBoot框架,感興趣的朋友可以了解下
    2021-03-03
  • Java中鎖的實現(xiàn)和內存語義淺析

    Java中鎖的實現(xiàn)和內存語義淺析

    這篇文章主要給大家介紹了關于Java中鎖的實現(xiàn)和內存語義的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-11-11
  • Spring boot 數(shù)據(jù)庫連接斷線重連問題

    Spring boot 數(shù)據(jù)庫連接斷線重連問題

    這篇文章主要介紹了Spring boot 數(shù)據(jù)庫連接斷線重連問題,需要的朋友可以參考下
    2017-06-06
  • Java語言中flush()函數(shù)作用及使用方法詳解

    Java語言中flush()函數(shù)作用及使用方法詳解

    這篇文章主要介紹了Java語言中flush函數(shù)作用及使用方法詳解,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01

最新評論