在对Struts2的工作原理学习之后,对Struts2的Action进行学习。主要对Struts2文档Guides中的Action分支进行学习,如下图:
1、Model Driven(模型驱动)
Struts2可以让开发者不必在需要接收很多参数的时候,在Action定义一系列的属性,或者定义一个类属性传参的时候使用className.fieldName的形式传值。使用Struts2的Model Driven需要打开Model Driven拦截器,不过这个拦截器(scopedModelDriven)默认是打开的,只要将自己的包继承“struts-default”包即可(<package name="..." extends="struts-default" namespace="...">)。
(1)利用模型驱动进行开发,Action需要实现ModelDriven接口,并重写getModel()提供泛型中的Model对象。
1 package yaolin.core.action; 2 3 import com.opensymphony.xwork2.ModelDriven; 4 import yaolin.core.entity.Person; 5 6 public class PersonAction implements ModelDriven<Person>{ 7 8 private Person person = new Person(); 9 10 public String input() { 11 return "input"; 12 } 13 14 public String index() { 15 return "index"; 16 } 17 // 重写ModelDriven的getModel()方法并提供Model对象 18 @Override 19 public Person getModel() { 20 return person; 21 } 22 // UI getter 这里只是方便页面取值 23 public Person getPerson() { 24 return person; 25 } 26 }
(2)Model有两个属性(name、age),提供必要getter和setter。
1 package yaolin.core.entity; 2 3 public class Person { 4 5 private String name; 6 private int age; 7 8 public String getName() { 9 return name; 10 } 11 12 public void setName(String name) { 13 this.name = name; 14 } 15 16 public int getAge() { 17 return age; 18 } 19 20 public void setAge(int age) { 21 this.age = age; 22 } 23 }
(3)创建编辑页面(input.jsp)和回显页面(index.jsp),访问input.action到input.jsp填写信息提交到person.action(index方法处理)到index.jsp回显。
input.jsp不需要参数名不需要使用person.name、person.age,直接使用name和age。
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <!DOCTYPE html> 4 <html> 5 <head> 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 7 <title>INPUT</title> 8 </head> 9 <body> 10 <!-- /person/... --> 11 <form action="person.action" method="post"> 12 <input name="name"> 13 <input name="age"> 14 <input type="submit" value="to_index"> 15 </form> 16 </body> 17 </html>
index.jsp直接获取person的值。
1 <%@ page language="java" contentType="text/html; charset=UTF-8" 2 pageEncoding="UTF-8"%> 3 <!DOCTYPE html> 4 <html> 5 <head> 6 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 7 <title>INPUT</title> 8 </head> 9 <body> 10 ${person.name} - ${person.age} 11 </body> 12 </html>
(4)修改struts.xml对访问路径进行路由
1 <!DOCTYPE struts PUBLIC 2 "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" 3 "http://struts.apache.org/dtds/struts-2.3.dtd"> 4 <struts> 5 <package name="person" extends="struts-default" namespace="/person"> 6 <action name="person" class="yaolin.core.action.PersonAction" method="index"> 7 <result name="index">/index.jsp</result> 8 </action> 9 <action name="input" class="yaolin.core.action.PersonAction" method="input"> 10 <result name="input">/input.jsp</result> 11 </action> 12 </package> 13 </struts>
(5)访问input.action填写信息并提交观察结果
如果没有Model Driven则需要在Action,定义两个属性name、age而不是person并提供getter和setter,或者定义person并提供getter和setter同时将页面参数名称改成person.name、person.age
2、Action Chaining (Aciton链)
Action链可以将一个请求经过多个Action处理,并保持Request中的参数,这个Redirect重定向有点区别,Action链可以将请求叫同一个namespace的action处理,也可以交给其他namespace的action处理,实现Action Chain需要将result的type设置成“chain”。
(1)修改Struts.xml添加chain.action,还是使用ModelDriven学习中的input方法来处理这个请求,将result的type设置成“chain”把请求交给namespace="/chain"的chain.action处理。
1 <!DOCTYPE struts PUBLIC 2 "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" 3 "http://struts.apache.org/dtds/struts-2.3.dtd"> 4 <struts> 5 <package name="person" extends="struts-default" namespace="/person"> 6 <action name="person" class="yaolin.core.action.PersonAction" method="index"> 7 <result name="index">/index.jsp</result> 8 </action> 9 <action name="input" class="yaolin.core.action.PersonAction" method="input"> 10 <result name="input">/input.jsp</result> 11 </action> 12 <action name="chain" class="yaolin.core.action.PersonAction" method="input"> 13 <result type="chain" name="input"> 14 <param name="actionName">chain</param> 15 <param name="namespace">/chain</param> 16 </result> 17 </action> 18 </package> 19 20 <package name="chain" extends="struts-default" namespace="/chain"> 21 <action name="chain" class="yaolin.core.action.ChainAction" method="index"> 22 <result name="index">/index.jsp</result> 23 </action> 24 </package> 25 </struts>
(2)创建ChainAction对请求进行再次处理,并对额外参数进行处理,结果还是回显在index.jsp页面中。ChainAction中将person的名字加上前缀“Chain:”同时将额外参数extras加到名字后面。
1 package yaolin.core.action; 2 3 import com.opensymphony.xwork2.ModelDriven; 4 5 import yaolin.core.entity.Person; 6 7 public class ChainAction implements ModelDriven<Person>{ 8 9 private Person person = new Person(); 10 private String extra; 11 12 public String index() { 13 // 修改person的name属性 14 person.setName("Chain : " + person.getName() + " " + extra); 15 return "index"; 16 } 17 18 @Override 19 public Person getModel() { 20 return person; 21 } 22 23 // UI 24 public Person getPerson() { 25 return person; 26 } 27 // POI 28 public void setExtra(String extra) { 29 this.extra = extra; 30 } 31 } 32
(3)访问input.action并带上name,age和额外参数extras:http://localhost/person/chain.action?name=yaolin&age=18&extra=chen观察结果
3、ActionEventListener (Action事件监听器)
Action事件监听器可以使开发者在Action创建的时候加入一些业务逻辑,或者在Action处理出错的时候进行处理。整个Struts应用ActionEventListener只要一个实例就可以了,设置成单例,使用ActionEventListener可以在struts.xml中配置bean,ActionEventListener需要实现ActionEventListener接口。
(1)编写自己的ActionEventListener,并重写prepare()和handleException()方法,在prepare()方法中为Action的extra设置值
1 package yaolin.core.listener; 2 3 import com.opensymphony.xwork2.ActionEventListener; 4 import com.opensymphony.xwork2.util.ValueStack; 5 6 import yaolin.core.action.ChainAction; 7 8 public class MyActionEventListener implements ActionEventListener{ 9 10 @Override 11 public Object prepare(Object action, ValueStack stack) { 12 if (action instanceof ChainAction) { 13 // 设置Action的extra值 14 ((ChainAction)action).setExtra("##ChainActionEventListener##"); 15 } 16 return action; 17 } 18 19 @Override 20 public String handleException(Throwable t, ValueStack stack) { 21 if (t != null) { 22 System.err.println(t.getMessage()); 23 } 24 return null; 25 } 26 }
(2)在Struts.xml中配置ActionEventListener,指定其类型为其实现的主要接口com.opensymphony.xwork2.ActionEventListener。其他配置沿用之前两个部分学习的配置。
1 <!DOCTYPE struts PUBLIC 2 "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" 3 "http://struts.apache.org/dtds/struts-2.3.dtd"> 4 <struts> 5 <package name="person" extends="struts-default" namespace="/person"> 6 <action name="person" class="yaolin.core.action.PersonAction" method="index"> 7 <result name="index">/index.jsp</result> 8 </action> 9 <action name="input" class="yaolin.core.action.PersonAction" method="input"> 10 <result name="input">/input.jsp</result> 11 </action> 12 <action name="chain" class="yaolin.core.action.PersonAction" method="input"> 13 <result type="chain" name="input"> 14 <param name="actionName">chain</param> 15 <param name="namespace">/chain</param> 16 </result> 17 </action> 18 </package> 19 20 <package name="chain" extends="struts-default" namespace="/chain"> 21 <action name="chain" class="yaolin.core.action.ChainAction" method="index"> 22 <result name="index">/index.jsp</result> 23 </action> 24 </package> 25 26 <!-- 配置ActionEventListener --> 27 <bean type="com.opensymphony.xwork2.ActionEventListener" class="yaolin.core.listener.MyActionEventListener"></bean> 28 </struts>
(3)直接访问/chain/chain.aciton不带参数,参数由ActionEventListener设置,观察结果
至此,Struts2中Guides的Action Tag学习了。
未完,待续。