随笔:45 文章:5 评论:25 引用:0
BlogJava 首页 发新随笔
发新文章 联系 聚合管理

     摘要: 原因:首先,JFreeChart和中文验证码的乱码问题和jsp的编码无关,是由于Java虚拟机找不到字体文件造成的,所以同类的Swing或者AWT的中文乱码问题也适用

  阅读全文
posted @ 2009-01-12 17:18 Hill 阅读(4025) | 评论 (0)编辑 收藏
 
     摘要: JFreeChart真是个好东西,今天刚刚学习了一下,以后要是用时,可以深入,大家要是不知道怎么在Web中画出图表,请参考,谢谢  阅读全文
posted @ 2009-01-12 16:41 Hill 阅读(122) | 评论 (0)编辑 收藏
 

Struts Validator验证器使用指南


验证器:

从0.5版,验证器在一些form中就已经实现了,他最初包含在开发人员包中,后来核心代码挪到Jakarta Commons包中和Struts特别扩展中作为 Struts 1.1的一部分。许多开发者为方便一直使用struts验证器,这篇文档首先概述验证器的核心功能性,然后大概介绍在 struts1.1中的变化和新增功能。

如果你配置好验证器插件,你应该扩展ValidatorForm而不是ActionForm,以便它能加载你的Validator资源。他根据struts-config.xml文件中的action的name属性为当前form的调用相应的验证器,因此在validator-rules.xml中的form元素的名称属性应该与action的name属性值相匹配。

另外一种选择是扩展ValidatorActionForm 而不是ValidatorForm,ValidatorActionForm使用struts-config.xml中action的path属性,所以path属性的值相应的应该与validator-rules.xml中的Form的name属性匹配。

一个分离的action可以定义给多页form的每个页面,而且验证规则可以与action关联而不是与页码,就像验证范例中的多页form范例那样。
国际化

在validator-rules.xml 文件中form的验证规则可以组织为FormSet。FormSet 有与java.util.Locale 类相应的属性:如语言, 国家以及变量型属性,如果他们未定义,FormSet 将把它设置为默认值。一个FormSet 也可以有关联的常量。另外还可以定义与FormSet 同一级别的全局global元素,他与FormSet同样也有常量。

注意:你必须在国际化的FormSet前声明一个没有国际化的默认FormSet。这样如果Validator没有找到locale时可以有一个默认版本。

        可插入验证器的默认错误信息值可以被msg元素覆盖。所以为mask验证器生成错误信息的替代方法就是使用msg属性,如果字段的name属性与验证器的name属性匹配,那末将使用字段的msg属性。

        error messages的可以设置arg0-arg3 等参数元素。如果没有设置arg0-arg3的name属性, error messages将使用他们作为默认的构建参数值。如果设置了name属性,你就可以把参数指定给一特定的可插入验证器,然后这些参数将在构造错误信息时被使用。

<field

property="lastName"

depends="required,mask">

<msg

name="mask"

key="registrationForm.lastname.maskmsg"/>

<arg0 key="registrationForm.lastname.displayname"/>

<var>

<var-name>mask</var-name>

<var-value>^[a-zA-Z]*$</var-value>

</var>

</field>

默认的arg0-arg3元素将在消息资源中查找相应的key,如果资源属性设为false,她将把值直接传进去,而不从消息资源中查找。注意1.1版本中,你必须为每个模块中明确地定义在验证中用到的消息资源,否则将使用top-level资源。

<field

property="integer"

depends="required,integer,intRange">

<arg0 key="typeForm.integer.displayname"/>

<arg1

name="range"

key="${var:min}"

resource="false"/>

<arg2

name="range"

key="${var:max}"

resource="false"/>

<var>

<var-name>min</var-name>

<var-value>10</var-value>

</var>

<var>

<var-name>max</var-name>

<var-value>20</var-value>

</var>

</field>
常量/变量

全局的常量可以在全局标签中定义,FormSet/本地常量能在formset 标签中创建。常量当前仅仅是代替字段的property属性,字段的var 元素的 value属性,字段的msg 元素的 key属性,字段的arg0-arg3 元素的 key属性。字段的变量也可以在arg0-arg3 元素中被代替(例如:${var:min}))。替换的顺序是FormSet/Locale常量第一,全局的常量第二,

arg elements 变量最后。

<global>

<constant>

<constant-name>zip</constant-name>

<constant-value>^\d{5}(-\d{4})?$</constant-value>

</constant>

</global>

 

<field

property="zip"

depends="required,mask">

<arg0 key="registrationForm.zippostal.displayname"/>

<var>

<var-name>mask</var-name>

<var-value>${zip}</var-value>

</var>

</field>

验证器可以使用字段下面的变量部分来存储变量,这些变量通过字段的getVar((String key)方法取得。

<field

property="integer"

depends="required,integer,intRange">

<arg0 key="typeForm.integer.displayname"/>

<arg1

name="range"

key="${var:min}" resource="false"/>

<arg2

name="range"

key="${var:max}" resource="false"/>

<var>

<var-name>min</var-name>

<var-value>10</var-value>

</var>

<var>

<var-name>max</var-name>

<var-value>20</var-value>

</var>

</field>
使用validwhen设计复杂的验证

使用validwhen来设计复杂验证的一个经常的要求就是根据一个字段验证另外一个字段(比如, 如果你要用户两次输入口令来确认值口令一致),另外一个就是表单中的一个字段只有另外一个字段有确定值的时候才是必须输入的。新的validwhen验证规则将很快被包含在1.1后的STRUTS版本中,她就是用来处理这种情况的。

        validwhen 规则处理单个的变量字段,叫测试。这变量的值是一个布尔的表达式,如果验证有效则它必须为真。可以包含这种变量的表达式有:

u        单引号或双引号字符串literals,

u        十进制、十六进制、八进制的Integer literals,

u        null与null和空字符串匹配,

u        其它可以用属性名引用的form字段,例如customerAge,

u        可以在外部因用得索引字段, 例如childLastName[2],

u        可以默认implicit因用得索引字段, 例如childLastName[], 她将作为被索引的字段使用同样的索引到数组中,

The literal *这里指它包含当前测试字段的值,

作为例子,考虑一个包含通讯地址和邮箱字段的form。如果通讯地址不为空则邮箱字段是必须的required。你能这样定义validwhen 规则:

<field property="emailAddress" depends="validwhen">

<arg0 key="userinfo.emailAddress.label"/>

<var>

<var-name>test</var-name>

<var-value>((sendNewsletter == null) or (*this* != null))</var-value>

</var>

</field>

上面定义的意思是:如果通讯地址是空或不空时这个字段时有效的。

这里有个稍微复杂的例子,它使用了索引字段。假定有一个表单,允许用户输入他们希望定购的部件号和数量。类orderLine 的bean的一数组被用来在称为orderLines 的一属性保持输入项。

If you wished to verify that every line with part number also had a quantity entered, you could do it with:

如果你希望校验订单中有数量输入得每一行,你可以这样:

<field

property="quantity"

indexedListProperty="orderLines"

depends="validwhen">

<arg0 key="orderform.quantity.label"/>

<var>

<var-name>test</var-name>

<var-value>((orderLines[].partNumber == null) or (*this* != null))</var-value>

</var>

</field>

这里的意思是:如果相应的partNumber 字段是空, 或这字段是不空的,则这字段是有效的。

最后一个例子,想象一表单,用户必须输入他们的以英寸为单位的高度,如果他们在高度在60英寸以下,则出一错误。(it is an error to have checked off nbaPointGuard as a career.)

<field property="nbaPointGuard" depends="validwhen">

<arg0 key="careers.nbaPointGuard.label"/>

<var>

<var-name>test</var-name>

<var-value>((heightInInches >= 60) or (*this* == null))</var-value>

</var>

</field>

 

给程序员的简单说明:

所有的比较关系必须在parens 封装。All comparisons must be enclosed in parens.

只有两个itme时可以and或or链接。

如果比较的两item都可以转为整数,则使用numeric比较,否则使用字符串比较。
可插入验证器

验证是从validation.xml 文件中加载的,默认的验证规则定义在validation.xml 文件中,默认定义了required, mask ,byte, short, int, long, float, double, date (没有本地支持), and a numeric range。

" mask "方式依赖于默认值安装要求,那意味着"required "可以完成,在"'mask "将运行以前"required "和" mask "方式被默认包含进框架中了。任何字段如果不是"required "而且是空或有零长度将跳过其他验证。

如果使用了Javascript 标签,客户端javascript在validator's javascript 属性中查找值而且产生一个有验证form方法的对象,要得到更多的关于Javascript Validator 标签工作细节的详细的解释,参阅html标签API参考。

"'mask' "方式让你用一正则表达式掩码验证字段,它使用jakarta的正规表达式包,所有的有效性规则存储在validator-rules.xml 文件,使用的主类是org.apache.regexp.RE。

validation.xml文件中的验证器配置范例:

<validator name="required"

classname="org.apache.struts.validator.FieldChecks"

method="validateRequired"

methodParams="java.lang.Object,

org.apache.commons.validator.ValidatorAction,

org.apache.commons.validator.Field,

org.apache.struts.action.ActionErrors,

javax.servlet.http.HttpServletRequest"

msg="errors.required">

<validator name="mask"

classname="org.apache.struts.validator.FieldChecks"

method="validateMask"

methodParams="java.lang.Object,

org.apache.commons.validator.ValidatorAction,

org.apache.commons.validator.Field,

org.apache.struts.action.ActionErrors,

javax.servlet.http.HttpServletRequest"

msg="errors.invalid">


定义可插入验证器

方法的参数是用逗号分隔的一些类名称列表,方法属性需要有一个符合上面的列表的签名。列表由以下组合而成:

java.lang.Object – 要验证的Bean。

org.apache.commons.validator.ValidatorAction – 当前ValidatorAction。

org.apache.commons.validator.Field – 要验证的字段

org.apache.struts.action.ActionErrors – 如果验证错误将加入ActionError的错误对象javax.servlet.http.HttpServletRequest –当前request 对象。

javax.servlet.ServletContext – 应用的ServletContext。

org.apache.commons.validator.Validator–当前的org.apache.commons.validator.Validator实例。

java.util.Locale – 当前用户的Locale。
多页面form

字段部分有一可选的页面属性,它可以被设为整数,页上字段的所有验证小于或等于服务器端验证的当前页,页上字段的所有验证小于或等于客户端页上所有字段的验证小于或等于服务器端验证的当前页验证的当前页。一个mutli-part表单需要定义页面属性:

<html:hidden property="page" value="1"/>。
比较两个字段

这是一个展示你怎样才能比较两个字段是否有一样的值的例子。比如“用户改变他们的口令“一般会有口令字段和一确认字段。

<validator name="twofields"

classname="com.mysite.StrutsValidator"

method="validateTwoFields"

msg="errors.twofields"/>

<field property="password" depends="required,twofields">

<arg0 key="typeForm.password.displayname"/>

<var>

<var-name>secondProperty</var-name>

<var-value>password2</var-value>

</var>

</field>

 

public static boolean validateTwoFields(

Object bean, ValidatorAction va,  

Field field, ActionErrors errors, HttpServletRequest request,  

ServletContext application) {

String value = ValidatorUtils.getValueAsString( bean,   field.getProperty());

String sProperty2 = field.getVarValue("secondProperty");

String value2 = ValidatorUtils.getValueAsString( bean,   sProperty2);

 

        if (!GenericValidator.isBlankOrNull(value)) {

try {

if (!value.equals(value2)) {

errors.add(field.getKey(),

Resources.getActionError( application, request, va, field));

                             return false;

}

} catch (Exception e) {

errors.add(field.getKey(), Resources.getActionError( application, request, va, field));

return false;

}

}

}
已知的bug

Struts Validator依赖于Commons Validator包,所以问题报告和增强需求可能在两个产品中列出。

·    Struts Validator Bugzilla Reports

·    Commons Validator Bugzilla Reports
变更和deprecations

新建的标记属性。

<html:javascript>标记有新的属性定义.

使用commons-validator.jar中的DTD验证。

当前使用的验证XML文件是根据commons-validator.jar中的DTD。Struts不在为validator-rules.xml and validator.xml.单独维护一个分离的DTD,另外,commons-validator 现在维护一个统一的validator.dtd。修改所有validator.xml文件的DTD引用为

<!DOCTYPE form-validation PUBLIC

"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN"

"http://jakarta.apache.org/commons/dtds/validator_1_0.dtd">

空字段。

当前默认在所有得基础验证类型中忽略空白的字段,如果你要求一个字段必须输入,那末在你的应用的validator.xml 文件相应的字段定义的depends属性中添加 " required "。

新建的范围RANGE方法.

JavaScript 和JAVA中都添加了intRange & floatRange 方法。

有条件地REQUIRED字段.

最大的修改是添加了基于其她字段的值的有条件地require验证的能力。它允许你定义逻辑如:“只有X字段非空的时候Y字段为’male’才有效”,这是实现上述逻辑的推荐方法,这种方法在1.1版后的第一版将实现。在1.1版中添加的Requiredif验证规则,将在新版中去掉。不过,如果你正准备使用requiredif,这里有一个简短的教程。

        让我们假定你有一个有3个字段的医药的信息表单,性别sex,怀孕测试pregnancyTest,测试结果testResult,如果性别为'f' or 'F',则怀孕测试pregnancyTest是required,如果pregnancyTest不是空,测试结果testResult是required。

你的validation.xml 文件的输入项应该是这样的:

<form name="medicalStatusForm">

<field property="pregnancyTest" depends="requiredif">

<arg0 key="medicalStatusForm.pregnancyTest.label"/>

<var>

<var-name>field[0]</var-name>

<var-value>sex</var-value>

</var>

<var>

<var-name>fieldTest[0]</var-name>

<var-value>EQUAL</var-value>

</var>

<var>

<var-name>fieldValue[0]</var-name>

<var-value>F</var-value>

</var>

<var>

<var-name>field[1]</var-name>

<var-value>sex</var-value>

</var>

<var>

<var-name>fieldTest[1]</var-name>

<var-value>EQUAL</var-value>

</var>

<var>

<var-name>fieldValue[1]</var-name>

<var-value>f</var-value>

</var>

<var>

<var-name>fieldJoin</var-name>

<var-value>OR</var-value>

</var>

</field>

<field property="testResult" depends="requiredif">

<arg0 key="medicalStatusForm.testResult.label"/>

<var>

<var-name>field[0]</var-name>

<var-value>pregnancyTest</var-value>

</var>

<var>

<var-name>fieldTest[0]</var-name>

<var-value>NOTNULL</var-value>

</var>

</field>

</form>

 

这里有一个使用索引的属性更复杂的例子,如果你的struts-config.xml 有这下面:

<form-bean name="dependentlistForm"

type="org.apache.struts.webapp.validator.forms.ValidatorForm">

<form-property

name="dependents"

type="org.apache.struts.webapp.validator.Dependent[]" size="10"/>

<form-property name="insureDependents" type="java.lang.Boolean" initial="false"/>

</form-bean>

这里dependentlistForm bean有lastName,firstName,dob,coverageType四个属性,你可以这样定义一验证规则:

<form name="dependentlistForm">

<field

property="firstName" indexedListProperty="dependents" depends="requiredif">

<arg0 key="dependentlistForm.firstName.label"/>

<var>

<var-name>field[0]</var-name>

<var-value>lastName</var-value>

</var>

<var>

<var-name>fieldIndexed[0]</var-name>

<var-value>true</var-value>

</var>

<var>

<var-name>fieldTest[0]</var-name>

<var-value>NOTNULL</var-value>

</var>

</field>

 

<field

property="dob" indexedListProperty="dependents" depends="requiredif,date">

<arg0 key="dependentlistForm.dob.label"/>

<var>

<var-name>field[0]</var-name>

<var-value>lastName</var-value>

</var>

<var>

<var-name>fieldIndexed[0]</var-name>

<var-value>true</var-value>

</var>

<var>

<var-name>fieldTest[0]</var-name>

<var-value>NOTNULL</var-value>

</var>

</field>

 

<field

property="coverageType" indexedListProperty="dependents" depends="requiredif">

<arg0 key="dependentlistForm.coverageType.label"/>

<var>

<var-name>field[0]</var-name>

<var-value>lastName</var-value>

</var>

<var>

<var-name>fieldIndexed[0]</var-name>

<var-value>true</var-value>

</var>

<var>

<var-name>fieldTest[0]</var-name>

<var-value>NOTNULL</var-value>

</var>

<var>

<var-name>field[1]</var-name>

<var-value>insureDependents</var-value>

</var>

<var>

<var-name>fieldTest[1]</var-name>

<var-value>EQUAL</var-value>

</var>

<var>

<var-name>fieldValue[1]</var-name>

<var-value>true</var-value>

</var>

<var>

<var-name>fieldJoin</var-name>

<var-value>AND</var-value>

</var>

</field>

</form>

这里的意思是:

如果lastName 字段是非空的,firstName 字段required。因为字段Indexed 为真,这它意味着lastName的indexed 必须与firstName 的索引的一样,dob同理,除非date不为空。

如果lastName 用样索引时的值不空, 而且非索引字段insureDependents为真,则coverageType 是only require。

你可以对字段在[n]中使用任意数字,唯一的限制是他们必须都是AND或OR,你无法混合使用。

Deprecation:

u        JavaScript 和Java的range方法.

u        StrutsValidator &StrutsValidatorUtil 类中的Deprecation方法
验证器api指南

一个简明的Struts验证器API指南 可以帮助你开始。
验证器资源

Struts Validator: Validating Two Fields Match 作者Matt Raible。(两个字段匹配验证)关于使用方法的文章。(范例部分为翻译此文内容)

DynaForms and the Validator 作者James Turner and Kevin Bedell。Struts Kickstart的其中一章(动态form和验证器),可以自由下载PDF).

Validating user input 作者 David Winterfeldt and Ted Husted。Struts in Action的其中一章,可以自由下载(PDF)。

posted @ 2009-01-07 09:52 Hill 阅读(179) | 评论 (0)编辑 收藏
 

首先,我先大概介绍一下jpetstore的整体架构,spring的这个版本主要使用了struts+spring+ibatis的框架组合,
而在MVC层的框架,这个版本又同时提供了两个实现版本,一个是struts,一个是spring 自带的web框架,

而数据库持久层使用的是ibatis框架,这个框架是一个SQL映射框架,轻量级而且使用非常容易,基本上会

使用JDBC的朋友看一两个小时就会使用了。
下图是该应用的一个简略架构图,没有什么好的工具,就大概画了一个,虽然比较简单,不过也基本可以

概括应用的整体框架了,首先是JSP请求,通过struts-config.xml(这里只是根据struts来画的,spring其实也差不多),

请求转到相应的Action中,可以看到,这里有一个BaseAction,是所有Action实现的父类,这个类的作用稍后再讲,

然后就是每个Action通过PetStoreFacade的对象调用后台DAO对象,从而通过ibatis进行数据的持久操作,

这里使用了门面(Facade)模式,隔离了前台与后台耦合度,而PetStoreFacade就是这个门面。结合下图,

相信大家对整个jpetstore会有个大概的了解。

 

 

好了,大概的结构讲了下,接下来我们就从代码入手,在这里考虑到struts大家比较熟悉,因此,

本文是以struts版本来讲,同时声明,本文并不会一段段代码详细讲述,而只是提供一个学习的参考,

大概讲解一下流程,让大家不再茫然不知从哪开始,好了,废话也不多说了。

既然是WEB应用,那当然首先从配置文件看起,那就非web.xml莫属了,打开WEB-INF目录下的web.xml,

我们挑出目前我们应该关注的配置代码:
代码  
<servlet>    
   <servlet-name>petstore</servlet-name>    
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>    
   <load-on-startup>2</load-on-startup>    
</servlet>    
   
<servlet>    
   <servlet-name>action</servlet-name>    
   <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>    
   <load-on-startup>3</load-on-startup>    
</servlet>    
   
<servlet-mapping>    
   <servlet-name>petstore</servlet-name>    
   <!--   
   <servlet-name>action</servlet-name>   
   -->    
   <url-pattern>*.do</url-pattern>    
</servlet-mapping>
在这里可看到两个servlet设置,以及一个servlet mapping,第一个petstore的servlet是用于spring web框架的,

而第二个action的servlet就是用于struts的,而这个版本的mapping默认的是使用spring web,可以看到,<servlet-name>action</servlet-name>这一行是被注释掉了,我们要使用struts的话,那就把这个注释去掉,

改为注释掉<servlet-name>petstore</servlet-name>,好了,如此注释以后,整个应用就会以struts的框架运行。

(这些配置是什么意思?如果你还搞不懂的话,建议你先去学学基础再来研究应用吧)

接下来我们可以打开strutc-config.xml文件,这里就是struts的默认配置文件,在这里可以看到struts的相关配置信息。

好了,接下来我们就以一个请求来讲述基本的请求流程,以search为例,生成项目,再启动,

成功之后进入应用的首页,我们终于可以看到久违的鹦鹉界面了,激动吧,呵呵,在界面的右上角,

有一个Search文本框,我们就以这个Search为例子来讲解,输入一个关键字cat,然后点search,

结果出来了,这个过程的内部是如何运作的呢?

我们用鼠标右键点击页面,然后选择属性,我们看到显示的地址可能是:
http://localhost:8080/shop/searchProducts.do;jsessionid=E2D01E327B82D068FEE9D073CA33A2A3

这个地址就是我们刚才点击查询时提交的地址了,我们看到searchProducts.do这个字符串,

我们之前在web.xml里面的设置大家还记得吗?
<servlet-mapping>
   <!--
   <servlet-name>petstore</servlet-name>
   -->
   <servlet-name>action</servlet-name>
   <url-pattern>*.do</url-pattern>
</servlet-mapping>
代表着所有以.do为结尾的请求,都将被名叫action的servlet处理,也就是通过struts-config配置进行处理,那我们就去struts-config.xml里面看看,打开struts-config.xml文件,ctrl+F弹出查询界面,输入searchProducts,我们就可查到
<action path="/shop/searchProducts" type="org.springframework.samples.jpetstore.web.
struts.SearchProductsAction" name="emptyForm" scope="session" validate="false">    
<forward name="success" path="/WEB-INF/jsp/struts/SearchProducts.jsp"/>    
</action>
根据以上配置,我们可以得知,刚才我们的提交将会被SearchProductsAction处理,而该action的form是emptyForm,查找emptyForm这个别名,我们可以找到它指向一个BaseActionForm,打开这个form我们可以看到,里面只有两个validate方法和一个addErrorIfStringEmpty方法,没有任何的属性,那就是说search这个提交并没有把我们输入的关键字保存在form里面,打开SearchProductsAction,我们看到execute方法里的第一句就是

String keyword = request.getParameter("keyword");
也就是说我们输入的关键字是以参数的形式传入到request里面,参数名字为“keyword”,我们打开IncludeTop.jsp,这个文件在WEB-INF/jsp/struts目录下。

注意了,jsp目录下分别有spring以及struts两个目录,这两个目录就是分别对应两个web框架的,我们使用的是struts所以jsp代码就到struts目录里面,为什么打开IncludeTop.jsp呢,我们可以看到,无论我们进入哪个页面,search那个文本框都存在,也就是说,这个文本框是被当作一个模板插入到所有页面当中去的,我们随便打开一个页面,就可以看到页面开头都是:

<%@ include file="IncludeTop.jsp" %>
这句就是把IncludeTop.jsp当作页面头部包含进来,所以凡是包含这个头页面的页面,他们的头部都是一样的,这也是我们在开发中常用的一种方式,统一界面的一种方式,我们也可以看到在这些文件尾部也有类似的代码,如:

<%@ include file="IncludeBottom.jsp" %>

其作用也是一样。打开IncludeTop.jsp后,我们看到其中有一段代码:

<form action="<c:url value="/shop/searchProducts.do"/>" method="post">
<input type="hidden" name="search" value="true"/>
<input name="keyword" size="14"/> <input border="0" src="../images/search.gif"

type="image" name="search"/>
</form>
这段代码就是我们search文本框以及提交链接的代码,在这里就不做详细介绍了。

好了,接下来我们再看看这个action的后续代码

if (keyword != null) {  
if (!StringUtils.hasLength(keyword)) {  
   request.setAttribute("message", "Please enter a keyword to search for,

then press the search button.");  
   return mapping.findForward("failure");  
   }  
PagedListHolder productList = new PagedListHolder(getPetStore().

searchProductList(keyword.toLowerCase()));  
productList.setPageSize(4);  
request.getSession().setAttribute("SearchProductsAction_productList", productList);  
request.setAttribute("productList", productList);  
return mapping.findForward("success");  
}

这里第一句就是判断keyword是否为空,不为空就执行其中的代码,我们search的时候这个keyword肯定是不为空的,

那就是说这段if包含的代码就是我们search的处理代码了,有的人也许会说,如果我不输入关键字而直接点search呢,

这keyword不就是为空了吗?我想这个你在此处加个断点,再运行一下就知道了,虽然你没有输入,

但是keyword一样不是null,它将是一个空字符串,而不是空对象。我们看到if里面还包含有一个if,

这里就是判断keyword是否为空字符串了,StringUtils.hasLength()方式是一个工具类,

用来判断keyword是否为空字符串,如果是空字符串就返回false,而这句判断当返回false时,

因为前面有个感叹号,所以值为false就执行被if所包含的语句,里面的代码就是保存一个错误信息,然后return mapping.findForward("failure");,这句的意思就不再解释了。

现在假设我们正确输入keyword,那么程序将不会执行if语句中的代码,直接向下执行,我们看到


PagedListHolder productList = new PagedListHolder(getPetStore().

searchProductList(keyword.toLowerCase()));

这句代码,PagedListHolder是spring提供的一个用来保存查询结构类,通常用来进行分页处理,

因此我们可以知道

getPetStore().searchProductList(keyword.toLowerCase())
这一句就是用来查询,并返回查询结果的。getPetStore()这个方法是继承自BaseAction的,它将获得一个PetStoreFacade的实现,我们打开BaseAction的代码,可以看到如下代码

public void setServlet(ActionServlet actionServlet) {  
       super.setServlet(actionServlet);  
       if (actionServlet != null) {  
           ServletContext servletContext = actionServlet.getServletContext();  
       WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);  
       this.petStore = (PetStoreFacade) wac.getBean("petStore");  
       }  
}

这句代码里面最重要的一句就是

WebApplicationContext wac = WebApplicationContextUtils.

getRequiredWebApplicationContext(servletContext);
这句代码的作用就是获取一个WebApplicationContext对象wac,在这里我们只需要知道这个对象的作用,而不对其进行深入研究,通过这个对象,我们可以根据spring的配置文件,获得相应的Bean,下面这句就是用来获取相应bean的语句:


this.petStore = (PetStoreFacade) wac.getBean("petStore");
petStore这个就是bean的id,这个petStore的bean具体是哪个类呢?我们打开applicationContext.xml,可以找到以下配置代码


<bean id="petStore" class="org.springframework.samples.jpetstore.domain.logic.PetStoreImpl">
   <property name="accountDao" ref="accountDao"/>
   <property name="categoryDao" ref="categoryDao"/>
   <property name="productDao" ref="productDao"/>
   <property name="itemDao" ref="itemDao"/>
   <property name="orderDao" ref="orderDao"/>
</bean>
从这里可以看到,petStoreFacade的具体类就是PetStoreImpl,而这个类当中,分别通过spring IOC注入了几个DAO的bean,这几个DAO的配置可以在dataAccessContext-local.xml文件里面找到,我们打开PetStoreImpl这个实现类,我们看到类里有一个searchProductList方法,这个方法就是我们在Action当中调用的方法

return this.productDao.searchProductList(keywords);
从这句代码可以看出,这个方法是通过调用productDao的searchProductList方法来获得结果的,

productDao这个DAO从上面的配置文件可以看出,是通过IOC容器进行注入的,我们打开dataAccessContext-local.xml文件,可以看到

<bean id="productDao" class="org.springframework.samples.jpetstore.dao.ibatis

.SqlMapProductDao">
   <property name="sqlMapClient" ref="sqlMapClient"/>
</bean>
这句配置代表了productDao的实现类就是SqlMapProductDao,同时这个类包含有一个sqlMapClient的属性对象,这个对象也是通过ioc注入的,再在这个配置文件里,我们可以找到如下一段代码

<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
   <property name="configLocation" value="WEB-INF/sql-map-config.xml"/>
   <property name="dataSource" ref="dataSource"/>
</bean>
这段代码就是sqlMapClient这个bean的配置,这里的实现是SqlMapClientFactoryBean,它是spring专门为ibatis框架提供的一个支持,通过这个对象就可以很好的集成ibatis框架,具体的介绍可以通过spring官方文档或者是其他一些教程获得,在这里就不多做介绍。

好了,接下来我们知道了,实际查询数据是通过DAO的实现类SqlMapProductDao进行的,而SqlMapProductDao当中就是通过了ibatis进行数据的查询,从而返回结果,这里也就不多做介绍了,大家可以通过ibatis的教程获得ibatis的使用方法,非常的简单,search操作从前台到后台的大概流程就介绍到这里了。

在这个参考文章中,我并没有对具体技术做过多的讲解,那是因为本文只是作为一个研究jpetstore的参考,提供一个可供参考的研究流程,主要是为了那些想开始研究jpetstore但是又不知道从哪开始或者是不知道如何进行研究的新人朋友们而准备的,如果具体的讲解每一部分,那我想将不仅仅是一篇文章就可以完成的事情,因为这里涉及到struts,spring,ibatis等具体的框架技术,每一个框架基本都可以写成一本书,用一篇文章来讲就不太实际了,而且我个人更倾向于遇到不理解的地方的时候,多使用google来搜索,这样能够进一步加深自己对问题的理解。

好了,关于jpetstore源码研究入门的文章就写到这里结束了,由于本人技术和文笔有限,有错漏或者表达不当的地方请不要介意,欢迎各位朋友来指正。

posted @ 2009-01-06 15:50 Hill 阅读(3764) | 评论 (0)编辑 收藏
 
本人刚转到Java技术方向,希望能在这里与大家一起学习,进步。
posted @ 2009-01-05 17:24 Hill 阅读(375) | 评论 (0)编辑 收藏
仅列出标题
共5页: 上一页 1 2 3 4 5 
CALENDER
<2024年5月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

常用链接

留言簿(3)

随笔档案

文章档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜


Powered By: 博客园
模板提供沪江博客