在这篇《Struts2学习之配置单个Action多控制处理逻辑》文章中,讲到指定method属性时,列举了以下的配置代码:
代码如下 | 复制代码 |
<struts> <constant name="struts.enable.DynamicMethodInvocation" value="true" /> <package name="lee" extends="struts-default" namespace="/"> <action name="registAction" class="com.jellythink.practise.LoginAction" method="regist"> |
可以发现,上面配置的两个Action,有很大一部分是类似的,存在冗余的现象。在Struts2框架中,允许使用通配符的方式进行配置。下面就利用Struts2框架的这一特性对上述这段配置代码进行重构。
重构第一步
在配置<action .../>元素时,允许在指定name属性时使用模式字符串(即用“*”代表一个或多个任意字符),接下来就可以在class、method属性及<result .../>子元素中使用{N}的形式来代表前面第N个星号所匹配的子串。基于此,文章一开始的配置代码可以重构为以下这样:
代码如下 | 复制代码 |
<struts> <constant name="struts.enable.DynamicMethodInvocation" value="true" /> <package name="lee" extends="struts-default" namespace="/"> |
上面的<action name="*Action" .../>元素不是定义了一个普通Action,而是定义了一系列的逻辑Action。只要用户请求的URL是*Action.action的模式,都可以使用该Action来处理。配置该action元素时,还指定method属性,但该method属性使用了一个表达式{1},该表达式就是name属性值中第一个*的值。例如:如果用户请求的URL为loginAction.action,则调用对应的login方法;如果为registAction.action,则调用regist方法。对于<result .../>子元素中使用的/{1}.jsp也是同样的道理。
重构第二步
更多时候,我们希望action对应的class属性也可以进行模式匹配,这样的话灵活性更高。比如现在有两个Action类,分别为:com.jellythink.practise.LoginAction和com.jellythink.practise.RegistAction,这两个类分别完成登陆与注册行为。当action的name匹配到loginAction时,则对应的class则为com.jellythink.practise.LoginAction;当匹配到registAction时,则对应的clas则为com.jellythink.practise.RegistAction。按照这样的需求,上述的配置代码又可以修改为这样:
代码如下 | 复制代码 |
<struts> <constant name="struts.enable.DynamicMethodInvocation" value="true" /> <package name="lee" extends="struts-default" namespace="/"> |
在上述配置代码中,action的name属性为*_*,这需要我们在前台页面设置action的值时按照指定的规则进行设定,例如:类名_方法名。当用户请求的URL是Login_login.action的模式时,则{1}代表的值为Login,而对应的{2}代表的值为login;同理,当请求为Regist_regist.action的模式时,则{1}代表的值为Regist,而对应的{2}代表的值为regist。
通过这种方式,配置代码的灵活性更高,写法更简单。
到底使用哪个?
通过使用模式匹配的方式,就会引申出另一个问题。比如有下面这段配置代码:
代码如下 | 复制代码 |
<struts> <constant name="struts.enable.DynamicMethodInvocation" value="true" /> <package name="lee" extends="struts-default" namespace="/"> <!--Action2--> <!--Action3--> |
问题是,如果客户端请求的URL是getBookInfoAction.action,那么到底匹配哪个Action呢?对于Struts2框架来说,规则是这样的:
如果请求URL是getBookInfoAction.action,如果struts.xml文件中有名为getBookInfoAction的Action配置,则一定由该Action来处理用户请求
如果struts.xml文件中没有名为getBookInfoAction的Action配置,则搜寻name属性值能匹配getBookInfoAction的Action,例如name为Action或,*Action并不会比*更优先匹配getBookInfoAction的请求,这取决于这两个Action定义的先后顺序
例子
1、 ActionMethod:Action执行的时候并不一定要执行execute方法,可以在配置文件中配置action的时候用“method”属性来指定执行哪个方法,也可以在url地址中动态指定(动态方法调用DMI)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> <constant name="struts.devMode" value="true" /> <package name="user" extends="struts-default" namespace="/user"> <action name="userAdd" class="com.bjsxt.struts2.user.action.UserAction" method="add"> <result>/user_add_success.jsp</result> </action> <action name="user" class="com.bjsxt.struts2.user.action.UserAction"> <result>/user_add_success.jsp</result> <result name="delete">/user_delete_success.jsp</result> </action> </package> </struts> |
Index.jsp页面的内容:
代码如下 | 复制代码 |
<?xml version="1.0" encoding="GB18030" ?> <%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <% String context = request.getContextPath(); %> <!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> <a href="<%=context %>/user/userAdd">添加用户</a><br /> <a href="<%=context %>/user/user!add">添加用户</a><br /> <a href="<%=context %>/user/user!delete">删除用户</a><br /> </body> </html> |
UserAction的内容:
代码如下 | 复制代码 |
package com.bjsxt.struts2.user.action; import com.opensymphony.xwork2.ActionSupport; public class UserAction extends ActionSupport { public String add() { return SUCCESS; } public String delete(){ return "delete"; } } |
2、 使用通配符
Strtus.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> <constant name="struts.devMode" value="true" /> <package name="actions" extends="struts-default" namespace="/actions"> <action name="Student*" class="com.bjsxt.struts2.action.StudentAction" method="{1}"> <result>/Student{1}_success.jsp</result> </action> <action name="*_*" class="com.bjsxt.struts2.action.{1}Action" method="{2}"> <result>/{1}_{2}_success.jsp</result> </action> </package> </struts> |
Action的内容:
代码如下 | 复制代码 |
public class CourseAction extends ActionSupport { public String add() { return SUCCESS; } public String delete() { return SUCCESS; } } public class StudentAction extends ActionSupport { public String add() { return SUCCESS; } public String delete() { return SUCCESS; } } public class TeacherAction extends ActionSupport { public String add() { return SUCCESS; } public String delete() { return SUCCESS; } } |
Index.jsp页面的内容:
代码如下 | 复制代码 |
<?xml version="1.0" encoding="GB18030" ?> <%@ page language="java" contentType="text/html; charset=GB18030" pageEncoding="GB18030"%> <%String context = request.getContextPath();%> <!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> 使用通配符,将配置量降到最低<br /> <a href="<%=context%>/actions/Studentadd">添加学生</a> <a href="<%=context%>/actions/Studentdelete">删除学生</a><br /> 不过,一定要遵守"约定优于配置"的原则<br /> <a href="<%=context%>/actions/Teacher_add">添加老师</a> <a href="<%=context%>/actions/Teacher_delete">删除老师</a> <a href="<%=context%>/actions/Course_add">添加课程</a> <a href="<%=context%>/actions/Course_delete">删除课程</a> </body> </html> |
相应的jsp页面有:
Course_add_seccess.jsp
Course_delete_success.jsp
Teacher_add_seccess.jsp
Teacher_delete_success.jsp
Studentadd_success.jsp
Studentdelete_success.jsp
总结
在日后的工作中,使用这样的技巧来重构代码,会带来很多好处,比如配置代码更加精简了,更加容易管理和维护了,更加容易读懂了等等。如果你说你不想用这些东西,那也好,至少你需要知道有这么个东西的存在,好让你去读懂别人写的代码。