Ser*_*gey 5 java validation design-patterns exception-handling
让我们想象一下,我们有一个进程,它接受以下类型的数据:
{"date":"2014-05-05", "url":"http://some.website.com","counter":3}
Run Code Online (Sandbox Code Playgroud)
date应该是一个可解析的日期,url也应该符合正常的 url 语法。date应该在未来,url应该是一个可访问的地址,返回200 OK.为了使它干净,必须将这两个验证例程分成不同的单元(类、实用程序等)。然而,所需的最终行为必须让用户清楚地了解数据中存在的所有违规行为。就像是:
{"Errors":[
"Specified date is not in the future",//Formal validation failed
"Specified URL has invalid syntax"//Logical validation failed
]}
Error对象的实现,并且充满了像Error.hasErrors()or之类的检查
error==null,这看起来并不优雅。javax.validation,它同时为您提供所有领域的所有违规行为。可以为内容验证实施相同的方法,但我不确定这是执行此操作的最佳方法。问题:处理各种性质的多个异常/违规的最佳做法是什么?
UPD:答案的简短摘要: collect Violations, build an Exception,包含它们的上下文、原因和描述,使用拦截器进行渲染。请参阅答案中的参考链接:
http://beanvalidation.org/1.0/spec/ JSR 303 规范
http://docs.spring.io/spring/docs/3.2.x/spring-framework-reference/html/validation.html Spring Bean 验证
http://docs.oracle.com/javaee/6/tutorial/doc/gircz.html Java EE 验证
您可以执行以下操作:
定义一个抽象Check类,如下:
public abstract class Check {
private final List<Check> subChecks = new ArrayList<Check>();
public Check add(Check subCheck) { subChecks.add(subCheck); return this }
public void run(Data dataToInspect, List<Error> errors) {
Error e = check(dataToInspect);
if (e != null) {
errors.add(e);
return;
}
for (Check subCheck : subChecks) {
subCheck.run(dataToInspect, errors);
}
}
// Returns null if dataToInspect is OK.
public abstract Error check(Data dataToInspect);
}
Run Code Online (Sandbox Code Playgroud)
classData是保存数据的类(需要检查)。可以是字符串、JSON 对象,等等。
类Error表示在数据中检测到的问题应该大致类似于:
public class Error {
private String problem;
public Error(String problem) { this.problem = problem }
public String getProblem() { return problem }
// maybe additional fields and method to better describe the detected problem...
}
Run Code Online (Sandbox Code Playgroud)
然后,您就有了针对数据运行检查的代码:
public class Checker {
private final List<Error> errors = new ArrayList<Error>();
private final List<Check> checks = new ArrayList<Check>();
public Checker() {
checks.add(new DateIsParsableCheck().add(new DateIsInTheFurutreCheck());
checks.add(new UrlIsWellFormed().add(new UrlIsAccessible());
checks.add();
..
}
public void check(Data d) {
for (Check c : checks) {
Error e = c.run(d, errors);
if (e != null)
errors.add(e);
}
}
}
Run Code Online (Sandbox Code Playgroud)
稍微改变了我原来的答案。在当前的答案中存在子检查的概念:如果调用的检查x有一个调用的子检查y,则y仅当检查成功时该检查才会运行x。例如,如果日期不可解析,则没有必要检查它是否是将来的。
在你的情况下,我认为所有/大多数逻辑检查应该是正式检查的子检查。
| 归档时间: |
|
| 查看次数: |
3340 次 |
| 最近记录: |