今天终于对《Jakarta Struts编程》看了一个大概,
准备搭建一个环境进行进一步学习。
我将下载的status-1.2.7.tar.gz解压缩后,
把lib目录中的status.jar、jstl.jar和standard.jar拷贝到了WEB-INF的lib目录中,
起动服务器后,竟然一个劲儿的抛出异常,
郁闷死……
最后,把所有的jar文件都拷贝到WEB-INF的lib目录后,
才解决了问题。
回过头再看书,才发现,
书上已经写的很明白了,只怪当时没有注意到。
看来,看书还是要仔细一些。
又或是,水平不够,所以注意不到书上说的内容的重要性。
我还是经常碰到这个问题,有时干脆把想得到的库文件都给它拷上,例如在我试验那个struts+spring+hibernate的程序时就是这样的。http://www.learndiary.com/disDiaryContentAction.do?searchDiaryID=1468&goalID=1468&naviStr=a10ac0ad0
...
6)、还有就是要把每个开源项目的包完整的拷到你的应用程序的lib中,比如:spring就要把它所有的在lib下的第三方支持包全部拷入你的应用程序的lib中。做这些事不要怕有冗余的文件,java的运行机制是要用的时候再去创建类的实例。多些文件只是占点硬盘空间而已。
...
祝你学习愉快。
--admin
谢谢您的鼓励。
----------------------------------------------------------------------------------------------------
搭建环境成功以后,
尝试着自己写了一个小程序,
结果搞了半天才弄好。(还好弄出来了)
问题出在:在JSP上显示FormBean中的数据的问题上。
主要还是两个标签的使用上,不太明白。
一、<bean:define>标签
研究了半天,才弄明白那几个常用的属性是什么意义。
作个总结,省得自己忘了。
这是copy已有的对象到bean:
id:新生成的bean的标识;
name:以存在的对象名;
type:新生成bean的类(型)。
比如:<bean:define id="form" name="loginForm" type="com.sinpool.formbeans.LoginForm"/>
新生成一个名为form的bean,类型是com.sinpool.formbeans.LoginForm,因为没有指定toScope,所以就是Page。
然后就可以用<bean:write>输出这个Form的属性了。
哈哈,接触Struts后,第一次对她产生好感了。
你在这里讲了,我才大概知道。我会用这个标签去试着解决我碰到的一个没有解决而悬着的问题:
疑问:不知道在Struts标签中怎么引用jsp片断里的变量 http://www.learndiary.com/disDiaryContentAction.do?goalID=1498
不知道提供的方法是否可行,
希望可以……
×××××××××××××××××××××××××××××××××××××××××××
昨天,只是作了一个小实验,
从jsp页面输入用户名后,
提交请求到Action,
在Action中将根据输入的用户名,
选择不同的View,显示给用户,
这个View还将输出刚才输入的用户名。
今天,在昨天的基础上,开始练习在ActionForm中进行数据的验证,
当然是在validate方法中写东西了,
要想使用这个方法进行验证,有两个条件必须达到:
1)必须在status-config中定义一个form-bean;
2)在响应的action标签中指定validate属性为“true”。
哈哈……还好我的配置是正确的,
顺利出现了错误信息,
可是,用<html:errors property="error1"/>显示的错误信息是黑色的,
郁闷……
还后,后来找到了一个解决的方法,
在定义的properties文件中加入以下两句:
errors.header=<FONT COLOR="#ff0000">
errors.footer=</BR></FONT>
一个是设置错误信息开头的html代码,另一个是设置错误信息结束时的html代码,
这样,错误信息就被显示成红颜色了。
先来无聊,想了一个问题:
当工程很大的时候,很可能把不同模块的文件放到不同的目录中,
所以打算把作好的几个jsp文件放到一个新建的目录中,
修改了相关的联接后,可以正常显示目录中的页面了,
不过,提交请求后,总是显示“错误500”,说找不到我在<form name="aaa" action="login">
中定义的login.do。
郁闷了半天,最后将刚才的form标记改成了<html:form action="login" >,就可以了。
得出了一个结论:尽量使用Struts提供的标记即可。
首先说,她真是一个好东西,只是我掌握的还不好!
她可以使网站所有的网页表现出相同的风格,
每个页面只需要指定与其他页面不同的地方就可以了。
我也只是初步了解了Tiles的使用方法,
还有很多东西等待以后再去深入。
先作一个小小的总结,省得自己忘了。
建立一个“模板”的步骤:
1)建立一个“模板”文件:
<tiles:insert attribute="header"/>
指出一个用于插入模板文件的地方;这里的attritbute属性说明了要插入模板文件的名字(name)。
可以通过修改这个模板的布局,来影响所有使用此模板的页面的布局风格。
+++++++++++++++++++++++++++++++++++++++++
例如:
<%@ page language="java" pageEncoding="GBK" %>
<%@ include file="/commons/StrutsHead.jsp" %>
<!DOCTYPE HTML PUBLIC "-//w3c//dtd html 4.0 transitional//en">
<html>
<head>
<title>Classic Layout</title>
</head>
<body topmargin = "0" leftmargin = "0" bgcolor="#FFFFFF">
<!-- 页眉信息 -->
<tiles:insert attribute="header"/>
<hr>
<!-- 菜单条 -->
<tiles:insert attribute="menu"/>
<hr>
<!-- 主体信息 -->
<tiles:insert attribute="body-content"/>
<hr>
<!-- 所有权声明 -->
<tiles:insert attribute="copyright"/>
</body>
</html>
+++++++++++++++++++++++++++++++++++++++++
2)在页面中套用刚才的模板文件:
一、<tiles:insert page = "/commons/layout/classicLayout.jsp" flush="true">
page属性说明模板文件的位置,假设刚才的模板文件命名为classicLayout.jsp;
flush属性是通知控制器把内容插入到页面之前要刷新输出流。
二、<tiles:put name ="header" value="/commons/header.jsp"/>
把value指定的页面文件放入(put,或者是替换到)一、中指定的模板文件中,替换模板文件中attribute属性与这个标签中name属性相匹配的地方。
+++++++++++++++++++++++++++++++++++++++++
例如:
<%@ page language="java" pageEncoding="GBK" %>
<%@ include file="/commons/StrutsHead.jsp" %>
<tiles:insert page = "/commons/layout/classicLayout.jsp" flush="true">
<tiles:put name ="header" value="/commons/header.jsp"/>
<tiles:put name ="menu" value="/commons/menu.jsp"/>
<tiles:put name ="body-content" value="/TableMaster/t_compT.jsp"/>
<tiles:put name ="copyright" value="/commons/copyright.jsp"/>
</tiles:insert>
+++++++++++++++++++++++++++++++++++++++++
3)编写模板用到的每个具体的页面:
针对这个例子来说,就是/commons/header.jsp、/commons/menu.jsp、/TableMaster/t_compT.jsp和/commons/copyright.jsp
其中,name为“body-content”的部分标识每个页面的主体,所以在每个页面中这个部分是不同的,而其他的三个部分应该是一样的,这样就使得不同页面据有相同的风格了。
+++++++++++++++++++++++++++++++++++++++++
下面这个页面是另一个套用此模板的例子,唯一不同的就是“body-content”部分:
<%@ page language="java" pageEncoding="GBK" %>
<%@ include file="/commons/StrutsHead.jsp" %>
<tiles:insert page = "/commons/layout/classicLayout.jsp" flush="true">
<tiles:put name ="header" value="/commons/header.jsp"/>
<tiles:put name ="menu" value="/commons/menu.jsp"/>
<tiles:put name ="body-content" value="/TableMaster/t_orderT.jsp"/>
<tiles:put name ="copyright" value="/commons/copyright.jsp"/>
</tiles:insert>
+++++++++++++++++++++++++++++++++++++++++
1)中提到的模板是一个很普通的模板,样式[1]是:
(发现网页不能正常显示空格,所以用“`”代替之。)
-------------------------------------
|```````````header```````````|
-------------------------------------
|````````````menu````````````|
-------------------------------------
|````````body-content````````|
-------------------------------------
|```````````footer```````````|
-------------------------------------
我想把她改成下面这个样式[2]:
------------------------------------
|```````````header```````````|
------------------------------------
|```m```|````````````````````|
|```e```|`````body-content``|
|```n```|````````````````````|
|```u```|````````````````````|
------------------------------------
|```````````footer```````````|
------------------------------------
疑惑:
我尝试在1)中的模板文件中使用table标记和<td width="xx%" align="left">(只是在第二行menu和body部分使用),
样子是出来了,不过menu的文字在最左面,而body的部分是在最右面。
中间有很大一个空间什么也没有,而采用样式[1]的时候,body部分是占据了浏览器整个宽度的,
现在也变得很窄了!
不知道该如何解决,郁闷中……
可以正常显示汉字及全角空格:
------------------
| 菜 | |
| | 正文 |
| 单 | |
------------------
不过,如果中间混杂有半角字符,以及英文和半角空格混合就不正常了,我发现半角的空格跟一个英文字母的宽度比起来窄很多,不知怎么样一回事,如下,实际里面的字符数是一样的,但是长度却差太多了:
this is a book.
t i i a k.
我对页面的设计简直一窍不通。
原来是这样呀!
=================================================================
在使用Validator之前,需要先配置一些东西。
(我使用的是Struts 1.2.7)
1)必要的包:
将Struts发行包中的commons-validator.jar和jakarta-oro.jar
这两个文件放到Web应用的WEB-INF/lib目录中。
2)在struts-config.xml中设置插件:
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/WEB-INF/validator-rules.xml,/WEB-INF/validation.xml"/>
</plug-in>
value值用来指定验证规则的文件,要用“,”分割。
3)配置验证规则:
Validator框架有两个重要的配置文件:
<1>``validation-rules.xml文件,
这个配置文件包好了一组可供应用程序使用的全局验证规则。
这个文件是所有应用程序都使用的,任何Struts应用程序也都能
使用。除非打算修改或扩展这组规则,否则无需修改这个文件!
注意1:需要在资源包中加上一下的“键-值”:
errors.required={0} is required.
errors.minlength={0} can not be less than {1} characters.
errors.maxlength={0} can not be greater than {1} characters.
errors.invalid={0} is invalid.
errors.byte={0} must be a byte.
errors.short={0} must be a short.
errors.integer={0} must be an integer.
errors.long={0} must be a long.
errors.float={0} must be a float.
errors.double={0} must be a double.
errors.date={0} is not a date.
errors.range={0} is not in the range {1} through {2}.
errors.creditcard={0} is an invalid credit card number.
errors.email={0} is an invalid e-mail address.
因为,验证出错的时候,系统会自动在资源包中查找对应的错误消息,
比如:required验证规则出现错误时,就会输出“errors.required”的值。
注意2:在Struts 1.2.7中,验证类使用的是:“org.apache.struts.validator.FieldChecks”,
以前使用的是“org.apache.struts.util.StrutsValidtor”,
只要是从struts 1.2.x发行包中拷贝的“validation-rules.xml”文件,就可以保证是正确的。
<2>``validation.xml文件
这个文件是专门用来验证页面指定的Field。
注意1:这个文件是由“<!DOCTYPE form-validation PUBLIC
"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN"
"http://jakarta.apache.org/commons/dtds/validator_1_2_0.dtd">”来管理其语法的。
(因为这个没有找到,耽误了很长时间,每次起动服务器都抛出异常“must match DOCTYPE root "null"”)
********************************
待续…………
********************************
在《使用Validator验证框架 一》中,
已经把要配置的东西说完了,
这次就记录一下对页面上某个Field具体是如何验证的。
这个功能是通过validation.xml文件实现的,
其实,这个文件名可以是任意的,可以起成别的名字,
比如:validators.xml,不过,也要相应修改struts-config.xml文件中的
加入validator框架PlugIn中的value属性。这个value属性用来指定validator-rules文件和具体的验证文件。
1)根元素:
validators.xml文件的“根元素(Root)”是form-validation,
意味着整个文件的内容包含在“<form-validation>”和“</form-validation>”之间,
2)元素global:
这个东西包含constant子元素,用来定义一个全局的“验证限制”,
以便在这个文件的其他地方使用这些验证规则。
例如:
<global>
<constant>
<constant-name>zip</constant-name>
<constant-value>^\d{5}(-\d{4})?$</constant-value>
</constant>
</global>
这个例子就定义了一个全局的验证规则,名字是“zip”,具体的规则由“constant-value”指出。
3)formset元素:
这个可能是这个文件最重要的元素了,
主要负责的就是指定对哪个Field进行验证以及验证规则。
例如:
<formset>
<constant>
<constant-name>zip</constant-name>
<constant-value>^\d{5}(-\d{4})?$</constant-value>
</constant>
<form name = "loginForm">
<field property = "usename"
depends = "required,mask"
<arg0 key = "label.usename"/>
<var>
<var-name>mask</var-name>
<var-value>^[a-zA-z]*$</var-value>
</var>
</field>
<field property = "postalCode"
depends = "required,mask"
<arg0 key="The postalCode" resource="false"/>
<var>
<var-name>mask</var-name>
<var-value>${zip}</var-value>
</var>
</field>
<field property = "ordno"
depends = "required,minLength"
<arg0 key="The ordno" resource="false"/>
<arg0 name="minLength"
key="${var:minLength}"resource="false"/>
<var>
<var-name>minLength</var-name>
<var-value>5</var-value>
</var>
</field>
</form>
</formset>
<1>在formset元素中仍然可以定义验证规则(“constant”),但是,它不是全局的!
这里定义了一个为“zip”的验证规则(这个例子与global的例子没有关系,不要混淆)。
<2>在formset元素中可以定义一个或多个“form”子元素,这个form子元素指的是“from-bean”,
name用于指定被验证的是哪个form-bean,具体的意思一会儿再提。
<3>form子元素中也可以包括一个或多个“field”子元素,这个用来指定这个form-bean中,
哪个field被验证。
<3.1>field元素中的property:指定用来验证的field名;
<3.2>field元素中的depends:指定要采用那些验证规则对其进行验证;
<3.3>field元素中可以包含msg元素(这个例子没有用到),这个元素有三个属性:
name:指定这个message用于哪条规则;
key:这个值应该是资源包中一个可用的“键”;
resource:是一个布尔值,用来说明key中指出的数值是否为资源包中的“键”。如果这个值是“false”,msg中的内容就是key中的字符串,而不是资源包中的值。
<3.4>field元素中可以包括一个到四个arg子元素,用于对应资源包中errors.XXX中的代换参数,
arg0对应{0},arg1对应{1}……,这个子元素包含的属性与msg一致。
小结:
var可以定义验证规则,比如:usename行;
var可以引用在constant中定义的验证规则(包括global中定义的),比如:postalCode行;
var可以定义要显示的数据,在key中引用这个值,比如ordno行。
写在最后的,刚才在介绍form子元素时,并没有具体说明它的name属性具体是如何指定要验证的form-bean的。
这里进行说明一下:
1、如果form-bean是ValidatorAction或DynaValidatorActionForm子类的话,系统将把struts-config中action元素的path属性传递给Validator,此时,Validator中form子元素的name属性应该对应action元素的path属性。
2、如果form-bean是ValidatorForm或DynaValidatorForm子类的话,系统将把struts-config中action元素的name属性传递给Validator,此时,Validator中form子元素的name属性应该对应action元素的name属性。即,与form-bean的名字是一致的!
通过今天的实践,
发现了两个问题,
可能需要以后注意。
1)错误信息不能为某个特定的Field使用。
Validator验证框架如果发现有不满足验证规则时,
将自动封装ActionErrors对象,并将这个对象返回给页面。
但是,这些ActionError(或ActionMessage)对象,使用add方法
加入ActionErrors使用参数是ActionMessages.GLOBAL,
所以,不能将错误信息定位到某个具体的Field上,
只能使用“<html:errors/>”元素将所有信息
一起输出出来。
2)Validator验证框架与ActionForm的validator方法冲突。
这里所说的ActionForm应该是某个ValidatorForm的子类或子孙类,
如果在这个对象中使用了validator方法,并且在struts-config文件中
的action元素中定义了需要使用validator方法验证。
这时,Validator验证框架将失去作用,只进行ActionForm的validator方法,
如果有了错误,将直接返回到struts-config中的action元素input属性指定的页面。
见:头疼,我搞不懂网页中空格的使用了(http://www.learndiary.com/disGoalContentAction.do?searchDiaryID=1690&goalID=1690&naviStr=a10a2416ah1334)
这个Action类可以将据有类似功能的Action合并到一起。它与DispatchAction类的作用差不多,唯一不同的是:这个类是通过资源包中的key作为请求参数来进行对方法的映射,而DispatchAction是通过请求参数来选择方法,即,SUBMIT的value与方法名必须一致。如果使用这个类,SUBMIT的value是资源包中key所对应的值,而根据这个key是如何选择运行方法的,下面就来介绍一下。
步骤一:扩展一个LookupDispatchAction的子类。
注意:1)每个方法必须是public的,为了向外面提供调用接口;
2)不能包括execute方法,这个方法使用LookupDispatchAction的默认方法;
3)每个方法的返回值与参数应该与普通Action类的execute方法一样;
4)每个方法代表一个功能,就相当于合并以前各个普通Action子类的execute方法。
步骤二:在这个子类中实现个体KeyMethodMap方法,实现“键--方法”的映射。
例子:
public Map getKeyMethodMap(){
Map map = new HashMap();
map.put("save","saveStatus");
map.put("load","loadStatus");
return map;
}
步骤三:在资源包中定义“键”对应的“值”,用于表示在SUBMIT按钮上。
例子:
save=save this status;
load=load this status;
步骤四:配置struts-config.xml。
例子:
<action path = "/qqq"
input = "/www.jsp"
parameter = "method"
scope = "request"
type = "com.sinpool.strtus.QQQAction"
<forward name = "success" path = "/order/complete.jsp"/>
</action>
其中parameter="method",指定的字符串是method,说明SUBMIT的property(name)就应该是method。
步骤五:在JSP中的代码。
例子:
<html:form action = "/qqq>
<html:submit property = "method">
<bean:message key = "save"/>
</html:submit>
</html:form>
必须用<bean:message key = "save"/>设置SUBMIT应该显示的值,这段代码提交请求时,应该类似这
个样子:http://localhost:8080/qqq?method="save this status"。参数名“method”应该与步骤四中
的action标签中的parameter一样。
总结:虽然在提交请求时,仍将SUBMIT的value("save this status")提交了,但是,可以按照getKeyMethodMap()方法的定义,通过资源包的key映射到具体的方法名上。所以,这个请求实际调用了save方法。