日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

五分鐘帶你了解Java的接口數據校驗

瀏覽:18日期:2022-08-19 16:10:44

本篇文章給大家分享平時開發中總結的一點小技巧!在工作中寫過Java程序的朋友都知道,目前使用Java開發服務最主流的方式就是通過Spring MVC定義一個Controller層接口,并將接口請求或返回參數分別定義在一個Java實體類中,這樣Spring MVC在接收到Http請求(POST/GET)后,就會自動將請求報文自動映射成一個Java對象。這樣的代碼通常是這樣寫的:

@RestControllerpublic class OrderController { @Autowired private OrderService orderServiceImpl; @PostMapping('/createOrder') public CreateOrderBO validationTest(@Validated CreateOrderDTO createOrderDTO) { return orderServiceImpl.createOrder(createOrderDTO); }}

這樣的代碼相信大家并不陌生,但在后續的邏輯實現過程中卻會遇到這樣的問題:“在接收請求參數后如何實現報文對象數據值的合法性校驗?”。一些同學也可能認為這并不是什么問題,因為具體某個參數字段是否為空、值的取值是否在約定范圍、格式是否合法等等,在業務代碼中校驗就好了。例如可以在Service實現類中對報文格式進行各種if-else的數據校驗。從功能上說冗余的if-else代碼沒啥毛病,但從代碼的優雅性來說冗長的if-else代碼會顯得非常臃腫。接下來的內容將給大家介紹一種處理此類問題的實用方法。具體將從以下幾個方面進行介紹:

使用@Validated注解實現Controller接口層數據直接綁定校驗; 擴展約束性注解實現數據取值范圍的校驗; 更加靈活的對象數據合法性校驗工具類封裝; 數據合法性校驗結果異常統一返回處理;Controller接口層數據綁定校驗

實際上在Java開發中目前普通使用的Bean數據校驗工具是'hibernate-validator',它是一個hibernete獨立的jar包,所以使用這個jar包并不需要一定要集成Hibernete框架。該jar包主要實現并擴展了javax.validation(是一個基于JSR-303標準開發出來的Bean校驗規范)接口。

由于Spring Boot在內部默認集成了'hibernate-validator',所以使用Spring Boot構建的Java工程可以直接使用相關注解來實現Bean的數據校驗。例如我們最常編寫的Controller層接口參數對象,可以在定義Bean類時直接編寫這樣的代碼:

@Datapublic class CreateOrderDTO { @NotNull(message = '訂單號不能為空') private String orderId; @NotNull(message = '訂單金額不能為空') @Min(value = 1, message = '訂單金額不能小于0') private Integer amount; @Pattern(regexp = '^1[3|4|5|7|8][0-9]{9}$', message = '用戶手機號不合法') private String mobileNo; private String orderType; private String status;}

如上所示代碼,我們可以使用@NotNull注解來約束該字段必須不能為空,也可以使用@Min注解來約束字段的最小取值,或者還可以通過@Pattern注解來使用正則表達式來約束字段的格式(如手機號格式)等等。

五分鐘帶你了解Java的接口數據校驗

以上這些注解都是“hibernate-validator”依賴包默認提供的,更多常用的注解還有很多,例如:

利用這些約束注解,我們就可以很輕松的搞定接口數據校驗,而不需要在業務邏輯中編寫大量的if-else來進行數據合法性校驗。而定義好Bean參數對象并使用相關注解實現參數值約束后,在Controller層接口定義中只需要使用@Validated注解就可以實現在接收參數后自動進行數據綁定校驗了,具體代碼如下:

@PostMapping('/createOrder')public CreateOrderBO validationTest(@Validated CreateOrderDTO createOrderDTO) { return orderServiceImpl.createOrder(createOrderDTO);}

如上所示,在Controller層中通過Spring提供的@Validated注解可以自動實現數據Bean的綁定校驗,如果數據異常則會統一拋出校驗異常!

約束性注解擴展

在“hibernate-validator”依賴jar包中,雖然提供了很多很方便的約束注解,但是也有不滿足某些實際需要的情況,例如我們想針對參數中的某個值約定其值的枚舉范圍,如orderType訂單類型只允許傳“pay”、“refund”兩種值,那么現有的約束注解可能就沒有特別適用的了。此外,如果對這樣的枚舉值,我們還想在約束定義中直接匹配代碼中的枚舉定義,以更好地統一接口參數與業務邏輯的枚舉定義。那么這種情況下,我們還可以自己擴展定義相應地約束注解邏輯。接下來我們定義新的約束注解@EnumValue,來實現上面我們所說的效果,具體代碼如下:

@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER})@Retention(RUNTIME)@Documented@Constraint(validatedBy = {EnumValueValidator.class})public @interface EnumValue { //默認錯誤消息 String message() default '必須為指定值'; //支持string數組驗證 String[] strValues() default {}; //支持int數組驗證 int[] intValues() default {}; //支持枚舉列表驗證 Class<?>[] enumValues() default {}; //分組 Class<?>[] groups() default {}; //負載 Class<? extends Payload>[] payload() default {}; //指定多個時使用 @Target({FIELD, METHOD, PARAMETER, ANNOTATION_TYPE}) @Retention(RUNTIME) @Documented @interface List { EnumValue[] value(); } /** * 校驗類邏輯定義 */ class EnumValueValidator implements ConstraintValidator<EnumValue, Object> { //字符串類型數組 private String[] strValues; //int類型數組 private int[] intValues; //枚舉類 private Class<?>[] enumValues; /** * 初始化方法 * * @param constraintAnnotation */ @Override public void initialize(EnumValue constraintAnnotation) { strValues = constraintAnnotation.strValues(); intValues = constraintAnnotation.intValues(); enumValues = constraintAnnotation.enumValues(); } /** * 校驗方法 * * @param value * @param context * @return */ @SneakyThrows @Override public boolean isValid(Object value, ConstraintValidatorContext context) { //針對字符串數組的校驗匹配 if (strValues != null && strValues.length > 0) {if (value instanceof String) { for (String s : strValues) {//判斷值類型是否為Integer類型 if (s.equals(value)) { return true; } }} } //針對整型數組的校驗匹配 if (intValues != null && intValues.length > 0) {if (value instanceof Integer) {//判斷值類型是否為Integer類型 for (Integer s : intValues) { if (s == value) { return true; } }} } //針對枚舉類型的校驗匹配 if (enumValues != null && enumValues.length > 0) {for (Class<?> cl : enumValues) { if (cl.isEnum()) { //枚舉類驗證 Object[] objs = cl.getEnumConstants(); //這里需要注意,定義枚舉時,枚舉值名稱統一用value表示 Method method = cl.getMethod('getValue'); for (Object obj : objs) { Object code = method.invoke(obj, null); if (value.equals(code.toString())) {return true; } } }} } return false; } }}

如上所示的@EnumValue約束注解,是一個非常實用的擴展,通過該注解我們可以實現對參數取值范圍(不是大小范圍)的約束,它支持對int、string以及enum三種數據類型的約束,具體使用方式如下:

/** * 定制化注解,支持參數值與指定類型數組列表值進行匹配(缺點是需要將枚舉值寫死在字段定義的注解中) */@EnumValue(strValues = {'pay', 'refund'}, message = '訂單類型錯誤')private String orderType;/** * 定制化注解,實現參數值與枚舉列表的自動匹配校驗(能更好地與實際業務開發匹配) */@EnumValue(enumValues = Status.class, message = '狀態值不在指定范圍')private String status;

如上所示代碼,該擴展注解既可以使用strValues或intValues屬性來編程列舉取值范圍,也可以直接通過enumValues來綁定枚舉定義。但是需要注意,處于通用考慮,具體枚舉定義的屬性的名稱要統一匹配為value、desc,例如Status枚舉定義如下:

public enum Status { PROCESSING(1, '處理中'), SUCCESS(2, '訂單已完成'); Integer value; String desc; Status(Integer value, String desc) { this.value = value; this.desc = desc; } public Integer getValue() { return value; } public String getDesc() { return desc; }}

通過注解擴展,就能實現更多方便的約束性注解!

更加靈活的數據校驗工具類封裝

除了上面直接在Controller層使用@Validated進行綁定數據校驗外,在有些情況,例如你的參數對象中的某個字段是一個復合對象,或者業務層的某個方法所定義的入參對象也需要進行數據合法性校驗,那么這種情況下如何實現像Controller層一樣的校驗效果呢?

需要說明在這種情況下@Validated已經無法直接使用了,因為@Validated注解發揮作用主要是Spring MVC在接收參數的過程中實現了自動數據綁定校驗,而在普通的業務方法或者復合參數對象中是沒有辦法直接綁定校驗的。這種情況下,我們可以通過定義ValidateUtils工具類來實現一樣的校驗效果,具體代碼如下:

public class ValidatorUtils { private static Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); /** * bean整體校驗,有不合規范,拋出第1個違規異常 */ public static void validate(Object obj, Class<?>... groups) { Set<ConstraintViolation<Object>> resultSet = validator.validate(obj, groups); if (resultSet.size() > 0) { //如果存在錯誤結果,則將其解析并進行拼湊后異常拋出 List<String> errorMessageList = resultSet.stream().map(o -> o.getMessage()).collect(Collectors.toList()); StringBuilder errorMessage = new StringBuilder(); errorMessageList.stream().forEach(o -> errorMessage.append(o + ';')); throw new IllegalArgumentException(errorMessage.toString()); } }}

如上所示,我們定義了一個基于'javax.validation'接口的工具類實現,這樣就可以在非@Validated直接綁定校驗的場景中通過校驗工具類來實現對Bean對象約束注解的校驗處理,具體使用代碼如下:

public boolean orderCheck(OrderCheckBO orderCheckBO) { //對參數對象進行數據校驗 ValidatorUtils.validate(orderCheckBO); return true;}

而方法入參對象則還是可以繼續使用前面我們介紹的約束性注解進行約定,例如上述方法的入參對象定義如下:

@Data@Builderpublic class OrderCheckBO { @NotNull(message = '訂單號不能為空') private String orderId; @Min(value = 1, message = '訂單金額不能小于0') private Integer orderAmount; @NotNull(message = '創建人不能為空') private String operator; @NotNull(message = '操作時間不能為空') private String operatorTime;}

這樣在編程體驗上就可以整體上保持一致!

數據合法性校驗結果異常統一處理

通過前面我們所講的各種約束注解,我們實現了對Controller層接口以及業務方法參數對象的統一數據校驗。而為了保持校驗異常處理的統一處理和錯誤報文統一輸出,我們還可以定義通用的異常處理機制,來保證各類數據校驗錯誤都能以統一錯誤格式反饋給調用方。具體代碼如下:

@Slf4j@ControllerAdvicepublic class GlobalExceptionHandler { /** * 統一處理參數校驗錯誤異常(非Spring接口數據綁定驗證) * * @param response * @param e * @return */ @ExceptionHandler(BindException.class) @ResponseBody public ResponseResult<?> processValidException(HttpServletResponse response, BindException e) { response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); //獲取校驗錯誤結果信息,并將信息組裝 List<String> errorStringList = e.getBindingResult().getAllErrors().stream().map(ObjectError::getDefaultMessage).collect(Collectors.toList()); String errorMessage = String.join('; ', errorStringList); response.setContentType('application/json;charset=UTF-8'); log.error(e.toString() + '_' + e.getMessage(), e); return ResponseResult.systemException(GlobalCodeEnum.GL_FAIL_9998.getCode(),errorMessage); } /** * 統一處理參數校驗錯誤異常 * * @param response * @param e * @return */ @ExceptionHandler(IllegalArgumentException.class) @ResponseBody public ResponseResult<?> processValidException(HttpServletResponse response, IllegalArgumentException e) { response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); String errorMessage = String.join('; ', e.getMessage()); response.setContentType('application/json;charset=UTF-8'); log.error(e.toString() + '_' + e.getMessage(), e); return ResponseResult.systemException(GlobalCodeEnum.GL_FAIL_9998.getCode(),errorMessage); } ...}

如上所示,我們定義了針對前面兩種數據校驗方式的統一異常處理機制,這樣數據校驗的錯誤信息就能通過統一的報文格式反饋給調用端,從而實現接口數據報文的統一返回!

其中通用的接口參數對象ResponseResult的代碼定義如下:

@Data@Builder@NoArgsConstructor@AllArgsConstructor@JsonPropertyOrder({'code', 'message', 'data'})public class ResponseResult<T> implements Serializable { private static final long serialVersionUID = 1L; /** * 返回的對象 */ @JsonInclude(JsonInclude.Include.NON_NULL) private T data; /** * 返回的編碼 */ private Integer code; /** * 返回的信息 */ private String message; /** * @param data 返回的數據 * @param <T> 返回的數據類型 * @return 響應結果 */ public static <T> ResponseResult<T> OK(T data) { return packageObject(data, GlobalCodeEnum.GL_SUCC_0); } /** * 自定義系統異常信息 * * @param code * @param message 自定義消息 * @param <T> * @return */ public static <T> ResponseResult<T> systemException(Integer code, String message) { return packageObject(null, code, message); }}

當然,這樣的統一報文格式也不僅僅只處理異常返回,正常的數據報文格式也可以通過該對象來進行統一封裝!本文內容從實用的角度給大家演示了,如何在日常工作中編寫通用的數據校驗邏輯,希望能對大家有所幫助!

到此這篇關于五分鐘帶你了解Java的接口數據校驗的文章就介紹到這了,更多相關Java 接口數據校驗內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲欧美在线专区| 国产伦精品一区二区三区视频 | 国产精品久久久一区二区| 欧美日本不卡| 国产va免费精品观看精品视频| 日韩精品免费一区二区三区| 激情欧美国产欧美| 亚洲精品高潮| 麻豆国产一区| 亚洲高清二区| 日欧美一区二区| 久久99精品久久久久久园产越南 | 久久精品二区亚洲w码| 日韩精品水蜜桃| 综合激情网...| 国产精品网站在线看| 久久九九精品| 日韩精品亚洲一区二区三区免费| 麻豆精品视频在线观看免费| 亚洲午夜电影| 欧美偷窥清纯综合图区| 麻豆精品蜜桃| 欧美久久精品| 久久香蕉国产| 国产剧情一区二区在线观看| 黑森林国产精品av| 视频一区欧美精品| 国产成人精品亚洲线观看 | 亚洲欧美一区在线| 国产亚洲一卡2卡3卡4卡新区| 久久精品成人| 国产精品麻豆成人av电影艾秋| 亚洲性图久久| 精品亚洲精品| 日本亚洲视频在线| 久久精品亚洲人成影院| 欧美日韩中出| 爽好久久久欧美精品| 国产一区二区三区四区五区传媒| 日韩中文字幕不卡| 另类中文字幕国产精品| 国产精品伊人| 日韩中文字幕区一区有砖一区| 精品久久在线| 日本强好片久久久久久aaa| 99精品综合| 久久精品女人| 亚洲精品一二| 午夜影院欧美| 欧美成a人国产精品高清乱码在线观看片在线观看久 | 日本蜜桃在线观看视频| 亚洲精品少妇| 欧美午夜不卡| 超碰超碰人人人人精品| 国产精品亚洲人成在99www| 99国产精品99久久久久久粉嫩| 国产一区二区三区91| 青青国产精品| 日本 国产 欧美色综合| 国产精品国产一区| 日韩成人午夜精品| 蜜臀精品久久久久久蜜臀| 欧美亚洲国产激情| 国产美女高潮在线| 精品香蕉视频| 欧美在线不卡| 日韩午夜视频在线| 亚洲在线电影| av一区二区高清| 久久伦理在线| 久久亚洲国产| 婷婷成人在线| 久久中文字幕二区| 久久精品亚洲人成影院| 日韩欧美一区二区三区在线观看| 久久影视三级福利片| 国产精品久久久久久久免费软件 | 蜜桃国内精品久久久久软件9| 国产白浆在线免费观看| 成人一区而且| 国产资源在线观看入口av| 久久只有精品| 精品一区视频| 麻豆国产精品| 成人精品久久| 欧美成人基地| 精品一区在线| 午夜欧美精品| 国产亚洲网站| 亚洲一区二区三区中文字幕在线观看 | 亚洲区欧美区| 国产精品白丝久久av网站| 欧美精品福利| 在线看片一区| 亚洲深夜影院| 久久亚洲美女| 亚洲精品动态| 日韩欧美激情电影| 欧美亚洲一区二区三区| 亚洲精品国产精品粉嫩| 日韩高清在线观看一区二区| 日韩av中文字幕一区| 国产日韩一区二区三区在线| 日韩不卡一区二区| 国产精品xxx| 日韩av片子| 久久中文字幕av| 亚洲综合不卡| 国产欧美视频在线| аⅴ资源天堂资源库在线| 久久青草久久| 快she精品国产999| 欧美精品中文| 国产传媒在线| 一区二区三区四区在线看| 亚洲欧美日韩高清在线| 亚洲五月综合| 久久国产麻豆精品| 日韩天堂在线| 一区二区三区四区精品视频| 国产精品永久| 日韩另类视频| 免费成人在线观看| 国产精品中文字幕亚洲欧美| 狠狠躁少妇一区二区三区| 亚洲一区二区日韩| 久久久久亚洲精品中文字幕| 久久精品不卡| 日本成人手机在线| 日韩88av| 国产免费成人| 麻豆成人91精品二区三区| 欧美日韩中文字幕一区二区三区| 蜜臀久久99精品久久久久宅男| 国产探花在线精品一区二区| 国产超碰精品| 香蕉久久一区| 久久久一本精品| 日韩中文字幕一区二区高清99| 国产一区二区三区四区| 国产亚洲亚洲| 成人精品高清在线视频| 老色鬼久久亚洲一区二区| 欧美aⅴ一区二区三区视频| 欧美日韩在线二区| 日韩极品在线观看| 亚洲v在线看| 欧美在线看片| 五月婷婷亚洲| 精品欠久久久中文字幕加勒比| 老鸭窝毛片一区二区三区| 美腿丝袜亚洲三区| 99香蕉国产精品偷在线观看| 麻豆久久一区| 日av在线不卡| 亚洲h色精品| 欧美aa在线视频| 免费在线观看不卡| 免费在线小视频| 国产精品二区影院| 国产精品日本| sm捆绑调教国产免费网站在线观看 | 国产欧美自拍一区| 欧美一区二区三区高清视频 | 综合一区在线| 欧美亚洲国产一区| 成人黄色av| 国产乱码精品一区二区三区亚洲人 | 美女尤物国产一区| 免费成人在线影院| 亚洲韩日在线| 国产精品久久久久久久久妇女| 亚洲精品少妇| 老鸭窝毛片一区二区三区| 国产一区视频在线观看免费| 高清一区二区| 国产精品久久久一区二区| 日韩一级精品| 久久精品国产大片免费观看| 精品久久99| 国产乱人伦丫前精品视频 | 日韩精品1区| 久久精品九色| 国产精品s色| 日韩精彩视频在线观看| 日av在线不卡| 日韩欧美国产精品综合嫩v| 国产九一精品| 欧美私人啪啪vps| 免费看欧美美女黄的网站| 亚洲不卡av不卡一区二区| 国语对白精品一区二区| 国产精区一区二区| 久久精品999| 国产精品资源| 国产伦一区二区三区| 久久国内精品视频| 国产精品手机在线播放| 久久不卡国产精品一区二区| 久久国产精品免费精品3p |