使用ABAP Data Validator验证数据有效性

在日常的开发过程中,我们常常要处理不同来源的数据。数据可能来自不可靠的外部系统、不可靠的用户输入和甚至设计有误的数据库表,因此,对数据有效性进行验证是必要的工作。

开源工具ABAP Data Validator是一个使用ABAP开发的数据验证工具,它可以简化开发者在这方面的工作。本文将介绍它的用法和一些设计思路。

本文链接:https://www.cnblogs.com/hhelibeb/p/12206648.html

原创内容,转载请注明

目的

具体而言,ABAP Data Validator将通过以下的思路简化数据有效性验证方面的工作:

  • 提供统一的检查接口,让开发者通过单次方法调用就可以实现对数据的检查。
  • 将验证逻辑集中实现,避免相似的检查代码分散在系统各处造成的逻辑不一致,从而降低相关程序的维护成本。
  • 避免检查过程中的潜在dump,减少开发者处理dump问题的精力花费。

为了实现以上目的,该工具实现了一些功能:

  • 内置常见的验证逻辑。
  • 可配置的检查规则。
  • 可扩展的检查程序。
  • 异常的统一处理。

支持的检查列表

ABAP Data Validator目前支持以下类型的检查(持续更新中):

  • 日期.
  • 时间.
  • 时间戳.
  • 邮件地址.
  • INT4.
  • 正则字符串.
  • URL.
  • JSON.
  • HEX.
  • IMEI.
  • GUID.
  • BASE64.
  • HTML (实验性的).

此外,它也支持对内表字段的必填检查、根据数据元素的类型进行检查等功能,下文会详细介绍。

使用

ABAP Data Validator支持多种检查方式,下面会由简单到复杂进行逐一介绍。

对单一字段的直接检查

对于每种数据类型,ABAP Data Validator会有一个专门的检查类,可以用这些检查类的is_valid方法来检查变量的值是否有效,就像使用abap的内置函数那样。比如,要检查一个字符串是否是有效的邮箱地址,可以用如下代码实现,

IF zcl_adv_email_check=>is_valid( ‘[email protected]‘ ).
 "do something
ENDIF.

所有的检查类都实现了接口zif_adv_check,因此它们都拥有静态方法is_valid,如下图(为了方便阅读,图中没有包含全部的实现类),

对于类方法而言,is_valid是个别名,也可以不使用别名来调用接口方法:

IF zcl_adv_email_check=>zif_adv_check~is_valid( ‘[email protected]‘ ).
 "do something
ENDIF.

当然并不推荐这种方式,因为会让代码变长。

检查类的命名规则是ZCL_ADV_类型名_CHECK。

使用参考数据元素检查

为了便于使用,方法is_valid的定义十分简单,只有一个输入参数、一个返回值,不包含任何异常,这使得它无法胜任数量、金额等类型(一般而言是P类型,包含长度和小数位定义)字段的检查。为了解决这一问题,ABAP Data Validator提供了参考数据元素进行检查的用法。可以使用类zcl_adata_validator的方法validate_by_element使用该功能,示例如下,

DATA(result) = NEW zcl_adata_validator( )->->validate_by_element(
   data    = data
   element = ‘MENGE_D‘ "数量
).

result是一个结构,包含两个字段valid和type,如果data的值无法转换为数字、或者转换后溢出的话,result-valid将被赋值为abap_false(即空);如果data是一个有效值,那么rresult-valid将被赋值为abap_true(即‘X‘)。

正常情况下,result-type总会被赋值为数据元素的类型,对P类型,则为固定值’PACKED‘(c_type_packed)。但如果输入的数据元素无效的话,type则会被赋值为固定值’Invalid Type‘(c_type_invalid)。

目前支持以下类型的数据元素:

  • 日期
  • 时间
  • 时间戳
  • INT4
  • GUID
  • HEX
  • DEC(P类型)

为了保持检查方法的简单性,validate_by_element方法的定义同样不包含异常。任何异常都会在方法内部被处理。出现异常时,result-valid会被赋值为abap_false,type会被赋值为’Invalid Type‘。

内表检查

ABAP Data Validator可以根据指定的规则对内表进行检查,如下所示,将规则my_rules和内表uploaded_data传入类zcl_adata_validator的方法validate,可以得到检查结果内表results,

TRY.
    DATA(results) = NEW zcl_adata_validator( )->validate(
         rules   = my_rules
         data    = uploaded_data
     ).
  CATCH zcx_adv_exception INTO DATA(ex).
    DATA(msg) = ex->get_text( ).
ENDTRY. 

检查规则rules用于设定检查逻辑。

rules的类型定义如下,

    TYPES: BEGIN OF ty_rule,
             fname            TYPE name_komp,   "字段名
             required         TYPE abap_bool,   "必填
             initial_or_empty TYPE abap_bool,   "必须为空或初始值
             user_type        TYPE ty_spec_type,"检查类型(参考类zcl_adata_validator的常量列表)
             regex            TYPE string,      "自定义正则表达式
             regex_msg        TYPE string,      "自定义正则表达式检查失败消息
             ref_element      TYPE rollname,    "参考数据元素
           END OF ty_rule.

    TYPES: ty_rules_t TYPE HASHED TABLE OF ty_rule WITH UNIQUE KEY fname.

简单的示例如下,

DATA: rules TYPE zcl_adata_validator=>ty_rules_t.
*字段1为必填字段,类型是日期,字段2非必填,类型为邮件地址
rules = VALUE #(
  ( fname = ‘FIELD1‘ required = abap_true  user_type = zcl_adata_validator=>c_type_date )
  ( fname = ‘FIELD2‘ user_type = zcl_adata_validator=>c_type_email )
).

扩展检查功能

使用ABAP Data Validator自带的检查逻辑可以满足很多场景下的基本检查需要,但是你也许还有更多的检查逻辑。有2种方式可以实现检查功能的扩展。

  1. 通过rules-regex传入正则表达式。
  2. 创建新的检查类型:定义新的类型名,创建它的检查类,实现接口zif_adv_check,将自定义检查逻辑写在is_valid方法的实现中。接着,将类型名和类名传入zcl_adata_validator的构造方法constructor中。这样就可以使用新的检查类型了。

正则表达式示例:如果你不仅要检查一个字段的值是否为邮件地址,还要验证它是gmail邮箱,那么可以把正则表达式’gmail\.com$‘复制给rules-regex,

DATA: rules TYPE zcl_adata_validator=>ty_rules_t.

DATA: cases TYPE ty_case_t.

cases = VALUE #(
    ( field3 = ‘[email protected]‘) "正确,是gmail邮箱
    ( field3 = ‘[email protected]‘)    "不正确,非gmail邮箱
).

rules = VALUE #(
  ( fname = ‘FIELD2‘ user_type = zcl_adata_validator=>c_type_email regex = ‘gmail\.com$‘ regex_msg = ‘Only gmail supported‘)
).

或者创建一个新类型和它的检查类,并且把它的检查类配置传入constructor,

DATA: check_class_config TYPE zcl_adata_validator=>ty_check_config_t.

check_class_config = VALUE #( ( type = zcl_adata_validator=>c_type_new  class = ‘ZCL_NEW_VALIDATOR‘ ) ).

TRY.
     DATA(result) = NEW zcl_adata_validator( check_class_conifg = check_class_config )->validate(
         rules   = rules
         data    = cases
     ).
CATCH zcx_adv_exception INTO DATA(ex).
    DATA(msg) = ex->get_text( ).
ENDTRY.

注意:constructor中已经包含了默认的检查类配置和检查消息配置,它们是Hard coding,一旦传入自定义配置,它们就会被覆盖。

可以按需对方法进行重定义、或者传入自己的配置。比如,从数据库或其它来源读取配置,这样可以在不修改既有代码的情况下扩展程序的功能

DATA: check_class_config TYPE zcl_adata_validator=>ty_check_config_t.

SELECT * FROM my_config_table INTO TABLE @check_class_config.

TRY.
    DATA(result) = NEW zcl_adata_validator( check_class_conifg = check_class_config )->validate(
        rules   = rules
        data    = cases
    ).
CATCH zcx_adv_exception INTO DATA(ex).
    DATA(msg) = ex->get_text( ).
ENDTRY.

项目地址

https://github.com/hhelibeb/abap-data-validator

我提交了绝大部分代码,此外还有2位贡献者larshpFreHu,他们帮助修正了代码格式和readme方面的一些问题。

欢迎参与这个工具的开发!如果你发现程序有任何问题,也可以在github提交issue告知我。

Q & A

怎样定义有效性?

有效性的定义十分重要,如果有效的定义是模糊的,那检查也失去了意义。

对于ABAP Data Validator,如果一个检查类型存在对应的ABAP数据类型(比如日期,时间戳等),那么“有效”是指:

  • 值可以直接被赋值给相应类型的ABAP变量,不产生异常,也不产生无意义的值。

以时间戳为例,

  • 2021-12-21 00:00:00   "无效
  • 19000000235959        "无效
  • 20200101235959        "有效

2021-12-21 00:00:00’\可能在某些情境下是合理的时间戳值,但是对于ABAP Data Validator而言,它是无效的,因为将它赋值给时间戳类型的变量会导致dump。而‘19000000235959‘虽然可以被赋值给ABAP时间戳变量,但因为没有实际意义,它同样是无效值。

这种类型检查的逻辑主要由SAP提供的标准功能实现,时间戳的检查实际上由正则检查、标准函数DATE_CHECK_PLAUSIBILITY和TIME_CHECK_PLAUSIBILITY组成。

如果一个检查类型没有对应的ABAP数据类型,ABAP Data Validator的检查逻辑收集自一些相对权威的来源,这些检查逻辑通常会符合行业标准。来源包括,

ABAP Data Validator的检查结果可靠吗?

绝大部分检查逻辑是成熟的,且它们都包含单元测试。你可以在单元测试中加上自己的用例来验证它们的行为是否符合你的期望。

HTML检查是个例外,它是唯一一个需要调用外部API(https://validator.w3.org/)的检查,而且w3.org提供的API本身也只是实验性的。请只把它的检查结果当作参考。

目前,我已经在工作中部分地应用了ABAP Data Validator,看起来工作良好。

为什么是多个类,而不是一个类、多个方法?

一个很自然的问题是为什么不把这些检查功能放到一个类里面?毕竟,有时候为了几行代码的检查逻辑创建一个新类太过奢侈。

如果将所有检查放在同一个类里面,将会有一些好处,

  • 减少了全局类数量,方便记忆/不易产生命名冲突。
  • 方法定义更灵活,不需要接受接口ZIF_ADV_CHECK的限制。

但是也会带来一些损失,

  • 不同类型的检查之间的耦合度增加,部署单个方法的更新时,可能会导致更多的LOAD_ PROGRAM CLASS_ MISMATCH异常。
  • 不同开发者的ABAP服务器可能环境不同,如果个别方法不可用,问题将波及整个类,导致其它检查也不可用。
  • 失去了接口接口ZIF_ADV_CHECK的约束后,动态编程会变得复杂,也难以保持检查规则的简单性。

总之,经过一番权衡之后我选择了当前的设计,尽管它也存在某些缺点,如果你有更好的想法,请告诉我。

原文地址:https://www.cnblogs.com/hhelibeb/p/12206648.html

时间: 2024-10-19 10:45:17

使用ABAP Data Validator验证数据有效性的相关文章

jQuery.validator 验证规则详解

前言:jQuery.validator是一款非常不错的表单验证插件,验证方式非常简单方便,它还对HTML5做了兼容处理,了解了验证规则,就基本掌握了它的使用,下面就让我一一道来 jQuery.validator 验证规则 一.在元素的class属性中添加需要验证的规则,多个规则以空格隔开 <label>邮箱:</label> <input class="required email" type="text" name="ema

vue学习记录:vue引入,validator验证,数据信息,vuex数据共享

最近在学习vue,关于学习过程中所遇到的问题进行记录,包含vue引入,validator验证,数据信息,vuex数据共享,传值问题记录 1.vue 引入vue vue的大致形式如下: <template> </template> <script> </script> <style> </style> 要引入其他vue ,需要 import <template> <div> <Header></

Validator验证框架

一.Validator框架的优势        Validator框架是一个Struts插件,最初由David Winterfeldt设计并实现.Validator框架从Struts 0.5时代就可以使用,但那时Validator框架只是被捐助的一个jar包.Apache组织为了使开发人员更方便地使用Validator框架,决定从Struts1.1开始,将Validator框架作为Struts的一部分同Struts一起发布. Validator框架可以在XML文件中配置验证规则和验证对象.因此,

Hibernate Validator验证框架中@NotEmpty、@NotBlank、@NotNull 的区别

Hibernate Validator验证框架中@NotEmpty.@NotBlank.@NotNull的主要使用情况 @NotEmpty  用在集合类上面 @NotBlank   用在String上面 @NotNull     用在基本类型上 原文地址:https://www.cnblogs.com/zhaofeng555/p/9184368.html

Validator验证Ajax提交表单的方法

当我们在一些稍微复杂的业务时,可能会遇到需要多个表单form在同一个页面的情况,但是提交一个表单以后不想页面刷新或者跳转,那么我们考虑到的就是Ajax提交表单,那么如何让Jquery的validator插件也可以对异步提交的表单进行验证呢?我们继续往下看. 在这里,我就用网络上的一个例子来说明好了. 下面是一个比较常见的jquery .ajax提交表单的写法 Js代码   $("#submitButton").click(function(){ //序列化表单 var param = 

jQuery 的 validator 验证动态添加的信息

jQuery.validator.addMethod("checkChannelName", function (value, element) { var returnVal = false; var id = $('input[name="channelId"]').val(); if (value != '') { $.ajax({ url: '{:U("TourChannel/checkChannelName")}', data: {na

spring 项目中使用 hibernate validator验证输入参数

1 hibernate validator 官方文档:https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/ 在 springboot 项目中 spring-boot-starter-web 已经包含了 hibernate-validator 可以直接使用.否则需要在 maven 依赖中添加依赖项. <dependency> <groupId>org.hibernate.valid

SpringMVC使用Hibernate Validator验证用户输入

一 简介 SpringMVC支持与JSR 349 Bean Validation API的集成.借助于Bean验证,可以非常容易地将验证元数据应用到实体类,并且通过合适的视图向用户展示可能的错误结果.在模型类中可以通过注解对属性验证进行定义,常见的注解有:@Size ,@Email ,@Pattern,@Max等,分别验证长度,邮箱格式,自定义正则表达式,最大值(PS:更多相关注解可以百度或者查API) 二 测试实例 (1)新建一个动态Java web项目,然后下载"Hibernate Vali

How to create XML validator(验证器;验证程序) from XML schema

In order to check XML data for validity we have to prepare its schema XSD-file. This file will be loaded by a JAXP package to a Schema objects instance. Then we'll use Schema to produce Validator which can then be used to validate any document with t