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

Java?Controller實現(xiàn)參數(shù)驗證與統(tǒng)一異常處理流程詳細講解

 更新時間:2023年01月11日 09:35:09   作者:李奈?-?Leemon  
Controller是Spring接受并處理網(wǎng)頁請求的組件,是整個應用的入口,因此學會Controller的常用注解對理解一個應用是重中之重。SpringBoot的Controller中經(jīng)常會用到注解@Controller、@RestController、@RequestMapping、@RequestBody等

最近開發(fā)了比較多的接口,因為沒有可參考的案例,所以一開始一直按照我的理解進行開發(fā)。開發(fā)多了發(fā)現(xiàn)自己每個結(jié)果都寫了相同的代碼:try() {} catch() {}, 和關于參數(shù)判空的:StringUtils.empty(xxx)。開發(fā)結(jié)束后自然想下次更加優(yōu)雅的開發(fā)。因此,使用了springboot的參數(shù)驗證和統(tǒng)一異常處理。

一,前期數(shù)據(jù)及類準備

1.1 統(tǒng)一狀態(tài)碼

對于不同的返回類型,我們應該要有不同對應的狀態(tài)碼。接口的返回類型在統(tǒng)一狀態(tài)碼中必須存在。

package com.lmc.common.enums;
/**
 * @Description: TODO 接口API返回狀態(tài)碼枚舉
 * @version: 1.0
 */
public enum ResultCodeEnum {
    SUCCESS(1000, "請求成功"),
    FAILURE(1001, "請求失敗"),
    VALIDATE_PARAMS_ERROR(1002, "參數(shù)校驗失敗");
    private int code;
    private String msg;
    ResultCodeEnum(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    /**
     * 獲取code
     * @return
     */
    public int getCode() {
        return code;
    }
    /**
     * 獲取信息
     * @return
     */
    public String getMsg() {
        return msg;
    }
}

1.2 統(tǒng)一返回格式

統(tǒng)一狀態(tài)碼完成后,還需要定義統(tǒng)一返回格式,為了前端的方便調(diào)用

package com.lmc.common.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.lmc.common.enums.ResultCodeEnum;
import lombok.Data;
import java.util.Date;
/**
 * @Description: TODO 接口返回結(jié)果類型
 * @version: 1.0
 */
@Data
public class ResultVo {
    /**
     * 狀態(tài)碼
     */
    private int code;
    /**
     * 狀態(tài)碼信息
     */
    private String msg;
    /**
     * 返回描述信息(預備為調(diào)用失敗的情況下提供詳細的失敗原因)
     */
    private String desc;
    /**
     * 返回數(shù)據(jù)
     */
    private Object data;
    /**
     * 接口調(diào)用結(jié)束時間
     */
    @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd HH:mm:ss")
    private Date searchTime;
    public ResultVo(int code, String msg, Object data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
        this.searchTime = new Date();
    }
    /**
     * 調(diào)用成功時返回
     * @param data
     * @return
     */
    public static ResultVo success(Object data) {
        return new ResultVo(ResultCodeEnum.SUCCESS.getCode(), ResultCodeEnum.SUCCESS.getMsg(), data);
    }
    /**
     * 調(diào)用失敗時返回
     * @param data
     * @return
     */
    public static ResultVo fail(Object data) {
        return new ResultVo(ResultCodeEnum.FAILURE.getCode(), ResultCodeEnum.FAILURE.getMsg(), data);
    }
    /**
     * 調(diào)用時指定狀態(tài)碼
     * @param enums
     * @param data
     * @return
     */
    public static ResultVo result(ResultCodeEnum enums, Object data) {
        return new ResultVo(enums.getCode(), enums.getMsg(), data);
    }
    public ResultVo withDesc(String desc) {
        this.desc = desc;
        return this;
    }
}

1.3 自定義接口API異常類

然后再自定義接口的異常類,當然也可以不用,看個人喜好

package pers.lmc.tools2.provider.exception;
import com.lmc.common.enums.ResultCodeEnum;
/**
 * @Description: TODO API異常類
 * @version: 1.0
 */
public class ApiException extends RuntimeException{
    private int code;
    private String msg;
    public ApiException(String msg) {
        super(msg);
        this.code = ResultCodeEnum.FAILURE.getCode();
        this.msg = ResultCodeEnum.FAILURE.getMsg();
    }
    public ApiException(ResultCodeEnum enums, String msg) {
        super(msg);
        this.code = enums.getCode();
        this.msg = enums.getMsg();
    }
}

1.4 參數(shù)封裝類

為了調(diào)試參數(shù)驗證,還需要自定義一個參數(shù)的封裝類

package pers.lmc.tools2.provider.vo;
import lombok.Data;
/**
 * @Description: TODO
 * @version: 1.0
 */
@Data
public class Param01Vo {
    private String name;
    private Integer age;
    private Short sex;
}

二,參數(shù)驗證

參數(shù)驗證需要用到springboot的validation依賴

2.1 pom.xml

		<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
		<!--   關于校驗     -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jackson.version}</version>
        </dependency>

2.2 修改參數(shù)封裝類

package pers.lmc.tools2.provider.vo;
import lombok.Data;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
 * @Description: TODO
 * @version: 1.0
 */
@Data
public class Param01Vo {
    @NotNull(message = "名稱不能為空")
    @Size(min = 1, max = 50, message = "名稱name長度必須是1-50個字符")
    private String name;
    @NotNull(message = "年齡age不能為空")
    @Min(value = 10, message = "年齡age不能低于10歲")
    @Max(value = 25, message = "年齡age不能超過25歲")
    private Integer age;
    @Min(value = 0, message = "性別sex只能是0和1,0=女1=男")
    @Max(value = 1, message = "性別sex只能是0和1,0=女1=男")
    private Short sex;
}

在這里對該封裝類的三個參數(shù)都做了限制

2.3 controller

在controller中對參數(shù)做驗證時,需要在類上使用注解@Validated,同時在接口的該參數(shù)也使用注解@Valid

package pers.lmc.tools2.provider.controller;
import com.lmc.common.vo.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import pers.lmc.tools2.provider.vo.Param01Vo;
import javax.validation.Valid;
/*
 * @Description: TODO
 * @version: 1.0
 */
@RestController
@Validated
@RequestMapping("/valicate")
@Slf4j
public class ValicateController {
    @PostMapping("/add")
    public ResultVo addParam01(@Valid @RequestBody Param01Vo param01Vo) {
        log.info("執(zhí)行add()方法,參數(shù):" + param01Vo.toString());
        return ResultVo.success(param01Vo);
    }
}

2.4 測試

開發(fā)完成,準備測試,到APIPost上 訪問 http://localhost:9003/provider/valicate/add,帶上參數(shù):

{
    "name":"lmc",
    "age": 22,
    "sex": 1
}

訪問成功,返回結(jié)果如下:

{
	"code": 1000,
	"msg": "請求成功",
	"desc": null,
	"data": {
		"name": "lmc",
		"age": 22,
		"sex": 1
	},
	"searchTime": "2022-06-26 19:59:55"
}

如果參數(shù)輸入不正確,例如:

{
    "name":"",
    "age": 220,
    "sex": 2
}

得到結(jié)果如下:

{
	"timestamp": "2022-06-26T12:02:21.748+00:00",
	"status": 400,
	"error": "Bad Request",
	"message": "",
	"path": "/provider/valicate/add"
}

日志是這樣的:

2022-06-26 20:02:21 [http-nio-9003-exec-1] WARN  o.s.w.s.m.support.DefaultHandlerExceptionResolver - Resolved [org.springframework.web.bind.MethodArgumentNotValidException: Validation failed for argument [0] in public com.lmc.common.vo.ResultVo pers.lmc.tools2.provider.controller.ValicateController.addParam01(pers.lmc.tools2.provider.vo.Param01Vo) with 3 errors: [Field error in object 'param01Vo' on field 'sex': rejected value [2]; codes [Max.param01Vo.sex,Max.sex,Max.java.lang.Short,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [param01Vo.sex,sex]; arguments []; default message [sex],1]; default message [性別sex只能是0和1,0=女1=男]] [Field error in object 'param01Vo' on field 'age': rejected value [220]; codes [Max.param01Vo.age,Max.age,Max.java.lang.Integer,Max]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [param01Vo.age,age]; arguments []; default message [age],25]; default message [年齡age不能超過25歲]] [Field error in object 'param01Vo' on field 'name': rejected value []; codes [Size.param01Vo.name,Size.name,Size.java.lang.String,Size]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [param01Vo.name,name]; arguments []; default message [name],50,1]; default message [名稱name長度必須是1-50個字符]] ]

拋出了MethodArgumentNotValidException異常。

雖然參數(shù)錯誤時確實被攔截了,但格式已經(jīng)和我們想要返回的不一致了。這個時候,就需要用到統(tǒng)一異常處理了。

三,統(tǒng)一異常處理

3.1 方法參數(shù)驗證異常處理

通過以上的問題,我們可以設置controller的統(tǒng)一異常處理,當出現(xiàn)參數(shù)驗證錯誤時,就捕獲MethodArgumentNotValidException異常,然后我們自己做處理。

package pers.lmc.tools2.provider.aop;
import com.lmc.common.enums.ResultCodeEnum;
import com.lmc.common.vo.ResultVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import pers.lmc.tools2.provider.exception.ApiException;
import java.util.List;
import java.util.stream.Collectors;
/**
 * @Description: TODO
 * @version: 1.0
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {
    /**
     * 處理所有校驗失敗的異常(MethodArgumentNotValidException異常)
     * @param e
     * @return
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResultVo handleBindGetException(MethodArgumentNotValidException e) {
        // 獲取所有異常參數(shù)
        List<String> errors = e.getBindingResult()
                .getFieldErrors()
                .stream()
                .map(x -> x.getDefaultMessage())
                .collect(Collectors.toList());
        return ResultVo.result(ResultCodeEnum.VALIDATE_PARAMS_ERROR, null).withDesc("參數(shù)校驗失敗:" + errors);
    }
    /**
     * 處理自定義APIException異常
     * @param e
     * @return
     */
    @ExceptionHandler(value = ApiException.class)
    public ResultVo handleApiException(ApiException e) {
        return ResultVo.fail(null).withDesc(e.getMessage());
    }
    /**
     * 處理其他異常
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public ResultVo handleException(Exception e) {
        log.info("執(zhí)行到統(tǒng)一處理方法...");
        return ResultVo.fail(null).withDesc(e.getMessage());
    }
}

通過以上配置,再次以非法參數(shù)傳輸時,會報出以下錯誤:

{
	"code": 1002,
	"msg": "參數(shù)校驗失敗",
	"desc": "參數(shù)校驗失敗:[性別sex只能是0和1,0=女1=男, 名稱name長度必須是1-50個字符, 年齡age不能超過25歲]",
	"data": null,
	"searchTime": "2022-06-26 20:08:22"
}

這個時候格式已經(jīng)我們想要的返回格式了。

3.2 其他異常處理

剛剛我們嘗試的是方法的參數(shù)驗證異常的處理,對于程序還可能出現(xiàn)的錯誤,配置統(tǒng)一異常處理后也不需要使用try{} catch() {},因為我們已經(jīng)在全局異常處理類中配置了:

	/**
     * 處理其他異常
     * @param e
     * @return
     */
    @ExceptionHandler(value = Exception.class)
    public ResultVo handleException(Exception e) {
        log.info("執(zhí)行到統(tǒng)一處理方法...");
        return ResultVo.fail(null).withDesc(e.getMessage());
    }

這個時候在程序中拋出其他異常,就會執(zhí)行到這里的代碼,同樣返回我們想要的格式。舉例如下

修改controller接口:

    @PostMapping("/add")
    public ResultVo addParam01(@Valid @RequestBody Param01Vo param01Vo) {
        log.info("執(zhí)行add()方法,參數(shù):" + param01Vo.toString());
        int k = 1/0; // 調(diào)用該接口時執(zhí)行到這里會拋出異常
        return ResultVo.success(param01Vo);
    }

調(diào)用接口返回結(jié)果:

{
	"code": 1001,
	"msg": "請求失敗",
	"desc": "/ by zero",
	"data": null,
	"searchTime": "2022-06-26 20:13:51"
}

到此這篇關于Java Controller實現(xiàn)參數(shù)驗證與統(tǒng)一異常處理流程詳細講解的文章就介紹到這了,更多相關Java Controller參數(shù)驗證與異常處理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java ArrayList使用總結(jié)

    Java ArrayList使用總結(jié)

    這篇文章主要介紹了Java ArrayList使用總結(jié),幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下
    2021-03-03
  • SpringAop日志找不到方法的處理

    SpringAop日志找不到方法的處理

    這篇文章主要介紹了SpringAop日志找不到方法的處理方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Java利用Jackson輕松處理JSON序列化與反序列化

    Java利用Jackson輕松處理JSON序列化與反序列化

    Jackson?是?Java?中最流行的?JSON?處理庫之一,它提供了許多注解來簡化?JSON?的序列化和反序列化過程。這篇文章將介紹一些?Jackson?常用的注解,以幫助您更輕松地處理?JSON?數(shù)據(jù)
    2023-05-05
  • spring單例如何改多例

    spring單例如何改多例

    這篇文章主要介紹了spring單例如何改多例,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • Java值得使用Lambda的8個場景合集

    Java值得使用Lambda的8個場景合集

    可能對不少人來說,Lambda顯得陌生又復雜,覺得Lambda會導致代碼可讀性下降,但畢竟2023年了,JDK都出了那么多新版本,是時候試試Lambda了
    2023-08-08
  • java集合 ArrayDeque源碼詳細分析

    java集合 ArrayDeque源碼詳細分析

    ArrayDeque是一種以數(shù)組方式實現(xiàn)的雙端隊列,它是非線程安全的。下面小編和大家一起學習一下
    2019-05-05
  • SpringBoot整合minio服務的示例代碼

    SpringBoot整合minio服務的示例代碼

    本文主要介紹了SpringBoot整合minio服務的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06
  • 如何開發(fā)基于Netty的HTTP/HTTPS應用程序

    如何開發(fā)基于Netty的HTTP/HTTPS應用程序

    HTTP/HTTPS是最常見的協(xié)議套件之一,并且隨著智能手機的成功,它的應用也日益廣泛,因為對于任何公司來說,擁有一個可以被移動設備訪問的網(wǎng)站幾乎是必須的。下面就來看看如何開發(fā)基于Netty的HTTP/HTTPS應用程序
    2021-06-06
  • mybatis批量更新與插入方式

    mybatis批量更新與插入方式

    這篇文章主要介紹了mybatis批量更新與插入方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • java讀取Excel導入去除空行簡單方法

    java讀取Excel導入去除空行簡單方法

    這篇文章主要給大家介紹了關于java讀取Excel導入去除空行的簡單方法,在日常開發(fā)中,想必都遇到過批處理的需求,文中給出了詳細的示例代碼,需要的朋友可以參考下
    2023-07-07

最新評論