`
cometlj
  • 浏览: 114065 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

关于Struts2中visitor校验器的解决方法

阅读更多

   这段时间重新开始拾起JAVA的学习,也是为了以后的工作打算,积累一些经验。

 

   记得开始的时候,学习Struts2中的输入校验,就对Vistor校验器情有独钟。首先,一般我们在提交表单的时候,对表单的各字段就要有校验的过程,实际部署过程中要分 客户端校验 和服务器端校验。 客户端校验使用rapid validation等第三方客户端校验框架就可以实现,而且比Struts2本身自带的客户端校验方式更好,但服务器端校验却可以分为好几种:

 

 

1.如果在Action中只有一个处理逻辑的话,可以重写ActionSupport中的validate()方法。

 

2.如果在Action中存在多个类似于execute的处理逻辑的话,我们可以重写validateXxx()方法(Xxx为不同的处理逻辑名称,例如有validateRegist()方法,就是处理Regist业务逻辑)

 

3.编写对应于Action的validate 的xml文件。这个应该是最为常用的一种解决方案了,但是有一个问题,Action众多,或者在Action中有多个对应一个或多个POJO的处理逻辑,那么这些xml文件就会随着Action文件和处理逻辑的增加而相应的增加,这显然不是个好的现象。  所以如果只是针对POJO来写相应的validate xml文件,无疑会好很多。  这就是Visitor校验器的功用了。

 

     很多和我一样的初学者可能手边都有一般李刚写的 《Struts 2 权威指南》,里面正好讲了visitor校验器,但是我照着书上讲的步骤重复做了N次都没有正确,于是乎在网上搜索了相关的文章,最后终于发现书上没有讲完整  (P280-P281)

 

以下我来举个例子:

 

  我建立了一个User的POJO,处理逻辑为UserAction, 测试页面为login.jsp

login.jsp

<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>用户登录页面</title>
		<style type="text/css">
.errorMessage {
	font-weight: bold;
	color: red;
}
</style>
	</head>
	<body>		
		<s:form action="pro_login.do">
			<s:textfield name="user.username" label="用户名称" />
			<s:password name="user.userpwd" label="登录密码" />
			<s:submit value="登 录" />
		</s:form>
	</body>
</html>

 

 

  那么我的Visitor校验器为

 

 

 UserAction-validation.xml 

  

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
	<field name="user">
		<field-validator type="visitor">
			<param name="context">userContext</param>
			<param name="appendPrefix">true</param>
			<message></message>
		</field-validator>
	</field>
</validators>

 

 

 -------------------------------------------------------------------

(注:context参数可以随便设置,只要保持一致就可以了)

 -------------------------------------------------------------------

User-userContext-validate.xml

 

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
 "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
    <field name="username">
        <field-validator type="requiredstring">
            <message>请输入用户名称</message>
        </field-validator>
    </field>
    <field name="userpwd">
        <field-validator type="requiredstring">
        	<message>请输入登录密码</message>
        </field-validator>
    </field>
</validators>

 

 

 

 

 

 

其中context参数将作为验证User类属性的文件名的一部分,如user属性返回一个User对象,那么用于验证User对象属性的文件名为User-abc-validation.xml

      这个文件要和User.class文件在同一个目录中。也就是要放到你的POJO文件相同的目录路径下,不然的话Visitor校验器就不会起作用。

     这个就是李刚老师没有写全的地方,附加个项目截图就更为清楚了。



 

 



 这样的话,Visitor校验器就起作用了。

 

 

 

 

 

 



 

  • 大小: 10.2 KB
  • 大小: 27.6 KB
分享到:
评论
26 楼 kjj 2009-02-03  
这也叫答案,xml验证放到annotations 里,况且,reuserpwd 从那里获取
25 楼 qchong 2009-01-21  
<div class="quote_title">kjj 写道</div>
<div class="quote_div">
<div class="quote_title">qchong 写道</div>
<div class="quote_div">
<div class="quote_title">jiyanliang 写道</div>
<div class="quote_div">
<div class="quote_title">kjj 写道</div>
<div class="quote_div">password 和repasswrod 可以设置到pojo的属性,然后验证用表达式来做</div>
<br />这个设置岂不是变成了dto了?</div>
<br />干嘛要把repassword设置到POJO的属性?repassword本身只是来确保密码输入正确的,又不是ENTITY的一个属性,传给ACTION用expression验证不就可以了 <br /></div>
<br />传给action 后怎么用exp 验证,还请教!</div>
<pre name="code" class="java">@FieldExpressionValidator(message = "两次密码必须一致", fieldName = "user.userpwd", expression = "user.userpwd == reuserpwd")</pre>
<p> </p>
<p> </p>
24 楼 kjj 2009-01-20  
qchong 写道
jiyanliang 写道
kjj 写道
password 和repasswrod 可以设置到pojo的属性,然后验证用表达式来做

这个设置岂不是变成了dto了?

干嘛要把repassword设置到POJO的属性?repassword本身只是来确保密码输入正确的,又不是ENTITY的一个属性,传给ACTION用expression验证不就可以了

传给action 后怎么用exp 验证,还请教!
23 楼 qchong 2009-01-19  
<div class="quote_title">jnduan 写道</div>
<div class="quote_div">
<div class="quote_title">cometlj 写道</div>
<div class="quote_div">
<p>        很多和我一样的初学者可能手边都有一般李刚写的 《Struts 2 权威指南》,</p>
</div>
<p><br />首先特别感兴趣这句话。</p>
<p> </p>
<p>其次,该功能我在struts2下用纯annotation方式没有配置成功,struts2的doc关于annotation也是几句带过,关键就是那个context还没搞明白怎么用annotation声明,别告诉我用xml,因为我已经用了annotation,不想写xml。等高人解惑。</p>
<p> </p>
<pre name="code" class="java"> @Validations(
visitorFields = {
@VisitorFieldValidator(message = "Default message", fieldName="user.username", shortCircuit = true, appendPrefix = true),
@VisitorFieldValidator(message = "Default message", fieldName="user.password", shortCircuit = true, appendPrefix = true)
        }
)</pre>
<p> </p>
</div>
<p><br />难道你不懂实现 ModelDriven,Preparable?</p>
22 楼 qchong 2009-01-19  
jiyanliang 写道
kjj 写道
password 和repasswrod 可以设置到pojo的属性,然后验证用表达式来做

这个设置岂不是变成了dto了?

干嘛要把repassword设置到POJO的属性?repassword本身只是来确保密码输入正确的,又不是ENTITY的一个属性,传给ACTION用expression验证不就可以了
21 楼 jiyanliang 2009-01-19  
kjj 写道
password 和repasswrod 可以设置到pojo的属性,然后验证用表达式来做

这个设置岂不是变成了dto了?
20 楼 guse520 2009-01-19  
向楼主推荐jquery的验证框架,非常好用
19 楼 kjj 2009-01-18  
flysunsystem 写道
struts2验证是个大败笔,哈哈。信不信有你,如果没有改源码的水平,要是有正式项目敢用struts2验证的说下。

第一次听人这么说!不过这样的话,我发现,基于announced 的Hibernian validat 更方便
18 楼 flysunsystem 2009-01-08  
struts2验证是个大败笔,哈哈。信不信有你,如果没有改源码的水平,要是有正式项目敢用struts2验证的说下。
17 楼 cometlj 2009-01-06  
<div class='quote_title'>kjj 写道</div>
<div class='quote_div'>password 和repasswrod 可以设置到pojo的属性,然后验证用表达式来做</div>
<p><br/><br/>  多谢 <strong>kjj</strong> 提醒,现在把改进的能够进行确认密码检测的代码放上来,本地测试通过 </p>
<p> </p>
<p>修改后的User的POJO为(<span style='color: #ff0000;'>repass</span>为添加的属性)</p>
<pre name='code' class='java'>package org.lj.domain.hibernate;

import java.util.Date;

/**
* User entity.
*
* @author MyEclipse Persistence Tools
*/

public class User implements java.io.Serializable {

// Fields

private Integer id;
private String username;
private String userpwd;
private String repass;
private Date createdAt;
private Date updatedAt;

// Constructors

/** default constructor */
public User() {
}

/** minimal constructor */
public User(String username, String userpwd, Date createdAt) {
this.username = username;
this.userpwd = userpwd;
this.createdAt = createdAt;
}

/** full constructor */
public User(String username, String userpwd, Date createdAt, Date updatedAt) {
this.username = username;
this.userpwd = userpwd;
this.createdAt = createdAt;
this.updatedAt = updatedAt;
}

// Property accessors

public Integer getId() {
return this.id;
}

public void setId(Integer id) {
this.id = id;
}

public String getUsername() {
return this.username;
}

public void setUsername(String username) {
this.username = username;
}

public String getUserpwd() {
return this.userpwd;
}

public void setUserpwd(String userpwd) {
this.userpwd = userpwd;
}

public Date getCreatedAt() {
return this.createdAt;
}

public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}

public Date getUpdatedAt() {
return this.updatedAt;
}

public void setUpdatedAt(Date updatedAt) {
this.updatedAt = updatedAt;
}

public String getRepass() {
return repass;
}

public void setRepass(String repass) {
this.repass = repass;
}

}</pre>
<p> </p>
<p><br/>修改的User-userContext-validation.xml 为</p>
<pre name='code' class='java'>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd"&gt;
&lt;validators&gt;
&lt;field name="username"&gt;
&lt;field-validator type="requiredstring"&gt;
&lt;message&gt;请输入用户名称&lt;/message&gt;
&lt;/field-validator&gt;
&lt;/field&gt;
&lt;field name="userpwd"&gt;
&lt;field-validator type="requiredstring"&gt;
&lt;message&gt;请输入密码&lt;/message&gt;
&lt;/field-validator&gt;
&lt;field-validator type="fieldexpression"&gt;
&lt;param name="expression"&gt;&lt;![CDATA[(userpwd==repass)]]&gt;&lt;/param&gt;
&lt;message&gt;确认密码不正确&lt;/message&gt;
&lt;/field-validator&gt;
&lt;/field&gt;
&lt;/validators&gt;</pre>
<p> </p>
<p><br/>User-validation.xml不用改变--------从这点我们也可以看出用Visitor校验器的好处了,就是直接在POJO里操作,相应的修改参数context属性的xml文件,很方便的</p>
<p> </p>
<p>相应的测试页面为register.jsp</p>
<p> </p>
<pre name='code' class='java'>&lt;%@ page language="java" pageEncoding="UTF-8"%&gt;
&lt;%@ taglib prefix="s" uri="/struts-tags"%&gt;
&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;head&gt;
&lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;
&lt;title&gt;用户注册页面&lt;/title&gt;
&lt;link href="utils/css/public.css" type="text/css" rel="stylesheet" /&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;div id="all"&gt;
&lt;div id="header"&gt;header&lt;/div&gt;
&lt;div id="content"&gt;
&lt;div&gt;已有账户,&lt;a href="login.do"&gt;登录&lt;/a&gt;&lt;/div&gt;
&lt;s:form action="pro_register.do"&gt;
&lt;s:textfield name="user.username" label="用户名称" /&gt;
&lt;s:password name="user.userpwd" label="登录密码" /&gt;
&lt;s:password name="user.repass" label="确认密码" /&gt;
&lt;s:submit value="注 册" /&gt;
&lt;/s:form&gt;
&lt;/div&gt;
&lt;div id="footer"&gt;footer&lt;/div&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;</pre>
<p> </p>
<p>两次输入的密码不同,检测成功</p>
<p>确认密码不正确的截图如下:</p>
<p><br/><img src='/upload/attachment/66403/731bd882-4561-35d6-b260-6d160bf18ecf.jpg' alt=''/><br/> </p>
<p> </p>
<p> </p>
16 楼 kjj 2009-01-06  
password 和repasswrod 可以设置到pojo的属性,然后验证用表达式来做
15 楼 ztroma 2009-01-06  
ffyahoo 写道
我有几个问题:
1. 我之前写的好像要是内网服务器无法访问到外网的时候 或者网络差的时候 就会抛出异常,怎么让他在脱机情况下也可以用这个validation?
2. 这个验证是在server端验证吗?
3. 如果是,为什么不考虑用js验证呢?何必让server端来承受不必要的开销呢?


1.这个问题是不应该出现的,如果真的有,我猜想可能是去网络上寻找你在xml文件开始定义的dtd文件吧?

2. 是在server端验证的,你如果在struts2源代码中关于验证表单相关的部分代码设置断点,会发现框架会把验证到的错误加到一个map里面的。

3. js验证一般只是用来验证的第一步,就像银行,银行的铁门是js,而银行装钱的保险柜就是更深层的验证。其实struts2的form标签提供了一个自动生成js代码的属性的,好像是validate="true"?只是它生成的代码不太好用,也难以阅读,所以还不如我们自己去写,这样也便于代码的理解和管理。
14 楼 cometlj 2009-01-05  
ffyahoo 写道
我有几个问题:
1. 我之前写的好像要是内网服务器无法访问到外网的时候 或者网络差的时候 就会抛出异常,怎么让他在脱机情况下也可以用这个validation?
2. 这个验证是在server端验证吗?
3. 如果是,为什么不考虑用js验证呢?何必让server端来承受不必要的开销呢?

第一个问题:我确实没遇到过这种情况,因为这个是服务器端的验证,所以我想你所说的内网访问外网或者脱机情况下也使用这个validation的话,我想是不可能的。
第二个问题:这个是Sever端的验证方式
第三个问题:JS验证当然也要用的,在实际的部署中,我们是要客户端验证和服务器端验证同时都有的。不然如果用户禁用了Javascript功能,或者通过其他的方式来Crack,我想后果是不堪设想的。至于你说的Server端不必要的开销,我想这个是正常的,不过通过客户端JS验证,基本90%的恶意或者非恶意输入产生的错误都在客户端被检测出来了,我想留个服务器的压力,在客户端和服务器端验证均存在的时候,也不是很大的。至少,在安全方面考虑,Client端和Server端的验证都要有。
13 楼 jnduan 2009-01-05  
<div class='quote_title'>cometlj 写道</div>
<div class='quote_div'>
<p>        很多和我一样的初学者可能手边都有一般李刚写的 《Struts 2 权威指南》,</p>
</div>
<p><br/>首先特别感兴趣这句话。</p>
<p> </p>
<p>其次,该功能我在struts2下用纯annotation方式没有配置成功,struts2的doc关于annotation也是几句带过,关键就是那个context还没搞明白怎么用annotation声明,别告诉我用xml,因为我已经用了annotation,不想写xml。等高人解惑。</p>
<p> </p>
<pre name='code' class='java'> @Validations(
visitorFields = {
@VisitorFieldValidator(message = "Default message", fieldName="user.username", shortCircuit = true, appendPrefix = true),
@VisitorFieldValidator(message = "Default message", fieldName="user.password", shortCircuit = true, appendPrefix = true)
        }
)</pre>
<p> </p>
12 楼 ffyahoo 2009-01-05  
我有几个问题:
1. 我之前写的好像要是内网服务器无法访问到外网的时候 或者网络差的时候 就会抛出异常,怎么让他在脱机情况下也可以用这个validation?
2. 这个验证是在server端验证吗?
3. 如果是,为什么不考虑用js验证呢?何必让server端来承受不必要的开销呢?
11 楼 coolhty 2009-01-04  
好东西,回去试一下..刚刚接触2.0

要学的东西太多了,而且这些框架更新又快..
10 楼 cometlj 2009-01-04  
jiyanliang 写道
那还真不如在Action里重写validate()方法。。

    当然,每个人有每个人的写法。我只是觉得在Visitor校验器比较适应于对一个POJO的复合属性进行检测,不用每次都必须重写Action里的validate方法,而且,对于在一个Action里有多个类似于execute()处理逻辑的时候,就要重写多个validateXxx()方法了。 
9 楼 jiyanliang 2009-01-04  
那还真不如在Action里重写validate()方法。。
8 楼 cometlj 2009-01-04  
jiyanliang 写道
密码和确认密码怎么配置呢?

Visitor 适用于检测Action中的复合属性,例如在一个Action里包含了User类型的属性。如果要检测密码和确认密码的功能,可以使用字段表达式校验器。或者,更为负责任的解决方法是 手动验证 ,既在Action里重写validate()方法,或者是重写validateXxx()方法。
7 楼 kjj 2009-01-03  
cometlj 写道
kjj 写道
我也做过,一直为好多actions 各自配置validator 发愁,vistor 验证可以解决这个问题吧!

  visitor校验器,按我的理解就是:从最根本的POJO验证出发,所有的action验证都是遵循POJO里验证的规则,这样无疑会节省很多代码,而且业务逻辑更简洁明了。

这个到好,可是如果这样配了,有些action 不需要验证又怎么办呢

相关推荐

    Visitor校验器 域对象级别上验证(完整示例源码)

    struts2中Visitor校验器以及域对象级别上验证和使用上下文优化的使用,我自己写的一个完整代码,详细的展示了如何使用Visitor校验器以及怎样在域对象上验证和注意事项,代码解压后可以直接部署到MyEclipse上运行,...

    深入浅出Struts2(附源码)

    9.2 Struts中的国际化支持 185 9.3 text标签 188 9.4 i18n标签 191 9.5 以手动方式选择一个资源包 193 9.6 小结 195 第10章 Model Driven和Preparable拦截器 196 10.1 把动作与模型隔离开 196 10.2 Model ...

    struts2.1.6 convertion,rest两插件的例子

    struts2.1.6 convertion插件(即注释方式配置)的helloworld 默认调用index()方法 文档说明用struts.xml中标签设置值,好象不用也行 rest插件例子 默认调用 create()方法 struts2.1.6 vistor校验例子 都是我测试例子,...

    深入浅出Struts 2 .pdf(原书扫描版) part 1

    9.2 Struts中的国际化支持 185 9.3 text标签 188 9.4 i18n标签 191 9.5 以手动方式选择一个资源包 193 9.6 小结 195 第10章 Model Driven和Preparable拦截器 196 10.1 把动作与模型隔离开 196 10.2 Model Driven...

    Visitor

    Visitor

    设计模式C++学习之访问者模式(Visitor)

    设计模式C++学习之访问者模式(Visitor)

    Visitor模式Visitor模式

    Visitor模式.docVisitor模式.doc

    Laravel开发-visitor

    Laravel开发-visitor 以数据库、页面点击量记录您的访问者,并为Laravel 5生成访问计数器

    试试visitor设计模式

    也许最开始出现这种模式,是因为另外的原因: 我有一堆数据放在一个库里头,不想让其它人拿着, 如果你要用数据干活,那你就把函数指针给我,我来替你使用这个数据。...然后人们就说,这是visitor模式。

    Visitor模式

    该PPT包含了Visitor里面所有的知识点和扩展,对于想要学习该模式的人来说是不二的选择,并且配上了源代,未经允许不可传至其他网站。

    Visitor TT1 BRK

    Visitor TT1 BRK

    visitor.js.zip

    visitor.js这个js文件能提供你关于你的网站的访客的详细信息(比如他在哪个城市,最后访问日期等等)。 该软件已改名为 session.js

    C++ Visitor模式

    23种设计模式之二十(行为模式)Visitor模式

    Laravel开发-visitor-log

    Laravel开发-visitor-log Laravel 4记录所有访客的包

    AXS Visitor Tracking System

    不错的统计+访客跟踪程序

    visitor pattern

    NULL 博文链接:https://zhang-yingjie-qq-com.iteye.com/blog/344236

    访问者模式VisitorPattern

    访问者模式(Java代码实现),博文附件

    设计模式系列之visitor

    博文链接:https://notguru.iteye.com/blog/78260

Global site tag (gtag.js) - Google Analytics