一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|

服務器之家 - 編程語言 - JAVA教程 - 淺談springmvc 通過異常增強返回給客戶端統一格式

淺談springmvc 通過異常增強返回給客戶端統一格式

2020-09-26 21:27nosqlcoco JAVA教程

這篇文章主要介紹了淺談springmvc 通過異常增強返回給客戶端統一格式。具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

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

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

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

配置applicationContext-mvc.xml:

?
1
2
3
4
5
6
7
<!-- 使用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發生的異常-->
  <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" />
</context:component-scan>

全局異常處理類:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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);
  }
  //數組越界異常
  @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格式返回客戶端數據。我們也可以自定義異常類(這里我把它叫做MyException)并且繼承RunTimeException,并且在全局異常處理類新增一個方法來處理異常,使用@ExceptionHandler(MyException.class)注解在方法上實現自定義異常增強。

格式化response數據類ReturnFormat:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
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;
//格式化返回客戶端數據格式(json)
public class ReturnFormat {
  private static Map<String,String>messageMap = Maps.newHashMap();
  //初始化狀態碼與文字說明
  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", "[服務器]數據類型轉換異常");
    messageMap.put("1003", "[服務器]IO異常");
    messageMap.put("1004", "[服務器]未知方法異常");
    messageMap.put("1005", "[服務器]數組越界異常");
    messageMap.put("1006", "[服務器]網絡異常");
    messageMap.put("1010", "用戶未注冊");
    messageMap.put("1011", "用戶已注冊");
    messageMap.put("1012", "用戶名或密碼錯誤");
    messageMap.put("1013", "用戶帳號凍結");
    messageMap.put("1014", "用戶信息編輯失敗");
    messageMap.put("1015", "用戶信息失效,請重新獲取");
    messageMap.put("1020", "驗證碼發送失敗");
    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", "缺少參數或值為空");
    
    messageMap.put("2029", "參數不合法");
    messageMap.put("2020", "無效的Token");
    messageMap.put("2021", "無操作權限");
    messageMap.put("2022", "RSA解密失敗,密文數據已損壞");
    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:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.drskj.apiservice.common.utils;
import java.io.Serializable;
import com.alibaba.fastjson.JSON;
public class OutputJson implements Serializable{
  /**
   * 返回客戶端統一格式,包括狀態碼,提示信息,以及業務數據
   */
  private static final long serialVersionUID = 1L;
  //狀態碼
  private int status;
  //必要的提示信息
  private String message;
  //業務數據
  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層發送短信驗證碼;

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

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

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

.....

大部分的請求異常,springmvc已經為我們定義好了,為我們開發restful應用提高了測試效率,方便排查問題出在哪一環節。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@RestController@RequestMapping("/api/v1/code")
public class CodeController extends BaseController {
  @Autowired
  private CodeService codeService;
  
  /**
   * 發送短信
   * @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);
  }
}
?
1
2
3
4
5
public abstract class BaseController {
  protected String retContent(int status,Object data) {
    return ReturnFormat.retParam(status, data);
  }
}

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

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

原文鏈接:https://www.cnblogs.com/nosqlcoco/p/5562107.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 99影视在线视频免费观看 | 精品亚洲欧美中文字幕在线看 | 国产精品免费小视频 | 欧美性野久久久久久久久 | 秋霞理论一级在线观看手机版 | 热99这里只有精品 | 我要看免费毛片 | 别停好爽好深好大好舒服视频 | 国产亚洲精品一区久久 | 欧美日韩精品免费一区二区三区 | 亚洲欧美综合在线观看 | 99re热精品这里精品 | 国内精品久久久久久中文字幕 | 太紧太深了受不了黑人 | 国产精亚洲视频 | 白丝萝莉h| 国产精品suv一区二区 | 国产麻豆精品视频 | 999任你躁在线精品免费不卡 | 国产精品亚洲片在线不卡 | 日产精品一卡2卡三卡4乱码久久 | 色婷丁香| 国产精品日韩欧美一区二区 | 亚洲高清一区二区三区四区 | 97超pen个人视频公开视频视 | 欧美成人精品第一区二区三区 | 国产成人精品一区二区阿娇陈冠希 | 女老板用丝袜脚夹我好爽 | 精品久久99麻豆蜜桃666 | 秋霞一级黄色片 | 精品一区二区三区高清免费不卡 | 日韩欧美亚洲一区精选 | 天天色综合三 | 国产99精品 | 国产美女做爰免费视频网址 | 美女的隐私视频免费看软件 | 手机看片自拍 | 国产在线视频欧美亚综合 | 99热久久国产精品这里 | 教室眠催白丝美女校花 | vod国产成人精品视频 |