很多开发人员一直都在抱怨,除了java代码,他们还要管理众多的xml配置文件。有了最近增加到java的元数据,通过使用标注(注解),框架里的普通详细配置信息现在都可以嵌入java文件里了。sun的文章“j2se 5.0 概要”(”j2se 5.0 in a nutshell.”)对元数据和标注进行了简要介绍。
这篇文章中,我们将总结现今的配置数据是如何管理的,紧接着的一个实现,标注如何在一个简单的验证框架使用,描述了日后元数据将提供什么样的功能。
版权声明:任何获得matrix授权的网站,转载时请务必保留以下作者信息和链接
作者:jacob hookomginge(作者的blog:http://blog.matrix.org.cn/page/ginge)
原文:http://www.onjava.com/pub/a/onjava/2005/01/19/metadata_validation.html
译文:http://www.matrix.org.cn/resource/article/44/44151_metadata_validation.html
关键字:metadata;validation
使用框架的今天
在我们日常的作业中,我们都使用了框架来处理这些事情,例如持久化,用户输入,验证,web服务以及工作流。为了与这些框架一起工作,我们不得不通过不同的方法在业务对象里做绑定。一些开发人员使用的与框架绑定的方法是:
1,实现或者继承框架提供的类。一个这样的例子就是为了处理用户的输入,struts里继承actionform。为了能够使用该框架,这是强制的,并且需要开发人员编写和维护专门的业务对象(employee对象和employeeform)。
2,维护单独的配置文件,这些配置文件把java对象和方法映射到该框架。hibernate,struts以及javaserverface都大量的使用了xml配置文件。然而,这些对于java代码很不显眼,我们失去了编译时验证以及不得不在不同的位置维护数据――在xml文件和在不同的java文件中。
元数据将提供什么?
元数据允许我们绑定框架相关的配置数据到我们的业务对象而无须改变或者继承任何对象固有的职责。我喜欢将元数据跟javadoc注释做比较。如果你改变了一个javadoc注释,它并不会改变你的代码的行为的,除非你确实用到javadoc命令。概念上,元数据以相似的方式运作。你可以把配置数据添加到你的对象,不用改变代码的行为,除非你要寻找该特定的元数据。既然元数据以这样的方式运作,你可以使用标注(java元数据)来支持持久化,支持你的web应用框架。斟酌这个例子:
@column('usremail')
@validateemail
public void setemail(string email) {
this.email = email;
}@validaterequired
@validateemail
public void setemail(string email) {
this.email = email;
}
@validaterequired
@validatelength(min=6,max=12)
public void setpassword(string password) {
this.password = password;
}
validator.validate(loginbean, "email", "yourname@onjava.com");
validator.validate(loginbean, "password", ""); // 非法
//例子 @validatelength(min=6,max=8)
public @interface validatelength {
int min() default 0;
int max() default integer.max_value;
}
// 例子 @validateexpr("^(\\w){0,2}$");
public @interface validateexpr {
string value();
}@retention(retentionpolicy.runtime)
@target(elementtype.annotation_type)
public @interface validate {
class<? extends validatehandler> value();
}
@retention(retentionpolicy.runtime)
@target(elementtype.method)
@validate(validateexprhandler.class)
public @interface validateexpr {
string value();
}
// 如在validate标注使用的接口
public interface validatehandler<t extends annotation>
{
public void validate(t settings, object value)
throws validationexception;
public class<t> getsettingstype();
}
// 与validateexpr标注使用的处理者
public class validateexprhandler
implements validatehandler<validateexpr>
{
public void validate(validateexpr settings,
object value)
throws validationexception
{
string i = (value != null)
? value.tostring()
: "";
if (!pattern.matches(settings.value(), i))
{
throw new validationexception(i
+ " does not match the pattern "
+ settings.value());
}
}
public class<validateexpr> getsettingstype()
{
return validateexpr.class;
}
}
validator.validate(loginbean, "email", "yourname@onjava.com");
validator.validate(loginbean, "password", "");
public static void validate(annotatedelement element,
object value)
throws validationexception
{
validate v;
validatehandler vh;
annotation a;
// 抓取所有标注
annotation[] ma = element.getannotations();
for (int i = 0; i < ma.length; i++) {
// 如果一个标注拥有一个验证标注
v = ma[i].annotationtype().getannotation(validate.class);
if (v != null) {
try {
// 使用validate的值创建一个validatehandler
vh = v.value().newinstance();
// 使用当前标注作为validatehandler的状态
// 会抛出 validationexception异常
vh.validate(ma[i], value);
} catch (instantiationexception ie) {
} catch (illegalaccessexception iae) {
}
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器