Struts1.x学习笔记
l 各种action的基本配置与使用
<action path="/register" type="com.kettas.action.UserAction"
input="/register.jsp" validate="true" name="userForm">
<forward name="success" path="/result.jsp">forward>
action>
<action path="/updateorder" type="com.kettas.action.OrderAction"
parameter="updateOrder">
<forward name="success" path="/result.jsp">forward>
action>
<action path="/deleteorder" type="com.kettas.action.OrderAction"
parameter="method">
<forward name="success" path="/result.jsp">forward>
action>
<action path="/usermanage" type="com.kettas.action.UserLookupAction" parameter="callmethod">
<forward name="success" path="/ok.jsp">forward>
action>
l 异常处理
Strut1.x的异常处理蛮简单。配置时分为全局,异常与局部异常。
对于一个action若发生异常则先查找本身action是否有相应异常的配置,若无则查找全局异常配置,还没有则报错。异常处理一定会用到资源文件
1. 局部配置如下
<exception key="user.register" type="com.kettas.exception.UserRegisterException" bundle="exception" path="/error.jsp"/>
2. 全局配置如下,各属性与局部配置一样
<global-exceptions>
<exception key="user.register" type="com.kettas.exception.UserRegisterException" bundle="exception" path="/error.jsp"/>
global-exceptions>
3.对于一个异常,通过会转入另外一个页面,提示错误,struts1.x在此设计有些不合理,一旦转入异常提示页面时,即使这个页面设置了isErrorPage="true"但是它的内置有exception对象依然为空,所以不能用exception得到异常中的信息,只能用<html:errors />来得到,一大失误哦,这也就是说struts1.x的异常处理是离不开资源文件的,因为异常的信息只能放在资源文件中。
l 国际化
国际化要对就资源文件,这必须在struts-config.xml中指定,与struts2中则不需。
配置方法:
<message-resources parameter="com.kettas.resources.messages" >message-resources>
<message-resources parameter="com.kettas.resources.information" key="information" >message-resources>
其中第一种配置为默认配置,没有指定其key属性,则struts会自动将其key设为org.apache.struts.action.MESSAGE,源码可查,且一旦要使用资源文件则一定要有一个不能有key属性,即一定要给org.apache.struts.action.MESSAGE指定一个资源文件,struts默认此资源文件为全局资源文件,即以后使用资源文件的地方若没有指定其使用哪个文件,则会从这个默认配置资源文件中找。Struts会将资源文件打包MessageResourcesConfig以key值为键放在ServletContext的作用域中,在其它使用到资源文件的地方可以key值指定使用哪个资源文件中的键值对;
类型转换
1. struts的页面的国际化
使用<bean:message bundle="information" key="errors.validwhen" arg0="param1" arg1="param2"/>
Bundle指定是使用哪个资源文件,即在资源文件配置时指定的key值。
Key为资源文件中的键值。
Arg0,arg1指若资源文件中有占位符时用来替代的值。
2. struts的异常的国际化
<exception key="user.register" type="com.kettas.exception.UserRegisterException" bundle="exception" path="/error.jsp"/>
3. struts的输入验证的国际化
配置:
<field property="userName" depends="required">
<msg key="errors.required" name="required" bundle="information"/>
<arg position="0" key="userName" resource="false" />
field>
l 输入验证
一.使用验证框架
(输入验证时需要用到如下两个jar包commons-validator.jar 与oro.jar.)
注意:要进行框架验证的Form必须继承自ValidatorForm,ValidatorActionForm。以及使用动态的
DynaValidatorForm和DynaValidatorActionForm。其中ValidatorForm与DynaValidatorForm在验证文件的配置时相同,另外两个相同。
前两个匹配action配置中的name,而后两个匹配的是action配置中的path.由此可知两者在使用上的一些局限性。
1. 框架的基本配置
Struts的验证框架默认是并不打开的,以插件的形式运行,在使用之前要进行插件注册,注册配置为
<plug-in className="org.apache.struts.validator.ValidatorPlugIn">
<set-property property="pathnames"
value="/org/apache/struts/validator/validator-rules.xml,
/WEB-INF/validation.xml" />
plug-in>
其set-property的property属性的值可以在源码找到,这个配置可以到struts提供的示例程序中去拷。对于不同版本的struts1.x它的validator-rules.xml放置的位置可能并不太一样,这点不能硬搞。 另外validation.xml为验证文件。
2. 验证文件基本配置:
xml version="1.0" encoding="utf-8" ?>
DOCTYPE form-validation PUBLIC
"-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.3.0//EN"
"http://jakarta.apache.org/commons/dtds/validator_1_3_0.dtd">
<form-validation>
<formset>
<form name="userForm">
<field property="userName" depends="required,maxlength">
<msg key="errors.required" name="required" bundle="information"/>
<msg key="errors.maxlength" name="maxlength" bundle="information"/>
<arg position="0" key="userName" resource="false" />
<arg position="1" key="${var:maxlength}" resource="false"/>
<var>
<var-name>maxlengthvar-name>
<var-value>10var-value>
var>
field>
<field property="userPwd" depends="required">
<msg key="errors.required" name="required" />
<arg position="0" key="userPwd" resource="false" />
field>
<field property="reUserPwd" depends="validwhen">
<arg position="0" key="repassword" resource="false"/>
<arg position="1" key="password" resource="false"/>
<msg name="validwhen" key="errors.validwhen"/>
<var>
<var-name>testvar-name>
<var-value>(*this*==userPwd)var-value>
var>
field>
<field property="birthday" depends="required,date">
<msg key="errors.required" name="required" />
<msg key="errors.typeinvalid" name="date" />
<arg position="0" key="birthday" resource="false" />
<var>
<var-name>datePatternvar-name>
<var-value>YYYY-MM-DDvar-value>
var>
field>
form>
formset>
form-validation>
二,重载ActionForm的validate方法
1.这种方法很简单,有一点是往ActionErrors里面加入ActionMessage时ActionMessage的重载构造方法可以确定传递进去的字符串是否来自资源文件以及在资源文件中的键值,若不是来自资源文件则此键值将会被显示,它不能指定这个键值来自哪个资源文件,这要靠页面标签来确定,这种设计明显不些不合理但也很无奈。而ActionErrors的add方法指定这个信息的标识符,即页面上用struts的标签以此标识来显示错误信息。
2.当Validate验证出错时会返回到action指定的input页面。出错的标志为ActionErrors里面是否有ActionMessage.
3.在页面上可以用struts标签得到错误信息。
<html:errors property="username.required" bundle="validateerrors"/>
Property指定在ActionErrors的add方法指定的标识符,bundle指定ActionErrors添加的ActionMessage的键值来自哪个资源文件。
4.要注意框架验证与重载ActionForm的validate方法的验证不能同时使用,若同时存在则只执行validate验证。
l 动态表单的使用
1. 基本使用
基本配置
<form-bean name="productForm" type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="productName" type="java.lang.String">form-property>
<form-property name="productPrice" type="java.lang.Double">form-property>
<form-property name="productDate" type="java.util.Date">form-property>
<form-property name="discription" type="java.lang.String">form-property>
form-bean>
2. 输入验证
基本配置
它的配置与普通表的ActionForm一样,没有任何区别。这就不多说了!
l Struts1.x的上传与下载
1. 文件上传
<form-bean name="photoForm"
type="org.apache.struts.validator.DynaValidatorForm">
<form-property name="photo1"
type="org.apache.struts.upload.FormFile">
form-property>
<form-property name="photo2"
type="org.apache.struts.upload.FormFile">
form-property>
<form-property name="photo3"
type="org.apache.struts.upload.FormFile">
form-property>
form-bean>
------------------------------------------------------------------
<action path="/upload" type="com.kettas.action.UploadAction"
name="photoForm">
<forward name="success" path="/ok.jsp">forward>
action>
------------------------------------------------------------------------------
<form action="<%=request.getContextPath() %>/upload.do" method="post" enctype="multipart/form-data">
<input type="file" name="photo1">
<input type="file" name="photo2">
<input type="file" name="photo3">
<input type="submit">
form>
------------------------------------------------------------------
package com.kettas.action;
import java.io.FileOutputStream;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.*;
import org.apache.struts.upload.FormFile;
import org.apache.struts.upload.MultipartRequestHandler;
public class UploadAction extends Action {
@SuppressWarnings("unchecked")
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
DynaActionForm daf=(DynaActionForm)form;
MultipartRequestHandler handler=daf.getMultipartRequestHandler();
Hashtable photos=handler.getFileElements();
Set set=photos.keySet();
System.out.println(set.size());
Iterator values=set.iterator();
while(values.hasNext())
{
FormFile file=(FormFile) photos.get(values.next());
System.out.println(file.getFileName());
FileOutputStream out=new FileOutputStream("c:\\"+file.getFileName());
out.write(file.getFileData());
out.close();
}
return mapping.findForward("success");
}
}
2. 文件下载
文件下载功能是通过DownloadAction实现的。
继承DownloadAction。
实现getStreamInfo方法,返回StreamInfo对象。
部分代码的实现:
package com.kettas.action;
import java.io.File;
import javax.servlet.http.*;
import org.apache.struts.action.*;
import org.apache.struts.actions.DownloadAction;
public class TestDownLoad extends DownloadAction{
@Override
/*
* 这个类可以没有execute方法。因为通过链接下载文件成功成没有必要跳转,当然也可以
* 做到,这时文件下载将会被抑制,就没有下载的意义了。
* 它的配置与其它的action没有任何区别
*/
protected StreamInfo getStreamInfo(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
String fileName = "test.txt";
response.setHeader("Content-disposition",
"attachment; filename=" + fileName);
File file = new File(this.servlet.getServletContext().getRealPath("/upload")+"//"+fileName);
return new FileStreamInfo("text/html", file);
}
}
l Struts1.x的其它一些问题
1. 时间类型先set验证时出现问题
查了很多资料,基本上没有好的解决办法,struts给的示例中用动态表单来接收数据,而接收时间的字段也是字符串类型,这样就避免了转换,并且可以进行格式验证。当这个动态表单数据传入action时,按需要再将这个字符串转成时间类型。由此也算是struts的ActionForm的一个硬伤。对于没有时间类型的form表单用静态actionform可以,若有则最好用动态。
其实其本上所有的表单提交用动态都行。推荐这么做
2. 一些有用的技巧。
对于form表达的提交按钮,如果这个按钮有name属性,则这个按钮的值也会被提交,若则不会,struts的LookupDispatcherAction就是以此来实现的。Struts内置了个小东西,若是一个submit的name值org.apache.struts.action.CANCEL则在执行业务方法前调用Action的isCancelled方法可以确定是否点了这个按钮以此来写此相应代码!当然这些实现很简单,自已也可以实现!
l Struts1.x的防止表单的重复提交
Struts的令牌机制
在转入提交表单的action中要调用saveToken方法,这样将会在session中放入令牌,
并将生成的令牌放入表单提交页面,一般放在一个隐藏域中,用el表达式给其符值,且隐藏域的名称为固定的
org.apache.struts.action.TOKEN 这可以从Globals.class中找到。
在处理表单提交的action中要调用isTokenValid方法来判断是否是第一次提交。
把表单处理后调用resetToken(request);将session中的令牌重置(其实这个重置似乎并没有太大意义)。
由上面的可知,可以自己来实现一个令牌使用
l Struts的titles框架
1. 在页面直接使用titles标签
先引入标签:<%@taglib uri="http://struts.apache.org/tags-tiles" prefix="tiles" %>
将模板页面要代替的内容用标签占位:<tiles:insert attribute="content">tiles:insert>
在另外一页面将模板页与内容页整合:
<tiles:insert page="usertemplate.jsp">
<tiles:put name="content" value="zczzh.jsp">tiles:put>
tiles:insert>
2. 使用titles框架
先插入框架的插件
<plug-in className="org.apache.struts.tiles.TilesPlugin">
<set-property property="definitions-config"
value="/WEB-INF/tiles-defs.xml" />
<set-property property="definitions-parser-validate"
value="true" />
plug-in>
定义titles配置文件
xml version="1.0" encoding="UTF-8"?>
DOCTYPE component-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN" "tiles-config_1_1.dtd" >
<component-definitions>
<definition name="template" page="/template.jsp">
<put name="head" value="head.jsp" >put>
<put name="foot" value="foot.jsp" >put>
<put name="left" value="left.jsp" >put>
definition>
<definition name="register" extends="template">
<put name="content" value="content2.jsp">put>
definition>
component-definitions>
在struts的action中调用
<action path="/testtiles" type="com.kettas.action.MyTilesAction"
parameter="register">
<forward name="success" path="/index.jsp">forward>
action>