Struts笔记
第一个struts
name="domain":包名;
namespace="/test":该包的名称空间,一般是以"/"开头;
extends="struts-default" :继承的父包的名称;
method="showHello" :JavaBean中对应处理的方法。(无参的);
name="success" :动作方法返回的字符串;
name="hellostruts" :同包中必须唯一,动作的名称。
class="com.domain.HelloWordAction" :负责处理的javaBean的类全名;
result中的type :转到目的地的方式,默认为转发,名称是:dispatcher.
type="redirect" :让地址重定向。
type:转到目的地的方式。默认值是转发,名称是dispatcher
(注:type的取值是定义好的,不是瞎写的。在struts-default.xml中的package中有定义)
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.dispatcher.ServletDispatcherResult" default="true"/>
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="org.apache.struts2.dispatcher.HttpHeaderResult"/>
<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.dispatcher.ServletActionRedirectResult"/>
<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
<result-type name="velocity" class="org.apache.struts2.dispatcher.VelocityResult"/>
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<result-type name="plainText" class="org.apache.struts2.dispatcher.PlainTextResult" />
dispatcher:普通的转发到某个页面
chain:普通的转发到某个动作名称
redirect:重定向到一个页面
redirectAction:重定向到一个动作名称
plainText:以纯文本的形式输出JSP内容
result元素的写法:
方式一:
<result type="chain" name="success">a2</result>
方式二:
<result type="chain" name="success">
<param name="actionName">a2</param><!--name对应的chain的处理器中的setActionName()方法-->
</result>
注意:如果要转向的是在另外一个名称空间的动作,那么只能使用方式二
<package name="p1" namespace="/namespace1" extends="struts-default">
<action name="a2">
<result type="dispatcher" name="success">/3.jsp</result>
</action>
</package>
<package name="p2" namespace="/namespace2" extends="struts-default">
<action name="a1">
<result type="chain" name="success">
<param name="namespace">/namespace1</param>
<param name="actionName">a2</param>
</result>
</action>
</package>
3、开发中配置文件的更改,在访问时让框架自动重新加载:
struts.devMode = false(default.properties)
利用strutx.xml中的constant元素来覆盖掉default.properties默认行为
<struts>
<constant name="struts.devMode" value="true"></constant>
</struts>
4.动态方法调用:(不建议使用)
http://localhost:8080/StrutsDemo2/users/updataUser!addUser
本来这里应该调用的是updataUser,但是由于是动态调用,所以就会执行addUser
5.使用通配符调用方法
<action name="user_*" class="com.action.Useraction" method="{1}">
<result type="dispatcher" name="success">/jsp/{1}.jsp</result>
</action>
*:代表你要访问的那个方法。
{1}:代表前面的*号。
User:最好是能表名是当前模块。
http://localhost:8080/StrutsDemo2/users/user_addUser
6. struts2配置文件的拆分,导入外部struts文件
<include file="user.xml"></include>
7.获取表单提交的请求参数
1. 表单提交的地址(struts配置文件里面的动作名): action="${pageContext.request.contextPath }
2. 表单名一定要和动作类名一样,不然struts2无法赋值,如果动作类里面有外部类那么提交表单里面的name就应该是: 外部类 . 属性名,struts2赋值就会自动实例对象赋值。
3. 如果是数组,strutS2也会自动帮你赋值。
8.动作类如果要构造方法,不能只有有参的构造方法,必须要有一个无参的构造方法,因为struts2每次都会去实例化一个无参的构造方法,所以struts2是线程安全的。
9.StrutS2默认的时间自动转换格式为:2013-12-12;如果使用的不是这种格式就要自定义转换器。
10.自定义时间转换器:如果使用了时间转换器,那么后面就只能是这种时间格式。(每次都要到转换器里)
局部时间转换器:
1.在当前工程下创建一个包com.convertor,在该包下面创建一个类继承DefaultTypeConverter,复写里面的convertValue(Map<String, Object> context, Object value,Class toType)方法。
2.在当前action类的包中创建配置文件(名称规则是固定的如下):动作类名-conversion.properties
3.在配置文件中注册:birthday(要转换的字段)=com.convertor.DateConvertor(转换器的全名)
4.StrutS2默认的时间格式是:2012-12-12
要转的格式:DateFormat df = new SimpleDateFormat("yyyy年MM月dd");(可其他格式)
public class DateConvertor extends DefaultTypeConverter {
@Override
public Object convertValue(Map<String, Object> context, Object value,Class toType) {
//如果此处转换成这种时间类型,那么其他的就不行了,因为每次都要到这里来。
DateFormat df = new SimpleDateFormat("yyyy年MM月dd");
if(toType == Date.class){
//保存数据时将String转换为Date类型
String strValue = ((String[])value)[0];
try {
return df.parse(strValue);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}else{
//获取时间时将Date转换为String
Date dValue = (Date) value;
return df.format(dValue);
}
}
}
全局时间转换器:
只需要在src下面创建一个如下配置文件
里面写的内容和上面一个是不一样的:
在配置文件中注册:java.util.Date =com.convertor.DateConvertor(转换器的全名)
11.当出现数据类型转换错误或数据验证错误时,就会自动转向name为input指定的页面
<action name="addUser" class="com.action.Useraction" method="addUser">
<result type="dispatcher" name="success">/jsp/addUser.jsp</result>
<result type="dispatcher" name="input">/jsp/add.jsp</result>
</action>
12.自定义拦截器(在这配置之前必须写一个拦截器类)
<package name="mypackage" extends="struts-default">
<!-- 配置全局拦截器 -->
<interceptors>
<interceptor name="loginInterceptor" class="com.interceptor.LoginInterceptor"></interceptor>
<interceptor-stack name="mydefaultstack">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="loginInterceptor"></interceptor-ref>
</interceptor-stack>
</interceptors>
<!-- 配置全局错误页面 ,影响范围只在本包(如果要是所有包就放在src下面)-->
<global-results>
<result type="dispatcher" name="error">/jsp/error.jsp</result>
</global-results>
</package>
自定义拦截器
<package name="interceptor" namespace="/interceptor" extends="mypackage">
<!-- 自定义的拦截器, 取一个名字下面用 -->
<interceptors>
<interceptor name="loginInterceptor" class="com.interceptor.LoginInterceptor"></interceptor>
</interceptors>
<action name="logIndex" class="com.action.LoginAction" method="login">
<!--<interceptor-ref name="mydefaultstack"></interceptor-ref> 如果要用上面的全局拦截器就直接这一句-->
<interceptor-ref name="defaultStack"></interceptor-ref> <!-- 这里必须写默认的 -->
<interceptor-ref name="loginInterceptor"></interceptor-ref> <!-- 如果这样的话,默认的就没有了,必须把自定义的写到最后。 -->
<result type="dispatcher" name="success">/index.jsp</result>
<result type="dispatcher" name="login">/jsp/login.jsp</result>
</action>
</package>
13.用户输入数据的验证(验证所有方法)
导入struts2的包:<%@taglib uri="/struts-tags" prefix="s" %>
1、手工编程验证,针对该动作类中的所有的动作方法
步骤:
a、动作类继承ActionSupport
b、覆盖调用public void validate()方法
c、在validate方法中,编写不符合要求的代码判断,并调用父类的addFieldError(String fieldName,String errorMessage)
如果fieldError(存放错误信息的Map)有任何的元素,就是验证不通过,动作方法不会执行。
Struts2框架会返回到name=input的result
d、在name=input指定的页面上使用struts2的标签显示错误信息。<s:fielderror/>
13.用户输入数据的验证(验证指定方法)
动作类中指定的方法进行验证:
编写步骤与上面相同
验证方法书写有要求:
public void validateXxx() Xxx代表的是要验证的动作方法名,其中要把动作方法名的首字母变为大写。
14.基于XML的验证方法(对所有方法进行验证)
1、在动作类中建立一个名称为的XML配置文件。
15.基于XML的验证方法(对指定方法进行验证)
1、只需要把XML的名字修改一下即可:动作类名 - 动作名(配置文件中的动作名) – validation.Xml
RegiterUserAction- regiterUser-validation.xml
<s:fielderror/> : 字段错误
<s:actionerror/>: 动作错误
16.StruthS中的内置验证器
17.基于XML的自定义验证器
1、编写一个类继承FieldValidatorSupport
2、在public void validate(Object object) throws ValidationException写你的验证规则
不符合要求的:addFieldError(fieldName, object); object会自动去取message里面的内容
3、注册自定义验证器:在WEB-IN/classes(src下)下面建立一个配置文件
18.Struts2中的国际化
配置文件:
全局:
1、 配置文件一定要放WEB-INF/classes下面
2、 在jsp中读取
3、 在java类中获取
带占位符的国际化:
1、 在jsp中读取
2、 在java类中获取
局部:(如果自己包中有就不会到全局里面去拿了,就用自己包中的)
包范围资源文件:服务于java类中包下面的动作类。
取名:package_语言_国家.properties
用法:将配置文件放到要用的包下:package_语言_国家.properties
Action范围内:放到动作类想对应的包中
取任意的:用i18n自己的一套标签
<!-- 取任意地方的 -->
<s:i18n name="com/action/package">
<s:param>jzp</s:param>
<s:param>hello</s:param>
</s:i18n>
19.OGNL表达式
1、在struts2中要使用ognl表达式必须结合struts2标签。
OGNL是从ActionContext中获取数据的。
ActionContext的结构:
ValueStack:
List:动作类放在此处。取存放在ValueStack中的root的对象的属性,直接写即可
访问以下内容中的对象要使用#+(范围)session
application:ServletContext中的那个Map
session:HttpSession中的那个Map
request:ServletRequest中的那个Map
parameters:请求参数的那个Map。(如同EL表达式的paramValues内置对象)
attr:相当于PageContext的findAttribute方法。${username}
小技巧:在页面中使用<s:debug/>查看上下文中的对象
20.Struts2常用标签
21.Struts2中的防止表单重复提交
1、在表单中加入<s:token/>标签
<s:token></s:token>
2、在动作类中加入token的拦截器
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="token"></interceptor-ref>
3、增加一个名称为invalid.token的结果视图
<result name="invalid.token">/success.jsp</result>
22.通过一个超链接提交到一个action
<s:url action="user_delUser" namespace="/user" var="url">
<s:param name="userId" value="#user.id"></s:param>
</s:url>
<a href="<s:property value='url' />">删除</a>
23.Struts2中的文件下载
资料:
<c:url value="/user/download" var="url">
<c:param name="path" value="${user.path }"></c:param>
<c:param name="filename" value="${user.filename }"></c:param>
</c:url>
<a href="${url }">下载</a>
<!-- 文件下载 -->
<action name="download" class="com.domain.User" method="download">
<result type="stream" name="success">
<param name="contentType">application/octet-stream</param>
<param name="inputStream">inputStream</param><!-- 对应的动作类中的那个字段 -->
<param name="contentDisposition">attachment;filename=${filename}</param>
</result>
</action>
//文件下载
public String download(){
path = ServletActionContext.getRequest().getParameter("path");
filename = ServletActionContext.getRequest().getParameter("filename");
//得到下载资源的路径
String storePath = ServletActionContext.getServletContext().getRealPath("/files");
try {
inputStream = new FileInputStream(storePath+File.separator+path+File.separator+filename);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return SUCCESS;
}
24、struts2核心解析和错误处理
Struts2的请求流程:
1、 创建actionContext
创建valueStack
ActionContext放入到threadlocal中
2、 创建ActionProxy
创建action
把action放到栈顶
得到所有的拦截器,并且返回迭代器的形式。
3、 ActionProxy.execute
执行所有的拦截器
执行action
执行结果集
24、struts2和Ajax整合