Struts2由Struts1和webWork两个经典MVC框架发展起来。与传统的Struts1相比,Struts2允许使用不同的Java对象作为Action。支持更多的视图技术,基于AOP思想的拦截器机制,提供了更好的扩展性,以及更强大更有效的表单校验功能,更为简单的文件上传功能,使得Struts2很受广大开发者青睐。
想要在我们的web项目中搭建struts2框架,首先我们先导入Struts2所需要的jar包,Struts2基本所需要的jar包可以struts2-blank中获取。然后我们还需要再web.xml中配上struts2的核心控制器:StrutsPrepareAndExecuteFilter.
<filter> <filter-name>struts2</filter-name> <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> </filter> <filter-mapping> <filter-name>struts2</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>然后在将struts2-blank中的struts.xml文件放在Resource Folder下面。基本的环境搭建就这么简单。这样在收到请求时通过Struts的过滤器StrutsPrepareAndExecuteFilter就可以处理我们的请求了。
Struts2的简单处理流程就是我们访问Action类的方法,当方法执行完,返回一个String字符串,然后Struts2再在struts.xml中寻找相应的结果视图,然后再通过不同形式转向到jsp页面。
比如:我们编写一个UserAction
public class UserAction { public String execute(){ return null; } public String input(){ return "input"; } public String edit(){ return "input"; } public String update(){ return "update"; } public String view(){ return "view"; } public String delete(){ return "list"; } public String list(){ return "list"; } }相应的我们在struts.xml中配置如下:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <package name="default" namespace="" extends="struts-default"> <action name="user_*" class="com.xiaohui.action.UserAction" method="{1}"> <result name="input" type="dispatcher"> <param name="location">/WEB-INF/jsps/input.jsp</param> </result> <result name="view" type="dispatcher"> <param name="location">/WEB-INF/jsps/view.jsp</param> </result> <result name="list" type="dispatcher"> <param name="location">/WEB-INF/jsps/list.jsp</param> </result> </action> </package> </struts>
上面的action的name属性user_*中的*通配我们的访问的方法,比如我们访问想要查看user的列表,就可以访问:http://127.0.0.1:8080/appName/user_list 即可。
struts.xml文件中的配置信息使用package进行分类和管理,不同的包对应不同的url访问路径,即在访问路径上就能区分出不同模块下的资源。一个包可以继承另外一个包,建议同一个模块采用相同的包。Struts2的通用访问路径:http://ip:port/AppPath/< PackageNamespace>/< ActionName>.< Extension>只要掌握了struts2访问路径的映射原理,也自然就知道如何编写Action的配置信息了。访问路径的默认扩展名为.action或者不使用扩展名。配置结果视图在struts.xml配置文件中配置结果视图,即在struts.xml配置文件中将请求处理方法返回的字符串关联到某个具体的视图资源上,这种映射方式可以实现action程序代码与返回的jsp页面名称的解耦。局部视图:在<action>元素中配置<result>元素全局视图:在<global-results>元素中配置<result>元素<result>元素的三个要素: 类型、名称和若干参数常量配置:在根元素<struts>下可以使用constant子元素配置常量。从strut2的核心jar包内的org.apache.struts2包下的default.properties文件中可以看到各个常量的注释说明,典型几个常量:
Ø<constant name=“struts.action.extension” value=“do,go”/>配置访问Action的后缀,可以配置多个后缀名。 提示:default.properties文件中为该常量配置了一个空字符串。 Ø常量struts.devmode可以让struts在控制台中打印出更多的信息和重新加载配置文件。 Ø常量struts.configuration.xml.reload可以让struts重新加载配置文件,但不会导致web应用重新启动。 Ø常量struts.i18n.encoding可以设置struts内部进行各种字符编码处理时的字符集编码,例如,用于获取请求参数时的解码、读取静态文本文件和输出静态文本文件时的字符解码和编码。 Ø<constant name=“struts.enable.DynamicMethodInvocation” value=“false”/>可以配置不支持动态方法调用。常量可以在下面多个文件中进行定义,struts2加载常量的搜索顺序如下,后面的设置可以覆盖前面的设置:
Ødefault.properties文件 Østruts-default.xml Østruts-plugin.xml Østruts.xml Østruts.properties(为了与webwork向后兼容而提供) web.xmlAction 的定位
- 根据访问路径中的包名部分在struts.xml等配置文件中查找对应的包,如果不存在相应的包,则查找上一层的包名,依此递推,直到追溯出一个存在的最匹配的上层包名。注意,只要一旦追溯到了一个最匹配的上层包名,不管这个包中是否存在要访问的Action,都不会再追溯更上层的包名了。
- 一旦定位到了某个包下,接着就会在这个包中查找action。由于struts会追溯上层包的特点,所以,用某个包的名称空间的子目录形式也可以访问到该包中的Action,前提是该子目录不存在对应的名称空间。
- namespace属性可以设置为空字符串””,即为默认名称空间,如果struts2定位到的包名中不存在当前要访问的Action ,struts2接着还会在默认名称空间寻找该Action,只有在默认名称空间的包名中还没找到该action时,才报错action找不到的错误。
- 注意区分默认名称空间与根(/)名称空间的区别,根(/)名称空间就是一个普通的名称空间,与”/user/admin”、”/user” 等一样,都是具体的包名,只是它是最顶层的名称空间,当struts在某个子名称空间对应的包中没有查找action时,不会再去根(/)名称空间中查找,但会在默认名称空间中继续查找该action。
Struts.xml 中的默认值与 更多配置细节
在根元素<struts>下可以使用include子元素引入其他的配置文件,这样可以将各个模块分散在不同的配置文件中进行配置。 package的name属性用于唯一标识这个包;namespace说明访问其中的各个action时在路径中要增加的目录前缀;extends属性用于说明这个包继承了另外一个包的定义,自己定义的包通常要继承struts-default.xml文件中定义的struts-default包;abstract属性说明这个包为抽象的,其中不能有action元素,struts-default包就是抽象的。package的namespace属性可以不设置,即为默认名称空间。 package元素下可以定义全局视图,如果两个package要共享相同的全局视图,那么为它们定义一个相同的父包。 <action>元素的method属性可以不设置,默认为execute;class属性可以不设置,默认为ActionSupport。 <result>元素的type属性和name属性都可以不设置,默认值分别为dispatcher和success。当<result>元素中只有默认的<param>子元素要设置时,可以将该<param>子元素中的内容直接写在<result>标签中。 在<package>元素下配置<default-action-ref>子元素,用于说明在该包下不存在的action路径映射,都可以统交给一个默认的<action>元素去处理。 在<package>元素下配置<default-class-ref>子元素,用于说明默认的Action类是可以进行配置修改的。动态方法调用
如果Action中存在多个方法时,在struts.xml文件中可以只配置一个<action>元素,访问路径可以在紧跟action名称的后面增加一个感叹号(!)后接着指定要访问的方法名,这就是动态方法调用,语法格式如下:Øhttp://ip:port/AppPath/< PackageNamespace>/< ActionName> !< MethodName>.<extension>如:http://127.0.0.1:8080/appName/user !list http://127.0.0.1:8080/appName/user !input
可以通过常量struts.enable.DynamicMethodInvocation关闭动态方法调用。 尽量不要使用动态方法调用,可以采用*通配符的方式进行替代。* 通配符
在action元素的name属性中可以使用*通配符,它可以匹配除了/以外的多个连续字符,在action元素的class和method属性以及result元素中可以引用*通配符在访问期间实际匹配的内容,例如:<action name="user_*" class="com.xiaohui.action.UserAction" method="{1}"> <result name="{1}" type="dispatcher"> <param name="location">/WEB-INF/jsps/{1}.jsp</param> </result> </action>
如果*匹配的内容为空,则调用execute方法;对于采用下划线连接*的方式,如果访问路径中没有为*部分指定内容,那么在访问路径中还可以省略下划线。 使用*通配符可能导致有多个action元素与一个访问路径匹配,这时候以排在配置文件中最后的配置项为准,所以更具体的模式应在更不具体的模式之后进行配置。访问 Servlet APIl调用ServletActionContext的各个方法
getActionMapping() ØgetPageContext() ØgetRequest() ØgetResponse() ØgetServletContext()l实现如下接口,由struts框架运行时分别注入相应的Servlet API对象:
ØServletRequestAware ØServletResponseAware ØServletContextAware拦截器
Struts2为一个Action自动注入的各种功能都是通过各种拦截器实施上去的。 在<action>中使用<interceptor-ref>元素引用拦截器或拦截器栈, struts-default.xml文件中查看和了解默认包中的默认拦截器栈的配置。Ø在<package>中使用<interceptors>元素配置<interceptor>或<interceptor-stack>Ø在<package>中使用<default-interceptor-ref >元素为该包中的所有action配置默认拦截器 ,每个包只能指定一个默认拦截器。 一旦为某个action显式指定了某个拦截器,则所属包中定义的默认拦截器将不起作用。 定义一个拦截器:继承 AbstractInterceptor 或者 实现 Interceptor编写一个拦截器如下:
package com.xiaohui.action; import javax.servlet.http.HttpServletRequest; import org.apache.struts2.interceptor.ServletRequestAware; import com.opensymphony.xwork2.Action; public class LoginAction implements ServletRequestAware{ private HttpServletRequest request; public String execute(){ String name = request.getParameter("name"); String password = request.getParameter("password"); if("admin".equals(name) && "12345".equals(password)){ request.getSession().setAttribute("user", name); return Action.SUCCESS; }else{ return "login"; } } @Override public void setServletRequest(HttpServletRequest request) { this.request = request; } }
struts.xml配置如下:<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN" "http://struts.apache.org/dtds/struts-2.3.dtd"> <struts> <constant name="struts.devMode" value="true" /> <package name="default" namespace="" extends="struts-default"> <!-- 配置拦截器栈 --> <interceptors> <interceptor name="login" class="com.xiaohui.interceptor.LoginInterceptor"></interceptor> <interceptor-stack name="myInterceptorStack"> <interceptor-ref name="login"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </interceptor-stack> </interceptors> <global-results> <result name="login" type="redirect"> <param name="location">/login.jsp</param> </result> <result name="success" type="redirect">/index</result> </global-results> <action name="user" class="com.xiaohui.action.UserAction"> <interceptor-ref name="myInterceptorStack"/> </action> <action name="login" class="com.xiaohui.action.LoginAction"> </action> <action name="index"> <result>/WEB-INF/jsps/index.jsp</result> </action> </package> </struts>