`
cometlj
  • 浏览: 115967 次
  • 性别: 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校验器类型详解

    在探讨Struts2校验器之前,我们首先需要了解这些校验器是如何被定义和集成到框架中的。如文中所述,Struts2的内建校验器主要位于`xwork-2.0.4.jar`压缩包中的`default.xml`文件里。这个文件定义了一系列常用的数据...

    Struts2学习文档

    以上内容详细介绍了Struts2框架的核心组成部分和技术细节,包括Action的实现方式、Result的配置方法、模型驱动的概念、异常处理机制、类型转换的实现、输入校验的流程、拦截器的设计与应用以及日志记录的配置。...

    Java实训教程 Java软件开发实战 Java开发框架介绍 struts2_7_数据验证 共56页.pptx

    除了基本的手动编程和框架内置验证外,Struts2还支持更高级的数据验证用法,如自定义校验器和visitor校验器的应用方法等。 1. **自定义校验器**: - 可以通过扩展Struts2提供的校验器类来自定义验证规则。 - 适用...

    struts2验证框架参数

    Struts2的核心特性之一就是其强大的验证机制,该机制允许开发者在请求到达控制器之前对用户输入进行检查,确保数据的完整性和正确性,从而避免潜在的运行时错误或安全漏洞。 ### Struts2验证框架的关键属性和语法 ...

    深入浅出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笔记

    Struts2中的错误处理机制主要通过`addFieldError`方法实现,该方法用于在表单验证失败时添加错误信息到用户界面。例如: ```java // 添加字段级别的错误信息 addFieldError("username", "用户名不能为空"); ``` 这...

    JavaEye论坛热点月报 总第8期

    - **关于Struts2中visitor校验器的解决方法**:针对Struts2框架的验证机制,特别是visitor校验器的使用方法和常见问题的解决方案。 3. **其他技术** - **g1安装Android软件详细攻略**:为Android开发者提供了...

    Struts2验证框架的配置及validation.xml常用的验证规则

    本文将详细介绍Struts2验证框架的配置方法以及validation.xml文件中常用的验证规则。 ### 验证框架的配置 在Struts2中,验证主要通过在Action类的关联配置文件validation.xml中定义规则来实现。该文件通常与Action...

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

    在`Demo18_Visitor`中,可能存在`ConcreteVisitorA`和`ConcreteVisitorB`这样的类,它们分别实现`Visitor`接口中的方法,执行不同的操作。 3. **元素接口(Element)**: 元素接口定义了一个接受访问者的接收方法...

    访问者模式VisitorPattern

    2. 定义元素接口或类,通常会有一个`accept(Visitor)`方法,接收访问者并调用相应的访问方法。 ```java public abstract class Element { public abstract void accept(Visitor visitor); } public class Employee...

    深入浅出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...

    C++ Visitor模式

    Visitor模式是设计模式中的一种行为模式,它在对象结构中引入了一个访问者角色,使得访问者能够对结构中的每个元素进行操作,而不改变元素本身的行为。这种模式允许我们在不修改已有类的情况下增加新的操作,遵循了...

    Laravel开发-visitor

    控制器方法可以接收请求并更新数据库中的访问记录。 3. **模型** (app/Models/): 创建一个 `Visitor` 模型,用于代表数据库中的访问记录。模型将与数据库表关联,提供插入、更新和查询数据的方法。表可能包含如 `...

    设计模式系列之visitor

    "设计模式系列之visitor"是一个关于软件设计模式的讨论,特别是关注于“访问者”(Visitor)模式。这个模式是GOF(Gamma, Helm, Johnson, Vlissides)在他们的经典著作《设计模式:可复用面向对象软件的基础》中提出...

    Visitor

    "Visitor" 在IT行业中可能指的是一个设计模式,即“访问者模式”。访问者模式是一种行为设计模式,它允许我们定义一种在多种不同对象结构中访问、改变或增加新行为的操作方式,而无需改变这些对象的结构。这个模式的...

Global site tag (gtag.js) - Google Analytics