Struts2深入探索:
1,package中的abstract="true"表示该package里面不能包函action元素
2,package中若指定namespace="/mynamespace"则:
<!--
包的namespace要以"/"开头,对应的页面的路径前面也加上/mymengya/ActionName.action
如:<s:form action="/mymengya/register.action" method="post" theme="simple">
-->
<package name="mengya" extends="struts-default" namespace="/mymengya">
<action name="register"
class="com.mengya.action.RegisterAction">
<result name="success">/show.jsp</result>
<result name="input">/index.jsp</result>
<result name="invalid.token">/index.jsp</result>
<interceptor-ref name="token"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
</package>
在页面form的action中也要加上/mynamespase并且还要加上后缀action(不管是不是用的struts标签)
3,模型驱动
/**
* 模型Bean
* @author 张明学
*
*/
public class RegisterBean {
private String username;
private String password;
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
Action则要接实com.opensymphony.xwork2.ModelDriven接口:
public class RegisterAction extends ActionSupport implements ModelDriven {
/**
* 模型驱动,该模型Bean必须实例化
*/
private RegisterBean loginBean = new RegisterBean();
public Object getModel() {
return loginBean;
}
@Override
public String execute() throws Exception {
return SUCCESS;
}
}
对应页面则可以直接用模型Bean的属性
如:<tr>
<td>
用户名:
<s:textfield name="username"></s:textfield>
<%-- 将form的theme="simple"就可以自由布局了,对于fielderror加上name属性就可以显示这个属生的错误信息 --%>
<s:fielderror name="username"></s:fielderror>
</td>
</tr>
<tr>
<td>
密码:
<s:password name="password"></s:password>
<s:fielderror name="password"></s:fielderror>
</td>
</tr>
<s:property value="username"/>
<s:property value="password"/>
5,表单重复提交:
一,在form里面加上<s:token id="register"></s:token>标签
二,在Action里加上<interceptor-ref name="token"></interceptor-ref>拦截器
默认拦截器:<interceptor-ref name="defaultStack"></interceptor-ref>
三:原理:
当页面第一次生成的时候<s:token id="register"></s:token>会生成一个隐藏表单域其中包涵一个值,该值也同样被存放到session当中去了
当页面第一次提交的时候token拦截器会比较这两个值是否相同,相同则第一次提交,第一次提交后会把session这个值清空,表单若再一次提交时则
session当中没有值即两个值不相同提交失败,返回的resut的name为:invalid.token 即:<result name="invalid.token">/index.jsp</result>
<s:form action="/mymengya/register.action" method="post" theme="simple">
<s:token id="register"></s:token>
<table width="50%">
<tr>
<td>
用户名:
<s:textfield name="username"></s:textfield>
<s:fielderror name="username"></s:fielderror>
</td>
</tr>
<tr>
<td>
密码:
<s:password name="password"></s:password>
<s:fielderror name="password"></s:fielderror>
</td>
</tr>
<tr>
<td>
<s:submit value="注册"></s:submit>
</td>
</tr>
</table>
</s:form>
<package name="mengya" extends="struts-default" namespace="/mymengya">
<action name="register"
class="com.mengya.action.RegisterAction">
<result name="success">/show.jsp</result>
<result name="input">/index.jsp</result>
<result name="invalid.token">/index.jsp</result>
<interceptor-ref name="token"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
</action>
</package>
修改Struts2默认的重复提交的错误提示信息:
在Struts2国际化属性文件中添加一条信息:
struts.messages.invalid.token = \u8868\u5355\u4e0d\u5141\u8bb8\u91cd\u590d\u63d0\u4ea4
struts.messages.invalid.token = 不能重复提交
6,Strust2与Servlet API
第一种方式:使用ActionContext
Java代码
/**
* ActionContext类降低了与servlet API的耦合(获得不了response)
*/
// 实例化,用ActionContext的getContext()静态方法
ActionContext actionContext = ActionContext.getContext();
// 与request.setAttribute("mengya", "xiaobo")类似
actionContext.put("mengya", "xiaobo");
// request.getAttribute("mengya")类似
actionContext.get("mengya");
// 相当于ServletContext
// Returns a Map of the ServletContext when in a servlet environment or
// a generic application level Map otherwise
actionContext.getApplication();
// 相当于HttpServletSession
Map session = actionContext.getSession();
// 相当于request.getParameterMap();
Map parametersMap = actionContext.getParameters();
/**
* ActionContext类降低了与servlet API的耦合(获得不了response)
*/
// 实例化,用ActionContext的getContext()静态方法
ActionContext actionContext = ActionContext.getContext();
// 与request.setAttribute("mengya", "xiaobo")类似
actionContext.put("mengya", "xiaobo");
// request.getAttribute("mengya")类似
actionContext.get("mengya");
// 相当于ServletContext
// Returns a Map of the ServletContext when in a servlet environment or
// a generic application level Map otherwise
actionContext.getApplication();
// 相当于HttpServletSession
Map session = actionContext.getSession();
// 相当于request.getParameterMap();
Map parametersMap = actionContext.getParameters();
第二种方式:让Action实现ServletRequestAware或ServletResponseAware接口
/**
* 获得HttpServletRequest 实现ServletRequestAware接口
*
* @author 张明学
*
*/
public class RegisterAction2 extends ActionSupport implements ModelDriven,
ServletRequestAware {
private HttpServletRequest request;
private RegisterBean loginBean = new RegisterBean();
public Object getModel() {
return loginBean;
}
@Override
public String execute() throws Exception {
request.setAttribute("mengya", "xiaobo");
request.getAttribute("mengya");
return SUCCESS;
}
public void setServletRequest(HttpServletRequest arg0) {
request = arg0;
}
}
/**
* 获得HttpServletResponse 实现ServletResponseAware接口
*
* @author 张明学
*
*/
public class RegisterAction3 extends ActionSupport implements ModelDriven,
ServletResponseAware {
private HttpServletResponse response;
private RegisterBean loginBean = new RegisterBean();
public Object getModel() {
return loginBean;
}
@Override
public String execute() throws Exception {
Cookie cookie = new Cookie("username", this.loginBean.getUsername());
response.addCookie(cookie);
return SUCCESS;
}
public void setServletResponse(HttpServletResponse arg0) {
this.response = arg0;
}
}
第三种方式:ServletActionContext
/**
* ServletActionContext真接获得HttpServletRequest和HttpServletResponse
*/
HttpServletRequest reqeust = ServletActionContext.getRequest();
HttpSession httpsession = reqeust.getSession();
HttpServletResponse response = ServletActionContext.getResponse();
7,Action多方法调用
方式一:
在struts.xml中的action标签中添加method值如:
<!-- 没有method属性值则这是MyTestAction默认的调用方法即execute方法将被调用 -->
<action name="myTest" class="com.mengya.action.MyTestAction">
<result name="success">/index.jsp</result>
</action>
<!-- method属性值为text1则这是MyTestAction调用方法即text1方法将被调用 -->
<action name="text1" class="com.mengya.action.MyTestAction" method="text1">
<result name="success">/index.jsp</result>
</action>
方式二:
在struts.xml中的action标签不改
<action name="myTest" class="com.mengya.action.MyTestAction">
<result name="success">/index.jsp</result>
</action>
页面修改:
<a href="myTest.action">Action默认的方法</a><br>
<a href="myTest!text1.action">Action的text1方法</a><br>
<a href="myTest!text2.action">Action的text2方法</a>
方式三:通配符(个人不推荐使用)
struts.xml的配置:
<action name="*myTest" class="com.mengya.action.MyTestAction" method={1}>
<result name="success">/index.jsp</result>
</action>
页面:
<a href="myTest.action">Action默认的方法</a><br>
<a href="text1myTest.action">Action的text1方法</a><br>
<a href="text2myTest.action">Action的text2方法</a>
8,result标签的type的类型
在struts2-core-2.1.6.jar中的struts-default.xml中:
<result-types>
<!-- Action链 -->
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<!-- 默认的type类型,请求转发 request.getRequestDispatcher(url).forward(request, response)-->
<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"/>
<!-- 重定向response.sendRedirect(url); -->
<result-type name="redirect" class="org.apache.struts2.dispatcher.ServletRedirectResult"/>
<!-- 重定向到另一个Action -->
<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" />
</result-types>