Action
具体视图的返回可以由用户自己定义的Action来决定,具体的手段是根据返回的字符串找到对应的配置项,来决定视图的内容
一、具体Action的实现
1、可以是一个普通的java类,里面有public String execute方法即可
package com.ncepu.struts; public class Action1 { public String execute() { System.out.print("在普通类中定义execute()方法"); return("success"); } }
2、或者实现Action接口
package com.ncepu.struts; import com.opensymphony.xwork2.Action; public class Action2 implements Action { public String execute() throws Exception { System.out.print("实现Action接口"); return "success"; } }
3、不过最常用的是从ActionSupport继承,好处在于可以直接使用Struts2封装好的方法
package com.ncepu.struts; import com.opensymphony.xwork2.ActionSupport; public class Action3 extends ActionSupport { public String execute() { System.out.print("继承ActionSupport类"); return("success"); } }
二、helloworld 例子中里面action没有配置class
<action name="hello"> <result> /index.jsp </result> </action>
就是默认为ActionSupport,里面的execute方法返回success
public String execute() throws Exception { return SUCCESS; }
三、DMI(dynami method invocation)动态方法调用
1、action不一定非得执行execute方法,可以指定调用具体的方法。不写的话默认为execute方法
action方法中的method方法指定调用具体的方法。
<action name="action1" class="com.ncepu.struts2.Action1" method="notexecute"> <result name="success"> /index.jsp </result> </action>
2、DMI 动态方法调用 用!号
<action name="user" class="com.ncepu.struts2.Action1" > <result name="success"> /add.jsp </result> </action>
jsp中<a href="user!add">添加学生</a> 自动调用Action1下面的add方法
也可直接访问 http://localhost:8080/Struts2_DMI/user!add
四、通配符
action配置
<action name="*_*" class="com.ncepu.struts2.{1}Action" method="{2}{1}"> <result name="success"> /{2}_{1}.jsp </result> </action>
jsp页面链接
<a href="Student_add">添加学生</a> <a href="Student_delete">删除学生</a> <a href="Teacher_add">添加教师</a> <a href="Teacher_delete">删除教师</a>
也可直接访问http://localhost:8080/Struts2_tongpeifu2/Student_delete思考:
仅用动态方法调用,result对于不同的action无法配置。要不只能到学生的jsp 要不只能到教师的jsp。
五、action接收参数
1、<a href="user!add?name=12345&password=12345">添加学生</a> 其中name和password是 action中的参数,并且有相应的getter和setter方法
2、使用Domain Model接收参数(最常用)
<a href="user/user!add?user.name=a&user.password=8">添加用户</a>
其中user是action中的参数,有getter和setter方法,而user是我们自己定义的域模型,里面有name和password参数
package com.ncepu.struts2; import com.ncepu.struts2.entity.User; public class Action1 { private User user; public User getUser() { return user; } public void setUser(User user) { this.user = user; } public String add() { System.out.println("添加的name="+this.user.getName()+"添加的password="+this.user.getPassword()); return ("success"); } }
或者用DTO传输数据,相当于VO value object ),比如注册的时候,得输入两遍密码,可以定义一个vo,包含3个属性,用户名,密码,确认密码,然后根据vo生成实体,该实体只包含用户名和密码两个属性。
3、使用ModelDriven接收参数
action实现ModelDriven接口,里面生成一个模型对象
public class Action1 extends ActionSupport implements ModelDriven<User>{ private User user = new User(); public String add() { System.out.println("name=" + user.getName()); System.out.println("age=" + user.getPassword()); return SUCCESS; } public User getModel() { return user; } }
<a href="user/user!add?name=a&password=8">添加用户</a>
会直接把属性设置到getModel方法获得的模型上面。
六、中文乱码问题
<form action="user!add" method="post"> 必须为post ,get就出错,action得不到值
七、简单验证
public String add() { if(name == null || !name.equals("admin")) { this.addFieldError("nameerror", "name is error"); this.addFieldError("nameerror", "name is too long"); this.addFieldError("passworderror", "password is not correct!"); return ERROR; } return SUCCESS; }
相应的在页面上
<s:fielderror fieldName="nameerror" theme="simple" /> <s:fielderror fieldName="passworderror" theme="simple" /> <s:property value="errors.nameerror" /> <s:property value="errors.nameerror[0]" /> <s:property value="errors.nameerror[1]" /> <s:property value="errors.passworderror" /><s:property value="errors.passworderror[0]" /> <s:debug></s:debug>
errors fieldErrors和action中所有的属性都会存在Value Stack Contents中
fielderror相当于一个数组,可以取所有,也可以取一个。
八、获得web元素4种方法
map类型的request session application(1、通过容器获得,2、实现aware接口通过IoC获得)
真实类型的request session application(3、通过容器获得,4、实现aware接口通过IoC获得)
1、通过容器获得map类型的request session application
package com.struts2.action; import java.util.Map; import com.opensymphony.xwork2.ActionContext; import com.opensymphony.xwork2.ActionSupport; public class Action1 extends ActionSupport { /** * */ private static final long serialVersionUID = 1L; private Map<String, Object> request; private Map<String, Object> session; private Map<String, Object> application; public Action1() { request = (Map) ActionContext.getContext().get("request"); session = ActionContext.getContext().getSession(); application = ActionContext.getContext().getApplication(); } public String execute() { request.put("r1", "requestpara"); session.put("s1", "sessionpara"); application.put("a1", "applicationpara"); return SUCCESS; } }
2、实现aware接口通过IoC获得map类型的request session application,(最常用)
package com.struts2.action; import java.util.Map; import org.apache.struts2.interceptor.ApplicationAware; import org.apache.struts2.interceptor.RequestAware; import org.apache.struts2.interceptor.SessionAware; import com.opensymphony.xwork2.ActionSupport; public class Action2 extends ActionSupport implements RequestAware, SessionAware, ApplicationAware { /** * */ private static final long serialVersionUID = 1L; private Map<String, Object> request; private Map<String, Object> session; private Map<String, Object> application; public void setRequest(Map<String, Object> request) { this.request = request; } public void setSession(Map<String, Object> session) { this.session = session; } public void setApplication(Map<String, Object> application) { this.application = application; } public String execute() { request.put("r1", "requestpara"); session.put("s1", "sessionpara"); application.put("a1", "applicationpara"); return SUCCESS; } }
3、通过容器获得真实类型的request session application
package com.struts2.action; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionSupport; public class Action3 extends ActionSupport { /** * */ private static final long serialVersionUID = 1L; HttpServletRequest request; HttpSession session; ServletContext application; public Action3() { request = ServletActionContext.getRequest(); session = request.getSession(); application = session.getServletContext(); } public String execute() { request.setAttribute("r1", "requestpara"); session.setAttribute("s1", "sessionpara"); application.setAttribute("a1", "applicationpara"); return SUCCESS; } }
4、实现aware接口通过IoC获得真实类型的request session application
package com.struts2.action; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.struts2.interceptor.ServletRequestAware; import com.opensymphony.xwork2.ActionSupport; public class Action4 extends ActionSupport implements ServletRequestAware { /** * */ private static final long serialVersionUID = 1L; HttpServletRequest request; HttpSession session; ServletContext application; public void setServletRequest(HttpServletRequest request) { this.request = request; this.session = request.getSession(); application = session.getServletContext(); } public String execute() { request.setAttribute("r1", "requestpara"); session.setAttribute("s1", "sessionpara"); application.setAttribute("a1", "applicationpara"); return SUCCESS; } }
login_success.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib uri="/struts-tags" prefix="s" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=GB18030" /> <title>Insert title here</title> </head> <body> User Login Success! <br /> <s:property value="#request.r1"/> | <%=request.getAttribute("r1") %> <br /> <s:property value="#session.s1"/> | <%=session.getAttribute("s1") %> <br /> <s:property value="#application.a1"/> | <%=application.getAttribute("a1") %> <br /> <s:property value="#attr.a1"/><br /> <s:property value="#attr.s1"/><br /> <s:property value="#attr.r1"/><br /> <s:debug></s:debug> <br /> </body> </html>
九、include 包含其他配置action的xml文件
<struts> <constant name="struts.devMode" value="true" /> <include file="module1.xml"></include> </struts>
而module1.xml文件中配置着action
十、namespace的默认action
<struts> <constant name="struts.devMode" value="true" /> <package name="default" namespace="/action" extends="struts-default"> <default-action-ref name="action1"></default-action-ref> <action name="action1" class="com.ncepu.struts2.Action1"> <result name="success"> /default.jsp </result> </action> </package> </struts>
每个package可以有一个默认的action,当没有匹配的时候时,就使用它,如用户输入错误时,根据他跳到默认的错误界面
十一、路径问题
1、action跳转
result都需要指定目标资源的URL,如果这个路径以“/”开始。代表的是应用程序根目录。
<package name="default" namespace="/path" extends="struts-default"> <action name="hello"> <result> /path.jsp </result> </action> </package>
其中path在webroot根目录下。能找到。如果是下面的配置
<package name="default" namespace="/path" extends="struts-default"> <action name="hello"> <result> path.jsp </result> </action> </package>
则不行,当前目录是Struts2_path/path/hello.action,相当于在当前目录查找,即/Struts2_path/path/path.jsp
2、jsp链接都使用绝对路径:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <a href="path.jsp"> path.jsp</a> <br> </body> </html>
定义path ,然后再head便签中添加<base href="<%=basePath%>">,相当于都从web应用的根目录下面找。