Java中的验证约定
我有一个目标。让我们称之为“Customer”,它是从JSON对象序列化的。Customer有许多不同的字段,但为了简单起见,假设它有二十个字段(其中五个是电话号码)。验证这些字段是否有某种约定?我创建了一个巨大的方法来检查每个字段本身,或者通过调用一个方法来检查特定的长度限制、电子邮件降格和验证、电话号码从所有非数字值中删除、长度检查和验证,等等Java中的验证约定,java,Java,我有一个目标。让我们称之为“Customer”,它是从JSON对象序列化的。Customer有许多不同的字段,但为了简单起见,假设它有二十个字段(其中五个是电话号码)。验证这些字段是否有某种约定?我创建了一个巨大的方法来检查每个字段本身,或者通过调用一个方法来检查特定的长度限制、电子邮件降格和验证、电话号码从所有非数字值中删除、长度检查和验证,等等 所有这些方法都保存在Customer类中,对我来说,它开始变得有点草率了。我是否应该创建另一个名为CustomerValidators的类?可能还有
所有这些方法都保存在Customer类中,对我来说,它开始变得有点草率了。我是否应该创建另一个名为
CustomerValidators
的类?可能还有其他几个类,如电子邮件验证程序
,电话验证程序
等。?这里有什么我不知道的习俗吗 当然有。它是否适合您取决于您的环境。尝试JSR-303 Bean验证。它允许您执行以下操作:
public class Customer {
@Size(min=3, max=5) //standard annotation
private String name;
@PhoneNumber(format="mobile") //Custom validation that you can write
private String mobile;
@PhoneNumber(format="US Landline") //... and reuse, with customisation
private String landline
@Email //Or you can reuse libraries of annotations that others make, like this one from Hibernate Validator
private String emailAddress;
//... ignoring methods
}
在我看来,这方面最好的文档是用于规范的实现。您的客户对象是否特定于用例?我建议为服务调用公开特定于用例的对象。然后,来自此对象的数据映射到可重用的富域对象。(如使用推土机) 我们为服务输入/输出有效负载提供特定于用例的对象的原因是“不要泄气”原则(即契约优先原则)——通过这种方式,您可以在不影响服务订阅者的情况下改进应用程序模型 现在验证:
- 您可以使用基于注释的JSR-303验证来验证输入是否在可接受的范围内
- 更复杂的规则用富域模型上的方法表示。避免贫乏的领域类反模式-让它们具有丰富的OO行为。为此,他们可能需要招募合作者。使用依赖注入来提供这些。非容器管理类的eg持久模型实例上的DI可以使用Spring的@Configurable注释(以及其他方法)实现
{
"$schema": "http://json-schema.org/schema#",
"id": "http://your-server/path/to/schema#",
"title": "Name Of The JSON Schema",
"description": "Simple example of a JSON schema",
"definitions": {
"date-time": {
"type": "object",
"description": "Example of a date-time format like '2013-12-30T16:15:00.000'",
"properties": {
"type": "string",
"pattern": "^(2[0-9]{3})-(0[1-9]|1[012])-([123]0|[012][1-9]|31)[T| ]?([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(.[0-9]{1,3}[Z]?)?$"
}
}
},
"type": "object",
"properties": "{
"nameOfField": {
"type": "string"
},
"nameOfSomeIntegerArray": {
"type": "array",
"items": {
"type": "integer"
},
"minItems": 0,
"maxItems": 30,
"uniqueItems": true
},
"nameOfADateField": {
"$ref": "#/definitions/date-time"
}
},
"required": [ "nameOfRequiredField1", "nameOfRequiredField2" ],
"additionalProperties": false
}
定义部分允许使用“$ref”
定义某些元素。“$ref”
后面的URI以#
开头,这意味着它引用了本地模式<代码>http://your-server/path/to/schema可以这么说。在上面的示例中,它定义了一种日期时间格式,可用于验证JSON字段,并为其设置了对日期时间定义的引用。如果字段中的值不匹配,则正则表达式验证将失败
在Java中,有几个库可用。我现在用的是弗朗西斯·加利格的。使用此框架验证JSON对象非常简单:
public boolean validateJson(JsonObject json) throws Exception
{
// Convert the JsonObject (or String) to a internal node
final JsonNode instance = JsonLoader.fromString(json.toString());
// Load the JsonSchema
final JsonNode schema = JsonLoader.fromResource("fileNameOfYourJsonSchema");
// Create a validator which uses the latest JSON schema draft
final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
final JsonValidator validator = factory.getValidator();
// Validate the JSON object
final ProcessingReport report = validator.validate(schema, instance);
// optional error output
final Iterator<ProcessingMessage> iterator = report.iterator();
while( iterator.hasNext() )
{
final ProcessingMessage message = iterator.next();
System.out.println(message.getMessage());
// more verbose information are available via message.getJson()
}
return report.isSuccess();
}
public boolean validateJson(JsonObject json)引发异常
{
//将JsonObject(或字符串)转换为内部节点
最终的JsonNode实例=JsonLoader.fromString(json.toString());
//加载JsonSchema
最终JsonNode模式=JsonLoader.fromResource(“fileNameOfYourJsonSchema”);
//创建一个使用最新JSON模式草案的验证器
最终JsonSchemaFactory工厂=JsonSchemaFactory.byDefault();
final JsonValidator validator=factory.getValidator();
//验证JSON对象
final ProcessingReport=validator.validate(模式、实例);
//可选错误输出
final Iterator Iterator=report.Iterator();
while(iterator.hasNext())
{
final ProcessingMessage=iterator.next();
System.out.println(message.getMessage());
//更多详细信息可通过message.getJson()获得
}
返回报告。isSuccess();
}
我认为您关于创建CustomerValidation
和其他类的建议非常好。也许你可以在用户输入这些信息时执行验证,即客户端验证。有关应用JSR303的详细信息,请参阅@GaryF的答案