struts经验总结
1 结构
1.1 总体结构
Struts理论上由3个文件Jsp,action类,form类。其中,form类继承了ActionForm,主要是set,get等方法,还有reset及validate方法(),,form类不属于控制层,所以不进行业务逻辑的处理。他的功能就是提供一个控制层与页面对话的一个窗口,以便让控制层与视图层沟通。一个form类对应页面一个表单。
而action类(C层)继承了Action则为主要的类,必须覆盖excute方法,原类的此方法返回null.动作流程在这里编写,一般将逻辑封装在bean(M层)中,由action来调用,这样可使逻辑变得清晰。一个action对应一个(或多个)动作(比如提交,link).
1.1.1 流程:
1.1.1.1 本例jsp页为action="/HelloWorld.do"。则在web.xml中寻找<url-pattern>属性为*.do的<servlet-name>的元素。
1.1.1.2 按照<servlet-name>的名称action找到对应的<servlet>
1.1.1.3 Servlet按照用户请求action="/HelloWorld.do",在config.xml中检索path为"/HelloWorld.do"的<action>
1.1.1.4 ActionServlet根据name属性创建一个HelloForm对象,将表单数据提交给对象,并且将对象保存在scope指定的范围内。
1.1.1.5 如果<action>的validate属性为true,则执行ActionForm的validate方法。
1.1.1.6 如果验证失败,则validate方法将ActionErrors对象保存在scope范围内,根据<action>属性,页面跳转。<html:errors />负责读取ActionErrors对象,显示出来。
1.1.1.7 验证成功则返回的ActionErrors中不包含任何ActionMessage对象,然后开始创建Action对象,调用其execute()方法。
1.1.2 使用方法
1.1.2.1 调bean
在jsp中使用
<logic:present name="HelloForm" scope="request">
判断request中叫HelloForm得bean是否存在,如果存在,则
<bean:write name="HelloForm" property="userName" />
1.1.3 actionForm
属于视图组件,提交表单后,struts自动将表单数据提交给actionForm Bean中,此类的方法包括,jsp页请求的set,get和reset,validate方法。Struts首先运行reset方法来重新设置默认值,然后运行validate,进行表单验证,如果发生错误,则创建ActionErrors实例,使用add(“username”,new ActionMessage(“”))方法添加错误,在return实例。如果发生错误,<html:errors>负责将保存在request中的ActionErrors的错误表示出来。
一个画面原则上应该对应一个form,当迁移的时候,Action类中可以使用多个form,一个为本form,其他为迁移先或者迁移元,而迁移先画面则使用自己的form,这样可以避免一个画面使用多个form,但是form的判断能力(validate)可能受到了限制(还有待考察)。
1.1.4 Action类
1.1.4.1 取得属性
mapping.getInput()得到<action-mapping>中的input属性.
1.1.4.2 画面迁移
return (mapping.findForward("SayHello"))返回目标网页
1.1.4.3 改变请求,与网页进行交互
在Action类中,可以实体化ActionForm,然后设置其属性,例:
FormBasicForm fbf = (FormBasicForm) form;
fbf.setName(“dzp”);
达到改变请求的目的,而由于页面使用了struts标签,所以自动从名称相同的请求中取得数据.此外,不同控件可以使用相同的property,从而达到一个请求对应多个控件的目的。
1.2 配置文件
1.2.1 config.xml
<form-beans>
<form-bean name="RegisterForm" type="app.RegisterForm">
</form-bean>
</form-beans>
这里type指向了form类,而name则为他定义了一个名字
<action-mappings>
<action path="/test" type="app.RegisterAction"
name="RegisterForm" scope="request" input="/register.jsp">
<forward name="success" path="/success.jsp">
</forward>
<forward name="failure" path="/failure.jsp">
</forward>
</action>
</action-mappings>
这里path标示了这个action的代号,和jsp中的<html:form action="/test.do">名称相同.
type指向了action类。
name对应了form类。
scope指范围。
input指的是错误信息(ActionErrors 类)输出页面,当Form类中validate方法return的errors不为空时,将转向input所指页面,以输出错误信息。
<struts-config>
<form-beans>
<form-bean name="HelloForm" type="hello.HelloForm"/>
</form-beans>
<action-mappings>
<action path = "/HelloWorld"
type = "hello.HelloAction"
name = "HelloForm"
scope = "request"
validate = "true"
input = "/hello.jsp">
<forward name="SayHello" path="/hello.jsp" />
</action>
</action-mappings>
<message-resources parameter="hello.application"/>
<form-beans>配置了ActionForm Bean
<action-mappings>中,path为jsp页引用action类时所要调用的名称。Type为action本身。Name为ActionForm类名,与<form-beans>种对应的ActionForm名相同。scope存在范围。Validate是否执行表单验证。Input为验证失败时的转发路径。
message-resources为resource Bundle使用的消息资源文件,本例为hello包下的application.properties文件。
1.3 乱码
1.3.1 Jsp页面上的乱码问题,表现为,使用eclipse时,jsp页面上的文字,经常突然变为乱码,原因为eclipse的编译方式默认的ms932,改成Other(UTF-8),则解决。Windows - Preference - General - Workspace - Text file encoding
1.3.2 Request中日文乱码,表现为,页面中传到formAction的request为乱码,即使在formAction中处理也无效。
解决方法:加过滤器
创建Trans.java 进行过滤
package common;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.RequestProcessor;
public class Trans extends RequestProcessor{
public Trans(){}
protected boolean processPreprocess( HttpServletRequest request,
HttpServletResponse response ){
try{
request.setCharacterEncoding("shift_jis");
}
catch(Exception ex){
ex.printStackTrace();}
return true;
}
}
然后再struts-config.xml中定义,
<controller processorClass="common.Trans" />我放在了action后面。
更改的重点为编码方式必须为“shift_jis”,“UTF-8”则不可以。
如果不是struts,在web.xml中添加过滤器也可以,但可能因为版本问题,我这里的eclipse生成的web.xml的dtd版本为2.2,不认识<filter>,有红X.但经过测试,却可以强行编译,运行,达到过滤的效果。
1.3.3 在url中拼写参数时出现的乱码
首先,在网上查了查,结果都是让我转字节码之类的方法,于是我设置了
new String(request.getParameter("a ").getBytes("ISO8859_1"),"shift_jis");
但经过百般修改,试验均无效。翌日,突然想起以前做asp时。使用了escape方法来进行转码,和unescape进行解码,终于得出正确结果。
public class EscapeUnescape
{
public static String escape (String src)
{
int i;
char j;
StringBuffer tmp = new StringBuffer();
tmp.ensureCapacity(src.length()*6);
for (i=0;i<src.length() ;i++ )
{
j = src.charAt(i);
if (Character.isDigit(j) || Character.isLowerCase(j) || Character.isUpperCase(j))
tmp.append(j);
else
if (j<256)
{
tmp.append( "%" );
if (j<16)
tmp.append( "0" );
tmp.append( Integer.toString(j,16) );
}
else
{
tmp.append( "%u" );
tmp.append( Integer.toString(j,16) );
}
}
return tmp.toString();
}
public static String unescape (String src)
{
StringBuffer tmp = new StringBuffer();
tmp.ensureCapacity(src.length());
int lastPos=0,pos=0;
char ch;
while (lastPos<src.length())
{
pos = src.indexOf("%",lastPos);
if (pos == lastPos)
{
if (src.charAt(pos+1)=='u')
{
ch = (char)Integer.parseInt(src.substring(pos+2,pos+6),16);
tmp.append(ch);
lastPos = pos+6;
}
else
{
ch = (char)Integer.parseInt(src.substring(pos+1,pos+3),16);
tmp.append(ch);
lastPos = pos+3;
}
}
else
{
if (pos == -1)
{
tmp.append(src.substring(lastPos));
lastPos=src.length();
}
else
{
tmp.append(src.substring(lastPos,pos));
lastPos=pos;
}
}
}
return tmp.toString();
}
}
转自:http://blog.youkuaiyun.com/emu/archive/2002/04/22/16337.aspx
2 标签
2.1 <html:errors property="username2"/>
Property属性对应ActionErrors.add(String,ActionMessage)中的String
2.2 <html:link>
paramId: 参数名
paramName: 对象名
paramProperty: 对象中的属性
<html:link page="/link.do" paramId="p" paramName="form" paramProperty="param">单参单值</html:link>
<html:link page="/link.do" name="dataForm" property="param">多参单值</html:link> paramId="p" paramName="dataForm" paramProperty <html:link page="/link.do" paramId="p" paramName="dataForm" paramProperty="param">单参单值</html:link><br/>
<html:link page="/link.do" name="dataForm" property="paramSingleMap">多参单值</html:link><br/>
<html:link page="/link.do" paramId="p" paramName="dataForm" paramProperty="param">单参单值</html:link><br/>
<html:link page="/link.do" name="dataForm" property="paramSingleMap">多参单值</html:link><br/>
3 其他
3.1 ActionMessage 从资源文件
<message-resources parameter=""/>中获得对应的message
New ActionMessage("hello.talk.to.monster", name1,name2,…));
将资源文件中对应的{0}换成name1中的内容,以此类推。
3.2 request
request.setAttribute("a","111")
为request中a的请求赋值。
另:response.sendRedirect("a.jsp");无法传递request
request.getRequestDispatcher("a.jsp").forward(request,response);才能共享request中数据。
3.3 ActionMapping
ActionMapping. getAttribute
得到被定义的formBean的名称,返回String类型
3.4 方法
3.4.1 isCancelled
if(isCancelled(request))判断取消时间是否发生.
4 实例
4.1 1个from对应多个action
可以在javaScript中作,但要注意指定action时要使用绝对路径
document.Form[0].action ="<%=request.getContextPath()%>/ApplyBtn.do";
这是因为struts已经为你搭好了框架,帮你写上了,而from本身是不清楚地,所以在javaScript中只好自己写。
4.2 标签中使用变量
以readonly属性为例,注意这里变量必须用布尔值
<%boolean bolReadOnly = applyForm.isReadOnly();%>
<html:text readonly="<%= bolReadOnly%>"/>