Struts2中一些零碎的知识点:struts.xml详解、模型驱动、Preparable接口、防止表单重复提交、ActionContext、动态方法调用、异常
?
?
?
1、struts.xml详解
a. struts.properties
??? 在struts.xml中可以定义constant覆盖struts-core.jar/org/apache/struts2/default.properties中的设置。
??? 例:<constant name="struts.custom.i18n.resources" value="message"/>
?? ?也可以直接新建struts.properties(与struts.xml在同一目录),在struts.properties中配置。推荐在struts.properties中进行配置。
?? ?例:struts.custom.i18n.resources = message
b. abstract package
?? ?struts-core.jar/struts-default.xml,中有如下定义。
?? ?<package name="struts-default"?abstract="true">
?? ??? ?......
?? ?</package>
?? ?其中abstract="true"中,表示在此package中不能定义Action(与Java abstract类相似),仅供继承。
c. namespace
?? ?strut.xml中:
?? ?<package name="MyStruts" extends="struts-default"?namespace="/mystruts">
?? ?......
?? ?</package>
?? ?默认命名空间为namespace="",命名空间要以"/"开头。
?? ?JSP访问:<s:form action="miscellaneous"?namespace="/mystruts">。
?? ?不能写成<s:form action="/mystruts/miscellaneous"> ,否则会发生错误:"No configuration found for the specified action: '/mystruts/miscellaneous' in namespace: '/miscellaneous'. Form action defaulting to 'action' attribute's literal value."[2]。
d. 模块化配置
?? ?......
?? ?<struts>
?? ??? ?<include?file="struts1.xml" />
?? ??? ?<package ...>
?? ??? ??? ?......
?? ??? ?</package>
?? ?</struts>
?? ?include中struts1.xml的编写与struts.xml是类似的。
2、属性驱动与模型驱动
属性驱动:直接在Action中写表单属性。
/StrutsHelloWorld/src/wintys/struts2/miscellaneous/MiscellaneousAction.java:
?
?
?
package wintys.struts2.miscellaneous; import com.opensymphony.xwork2.ActionSupport; /** * * @author Winty (wintys@gmail.com) * @version 2009-8-24 * @see http://wintys.blogjava.net */ @SuppressWarnings("serial") public class MiscellaneousAction extends ActionSupport { private String name; private String password; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String execute() throws Exception { return SUCCESS; } }
?
?
?
模型驱动:将属性放到JavaBean中,Action需要实现com.opensymphony.xwork2.ModelDriven接口。ModelDrivenInterceptor 必须在之前StaticParametersInterceptor and ParametersInterceptor。这个顺序已在defaultStack Interceptor中定义。
/StrutsHelloWorld/src/wintys/struts2/miscellaneous/User.java:
?
?
?
?
package wintys.struts2.miscellaneous; /** * 模型驱动Action中的模型 * @author Winty (wintys@gmail.com) * @version 2009-8-25 * @see http://wintys.blogjava.net */ public class User { private String name; private String password; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } }?
?
?
/StrutsHelloWorld/src/wintys/struts2/miscellaneous/MiscellaneousModelDrivenAction.java:
?
?
?
package wintys.struts2.miscellaneous; import com.opensymphony.xwork2.ModelDriven; @SuppressWarnings("serial") public class MiscellaneousModelDrivenAction extends ActionSupport implements ModelDriven<User>{ private User user = new User(); @Override public User getModel() { return user; } @Override public String execute() throws Exception { return SUCCESS; } }?
?
3、Preparable接口
?? ?Action还可以实现com.opensymphony.xwork2.Preparable接口,用于准备Action自己。Preparable中的prepare方法在Action执行其它方法前执行。
4、使用simple 主题时,如何单独格式化Struts错误提示信息
?? ?单独显示name字段的fielderror:
?
?
<s:fielderror> <s:param>name</s:param> </s:fielderror>?
?
5、Struts防止表单重复提交
?? ?JSP页面中加入token和actionerror:
<s:actionerror />
<s:form .../>
?? ?<s:token />
</s:form>
?? ?token产生的actionerror的i18n key为:struts.message.invalid.token。
?? ?在struts.xml中的Action配置中加入token interceptor,和invalid.token result:
?
?
<action name="miscellaneous" class="wintys.struts2.miscellaneous.MiscellaneousModelDrivenAction"> <result name="success">/miscellaneous/output.jsp</result> <result name="input">/miscellaneous/input.jsp</result> <result name="invalid.token" >/miscellaneous/input.jsp</result> <interceptor-ref name="token" /> <interceptor-ref name="defaultStack" /> </action>?
?生成的JSP页面如下:
?? ?<input type="hidden" name="struts.token.name" value="struts.token" />
?? ?<input type="hidden" name="struts.token" value="ORU0RZIP8JWQ7BDZG4P1NJSEKITGG6X5" />
?? ?struts.token.name指<s:token />中的name,默认为struts.token。也可以自己指定<s:token name="mytoken" />。则生成如下token:
?? ?<input type="hidden" name="struts.token.name" value="mytoken" />
?? ?<input type="hidden" name="mytoken" value="GFD13EW206G2DY9AB3SRIAVXXT1S915C" />
6、通过Struts获取Servlet API
?? ?一般Java Web程序不能离开容器进行测试。容器内测试常用框架:Cactus(jakarta.apache.org/cactus/index.html) 、Mock。
?? ?通过Struts获取Servlet API,使程序可脱离容器测试。Struts中可通过如下方法获取Servlet API:ActionContext 、ServletActionContext、ServletXXXAware。首选ActionContext,其次选择ServletActionContext,再次ServletXXXAware。
a. ActionContext
?? ?com.opensymphony.xwork2.ActionContext.getActionContext()获取ActionContext实例。
?? ?ActionContext的get()和put()方法与HttpServletRequest的对应关系:
?? ?ActionContext.get() <=> HttpServletRequest.getAttribute()
?? ?ActionContext.put() <=> HttpServletRequest.setAttribute()
?? ?例:
ActionContext context = ActionContext.getContext(); context.put("info", "this is ActionContext value");?但是ActionContext无法获取Servlet HttpResponse对象。
b. ServletActionContext
?? ?org.apache.struts2.ServletActionContext是com.opensymphony.xwork2.ActionContext的子类。
?? ?使用静态方法直接获取Servlet对象:
?? ?Request: ServletActionContext.getRequest();
?? ?Response: ServletActionContext.getResponse();
?? ?Session: ServletActionContext.getRequest().getSession();
?? ?例:
Cookie cookie = new Cookie("mycookie" , "10000"); HttpServletResponse response = ServletActionContext.getResponse(); response.addCookie(cookie);?c. ServletXXXAware接口
?? ?org.apache.struts2.util.ServletContextAware接口
?? ?org.apache.struts2.interceptor.ServletRequestAware接口
?? ?org.apache.struts2.interceptor.ServletResponseAware接口
?? ?org.apache.struts2.interceptor.SessionAware接口
?? ?实现ServletXXXAware接口的Action会被Struts自动注入相应的Servlet对象。
?? ?例:
package wintys.struts2.miscellaneous; import org.apache.struts2.interceptor.ServletRequestAware; import com.opensymphony.xwork2.ActionSupport; @SuppressWarnings("serial") public class MiscellaneousModelDrivenAction extends ActionSupport implements ServletRequestAware { private HttpServletRequest request; ...... @Override public String execute() throws Exception { //实现ServletRequestAware接口,Struts自动注入的request Cookie[] cookies = this.request.getCookies(); for(Cookie ck : cookies){ System.out.print("cookie:" + ck.getName()); System.out.println(" = " + ck.getValue()); } return SUCCESS; } ...... @Override public void setServletRequest(HttpServletRequest request) { this.request = request; } }?7、动态方法调用
a. Action配置中,由method指定动态调用方法的名称。
<action name="myaction" class="com.tests.MyAction" method="myexecute">
......
</action>
b.在JSP页面中,调用Action时加感叹号指定动态调用方法的名称。
<s:form action="myaction!myexecute" />
c.通配符
<action name="*action" class="com.tests.MyAction" method="{1}">
则请求中helloaction对应到action中的hello()方法,以此类推。
8、异常
?? ?发生异常时,可转到指定的result。由exception-mapping配置
?
<action name="miscellaneous" class="wintys.struts2.miscellaneous.MiscellaneousModelDrivenAction"> <result name="success">/miscellaneous/output.jsp</result> <result name="input">/miscellaneous/input.jsp</result> <exception-mapping exception="wintys.struts2.miscellaneous.NameInvalidException" result="nameInvalid" /> <result name="nameInvalid">/miscellaneous/nameInvalidException.jsp</result> </action>
?
也可以配置全局exception mapping
?
<global-exception-mapping> <exception-mapping result="nameInvalid" /> </global-exception-mapping>
?
?nameInvalidException.jsp:
<s:property value="exception"/> <s:property value="exceptionStack" />
?NameInvalidException.java:
package wintys.struts2.miscellaneous; @SuppressWarnings("serial") public class NameInvalidException extends Exception { public NameInvalidException(String message) { super(message); } }?9、详细代码
/StrutsHelloWorld/WebRoot/miscellaneous/input.jsp:
?
<%@ page language="java" contentType="text/html;charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>Input</title> </head> <body> <s:actionerror/> <s:form action="miscellaneous" method="post" theme="simple" namespace="/mystruts"> <s:token name="mytoken"/> 用户名:<s:textfield name="name" /> <s:fielderror > <s:param>name</s:param> </s:fielderror> <br /> 密码:<s:textfield name="password"/> <s:fielderror > <s:param>password</s:param> </s:fielderror> <br /> <s:submit name="提 交" /> </s:form> <hr /> 动态方法调用方法二: miscellaneous!myexecute <s:form action="miscellaneous!myexecute" namespace="/mystruts"> <s:token name="mytoken"/> <s:hidden name="name" value="test" /> <s:hidden name="password" value="test" /> <s:submit name="提交执行myexecute() " /> </s:form> </body> </html>
?/StrutsHelloWorld/WebRoot/miscellaneous/output.jsp:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>Output</title> </head> <body> 提交结果:<br/> 用户名:<s:property value="name"/> <br /> 密码:<s:property value="password"/> <br /> <hr /> ${request.info} ${cookie.mycookie.value } </body> </html>
?/StrutsHelloWorld/src/wintys/struts2/miscellaneous/MiscellaneousModelDrivenAction.java:
?
package wintys.struts2.miscellaneous; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts2.ServletActionContext; import org.apache.struts2.interceptor.ServletRequestAware; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; import com.opensymphony.xwork2.ModelDriven; /** * Struts2深入探索 * @author Winty (wintys@gmail.com) * @version 2009-8-26 * @see http://wintys.blogjava.net */ @SuppressWarnings("serial") public class MiscellaneousModelDrivenAction extends ActionSupport implements ModelDriven<User> , ServletRequestAware { private User user = new User(); private HttpServletRequest request; @Override public User getModel() { return user; } @Override public String execute() throws Exception { System.out.println("this is model driven action"); if(user.getName().equals("admin")){ throw new NameInvalidException("name 'admin' is invalid"); } //ActionContext.put相当于HttpServletRequest.setAttribute() ActionContext context = ActionContext.getContext(); context.put("info", "this is ActionContext value"); //ServletActionContext.getResponse得到Response对象 Cookie cookie = new Cookie("mycookie" , "10000"); HttpServletResponse response = ServletActionContext.getResponse(); response.addCookie(cookie); //实现ServletRequestAware接口,Struts自动注入的request Cookie[] cookies = this.request.getCookies(); for(Cookie ck : cookies){ System.out.print("cookie:" + ck.getName()); System.out.println(" = " + ck.getValue()); } return SUCCESS; } public String myexecute()throws Exception{ System.out.println("myexecute()"); return SUCCESS; } @Override public void validate() { if(user.getName() == null || user.getName().equals("")){ this.addFieldError("name", "invalid name"); } } @Override public void setServletRequest(HttpServletRequest request) { this.request = request; } }
?
?
/src/struts.xml:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="MyStruts" extends="struts-default" namespace="/mystruts"> <!-- Struts2深入探索 --> <action name="miscellaneous" class="wintys.struts2.miscellaneous.MiscellaneousModelDrivenAction"> <result name="success">/miscellaneous/output.jsp</result> <result name="input">/miscellaneous/input.jsp</result> <exception-mapping exception="wintys.struts2.miscellaneous.NameInvalidException" result="nameInvalid" /> <result name="nameInvalid">/miscellaneous/nameInvalidException.jsp</result> <result name="invalid.token" >/miscellaneous/input.jsp</result> <interceptor-ref name="token" /> <interceptor-ref name="defaultStack" /> </action> </package> </struts>?[参考资料]:
??? [1]《浪曦视频之Struts2应用开发系列》
?? ?[2] No configuration found for the specified action :?http://javasunnyboy.javaeye.com/blog/254753
?
?
?
?
?
该篇BOLG 摘自 ?http://www.blogjava.net/wintys/archive/2009/08/29/struts_helloworld_miscellaneous.html
?
?
感谢博主的分享. 觉得很实用就全文摘抄下来了..呵呵~~