EasyJWeb的验证系统的Bug及使用心得

本文分享了在使用EasyJWeb进行用户注册时遇到的验证功能Bug,并详细记录了问题定位与解决过程,最终实现了预期的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

<iframe align="top" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog01.html" frameborder="0" width="728" scrolling="no" height="90"></iframe>


今天使用EasyJWeb的“人性化”验证功能,发现了存在不少Bug,这里发出来并与大家分享。

我们系统中的User基类的内容如下:

@Entity
@Cache(usage
=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@javax.persistence.Table(name
="UserInfo")
@Inheritance(strategy
=InheritanceType.JOINED)
@FormPO(inject
="name,email,password,problem,solution")
publicabstractclassUserimplementsPrincipal,UserDetails...{

privatestaticfinallongserialVersionUID=2915030721449148555L;

@Id
@GeneratedValue(strategy
=GenerationType.TABLE)
privateLongid;

@Column(length
=30,unique=true)
@Field(validator
=@Validator(name="string",value="blank;trim;max:30",required=true))
privateStringname;

@Column(length
=100)
@Field(validator
=@Validator(name="email",required=true,value="max:100"))
privateStringemail;

@Column(length
=64)
@Field(validator
=@Validator(name="string",value="blank;trim;max:64",required=true))
privateStringpassword;

privateDateregisterTime;

privateIntegerstatus=1;//-1锁定、0未审核、1通过

privateIntegerloginTimes;

privateDatelastLoginTime=newDate();

privateStringlastLoginIP;

privateStringproblem;//密码提问

privateStringsolution;//答案

privateLongimUin;

@ManyToMany(mappedBy
="users",cascade=CascadeType.ALL)
@JoinTable(name
="User_Roles")
privateListRole>roles=newjava.util.ArrayListRole>();

@ManyToMany(cascade
=CascadeType.ALL)
@JoinTable(name
="User_Permissions")
privateListPermission>permissions=newjava.util.ArrayListPermission>();

@Transient
privateGrantedAuthority[]authorities;

...

}


下面是一个User的子类,PersonalUser的内容如下:

@FormPO(label="个人用户信息",disInject="score,activeCode")
@Entity
@Cache(usage
=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
publicclassPersonalUserextendsUser...{
/***//**
*积分
*/

privateIntegerscore;

/***//**
*真实姓名
*/

@Field(name
="真实姓名",validators=...{@Validator(name="string",value="msg:请填写您的真实姓名。;blank;min:2;max:10",required=true)})
@Column(length
=20)
privateStringtrueName;

/***//**
*身份证号
*/

@Field(name
="身份证号",validators=...{@Validator(name="regex",value="msg:请填写有效的证件号码。;expression:\d{15}|\d{17}[\dXx]",required=true)})
@Column(length
=20)
privateStringidentifyCard;

/***//**
*电话
*/

@Field(name
="电话",validators=...{@Validator(name="required",value="msg:您填写的身份证号码有误,请检查后重新提交。;blank;min:7;max:15",required=true)})
@Column(length
=20)
privateStringtel;

/***//**
*手机
*/

@Field(name
="手机",validators=...{@Validator(name="regex",value="expression:\d{11}",required=true)})
@Column(length
=25)
privateStringmobile;

..
}


下面是个人用户注册保存时的源代码:

/***//**
*保存个人注册信息
*
*
@paramform
*
@return
*/

publicPagesavePersonal(WebFormform)...{
PersonalUseruser
=form.toPo(PersonalUser.class);
if(hasErrors())returnpage("registerStep3Personal");//跳回注册页面
//执行注册操作
this.userService.addPersonalUser(user);
returnpage("success");
}



执行这个程序,针对name及password等属性的验证能正常工作。但PersonalUser中针对电话号码、身份证等属性无论如何都不能正常执行验证功能,真是郁闷啊。后来仔细发现,不但没有执行验证,尽然连值也没有传入到持久层中。因此,应该是不允许注入这些属性值的问题所允许的。于是跟踪了一下源代码,在com.easyjf.web.core.FormHandler中发现如下的内容:

publicbooleancheckFormPOWriteEnabled(Classclz,
java.beans.PropertyDescriptorproperty)
...{
booleanret=true;
FormPOformPO
=(FormPO)clz.getAnnotation(FormPO.class);
booleanhaveFound=false;
if(formPO!=null)...{
StringinjectEnabled
=formPO.inject();

if(StringUtils.hasLength(injectEnabled))...{
ret
=(","+injectEnabled+",").indexOf(","
+property.getName()+",")>=0;//找不到,则不注入
if(ret)
haveFound
=true;
}
else...{
StringdisInject
=formPO.disInject();
if(StringUtils.hasLength(disInject))
ret
=(","+disInject+",").indexOf(","
+property.getName()+",")0;//找到,则不注入
if(!ret)
haveFound
=true;
}

}

if(!haveFound&&clz.getSuperclass()!=Object.class)
ret
=checkFormPOWriteEnabled(clz.getSuperclass(),property);
returnret;
}


这个方法写得比较有意思,几行代码转了几个弯,真考验人的逻辑思维啊。他是在检查@FormPO标签中的inject或disInject属性情况。在子类中若找不到标签属性,还会到父类中去找。感觉这里问题就出来了,如果父类跟子类使用的注入指标标签不一致的话,应该就会出现问题。也就是说如果父类中使用inject来标签注入的属性,而子类中使用disInject来指定不可以注入的属性。则先在子类中发现这个属性没找到,则haveFound就为false,则到父类中去找,由于父类使用inject标识,而一般他不会把子类的属性也标识进去,所以肯定得到的结果也是false。因此,就会给我们无法注入的结果。
这应该是跟子类中想要表达的意思不一致:“也即子类规定的是除了disInject中规定的属性以外(或者是所有属性,即inject及disInject都没有用的情况下)的所有属性都可以注入”这一功能无法实现。

这不知道算不算上是一个Bug。但想了一下,这个Bug也可以完全避免,只要把父类及子类的注入标识写一致就OK了。于是我把两者的注入标识都改成了使用disInject属性。如下:

正常的User基类

@FormPO(disInject="id,status,loginTimes,lastLoginTime,lastLoginIP,roles,permissions,authorities")
publicabstractclassUserimplementsPrincipal,UserDetails...{

...

}


子类PersonalUser

@FormPO(label="个人用户信息",disInject="score")
publicclassPersonalUserextendsUser...{

..
}

然后执行刚才的用户注册程序,验证系统终于“人性化”地按我要的出来了。呵呵,大功告成,立即走人。




Trackback: http://tb.blog.youkuaiyun.com/TrackBack.aspx?PostId=1821187


EasyJWeb综述 EasyJWeb是基于java技术,用于企业级Java Web应用程序快速开发的MVC框架。框架设计构思来源于国内众多项目实践,框架的设计及实现借鉴当前主要流行的开源Web框架,如Rails、Struts、JSF、Tapestry等,吸取其优点及精华,是一个完全由来自的中国开源爱好者开发,文档及注释全部为中文的开源框架。 EasyJWeb由主要由四个部分组成: 1、核心MVC。EasyJWeb的核心是一个基于模板技术实现的MVC框架;他能让我们用非常简洁的代码写基于Java的Web应用。 2、容器及通用业务逻辑封装。作为一个旨在让基于Java的Web应用程序开发变得直接、快速、简易的框架,EasyJWeb提供了一个IoC容器,并对企业级应用中的一些通用业务逻辑(如分页、查询、DAO等)进行了抽象及封装,提供了一套可以直接操作、应用企业资源的组件及API。 3、代码生成引擎及工具。仅仅依靠一个灵活、简易的MVC核心引擎还不能最大限度的提高开发速度,因此EasyJWeb还提供了一个灵活、易用的代码生成引擎及工具,通过使用代码生成引擎,可以快速完成基于JavaEE平台的企业级应用程序生成。如数据库添删改查(CRUD)代码生成、自动页面模版生成、自动配置文件管理等。 4、EasyJWeb插件体系,项目中的各种实用功能的扩展,可以灵活地通过基于插件的形式安装到EasyJWeb中,提供各种针对性的功能。如ajax实用插件、代码生成插件等。
EasyJWeb是基于java技术,用于企业级Java Web应用程序快速开发的MVC框架。框架设计构思来源于国内众多项目实践,框架的设计及实现借鉴当前主要流行的开源Web框架,如Rails、Struts、JSF、Tapestry等,吸取其优点及精华,是一个完全由来自的中国开源爱好者开发,文档及注释全部为中文的开源框架。 EasyJWeb由主要由四个部分组成:   1、核心MVC。EasyJWeb的核心是一个基于模板技术实现的MVC框架;他能让我们用非常简洁的代码写基于Java的Web应用。    2、容器及通用业务逻辑封装。作为一个旨在让基于Java的Web应用程序开发变得直接、快速、简易的框架,EasyJWeb提供了一个IoC容器,并对企业级应用中的一些通用业务逻辑(如分页、查询、DAO等)进行了抽象及封装,提供了一套可以直接操作、应用企业资源的组件及API。    3、代码生成引擎及工具。仅仅依靠一个灵活、简易的MVC核心引擎还不能最大限度的提高开发速度,因此EasyJWeb还提供了一个灵活、易用的代码生成引擎及工具,通过使用代码生成引擎,可以快速完成基于JavaEE平台的企业级应用程序生成。如数据库添删改查(CRUD)代码生成、自动页面模版生成、自动配置文件管理等。    4、EasyJWeb插件体系,项目中的各种实用功能的扩展,可以灵活地通过基于插件的形式安装到EasyJWeb中,提供各种针对性的功能。如ajax实用插件、代码生成插件等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值