Struts2 动态方法调用
动态方法调用就是为了解决一个Action对应多个请求的处理,以免Action太多.
1.指定method属性
2.感叹号方式
3.通配符方式
Demo结构图
web.xml标准配置
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- 配置Struts2 过滤器 --> <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> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
HelloWorldAction.java
package com.struts2.action; import com.opensymphony.xwork2.ActionSupport; public class HelloWorldAction extends ActionSupport{ private static final long serialVersionUID = 1L; private static final String SUCCESS = "success"; private static final String Add = "add"; private static final String UPDATE = "update"; public String add(){ System.out.println("执行add方法"); return Add; } public String update(){ System.out.println("执行update方法"); return UPDATE; } @Override public String execute() throws Exception { System.out.println("执行Action"); return SUCCESS; } }
<?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.enable.DynamicMethodInvocation" value="false" /> <!-- 把它设置为开发模式,发布时要设置为false --> <constant name="struts.devMode" value="true" /> <package name="default" namespace="/" extends="struts-default"> <action name="helloWorld" class="com.struts2.action.HelloWorldAction"> <result name="success">/result.jsp</result> </action> <action name="helloWorldAdd" class="com.struts2.action.HelloWorldAction" method="add"> <result name="add">/add.jsp</result> </action> <action name="helloWorldUpdate" class="com.struts2.action.HelloWorldAction" method="update"> <result name="update">/update.jsp</result> </action> </package> </struts>
<%@ 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> </head> <body> <a href="helloWorld.action">helloWorld</a><br> <a href="helloWorldAdd.action">addAction</a><br> <a href="helloWorldUpdate.action">updateAction</a><br> </body> </html>
然后就可以部署发布了...
------------------------------------------------华丽丽的分割线------------------------------------------------
好了,然后来说 感叹号方式动态调用
struts2 官方并不推荐使用,但是了解一下 还是需要的....
使用感叹号动态调用需要在struts.xml配置文件中,添加一个配置参数
<!-- 是否支持动态调用 (使用感叹号来调用) --> <constant name="struts.enable.DynamicMethodInvocation" value="true" /> 该属性设置Struts2是否支持动态方法调用,该属性的默认值是true,如果需要关闭动态方法调用,则可设置该属性为false。使用这个设置后可以这样调用:action!method
只要修改struts.xml配置文件就好了...
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.enable.DynamicMethodInvocation" value="true" /> <!-- 把它设置为开发模式,发布时要设置为false --> <constant name="struts.devMode" value="true" /> <package name="default" namespace="/" extends="struts-default"> <action name="helloWorld" class="com.struts2.action.HelloWorldAction"> <result name="success">/result.jsp</result> <result name="add">/add.jsp</result> <result name="update">/update.jsp</result> </action> </package> </struts>注意看 这个struts.xml 和 上面一个使用method 的 struts.xml 有什么不同哦.....
index.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> </head> <body> <a href="helloWorld!add.action">动态调用方法Add</a><br> <a href="helloWorld!update.action">动态调用方法Update</a><br> </body> </html>
仔细看url链接地址....
OK.....
------------------------------------------------华丽丽的分割线------------------------------------------------
接下来是使用通配符进行动态跳转
别忘记了,将 <constant name="struts.enable.DynamicMethodInvocation" value="true" /> 中的 true,改为false
主要也是修改.. 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.enable.DynamicMethodInvocation" value="false" /> <!-- 把它设置为开发模式,发布时要设置为false --> <constant name="struts.devMode" value="true" /> <package name="default" namespace="/" extends="struts-default"> <!-- 使用通配符来调用 name="helloWorld_*",中的"_" 是用来分隔的,"*"就是对应后面的 method中的"{1}" 如果 name="helloWorld_*_*" ,那么 method="{1}{2}" --> <action name="helloWorld_*" method="{1}" class="com.struts2.action.HelloWorldAction"> <!--<action name="helloWorld" class="com.struts2.action.HelloWorldAction">--> <result name="success">/result.jsp</result> <result name="add">/{1}.jsp</result> <result name="update">/{1}.jsp</result> </action> </package> </struts>
<%@ 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> </head> <body> <a href="helloWorld_add.action">通配符add</a><br> <a href="helloWorld_update.action">通配符Update</a><br> </body> </html>
------------------------------------------------华丽丽的分割线------------------------------------------------
OK....三种调用方式都结束了......
Struts2 的工作原理
先来看下这张经典的Struts2流程图
Struts2 工作原理 Struts2 在web.xml文件中进行配置过滤器(org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter); 配置过滤器之后,当WEB项目启动之后,过滤器就会生效. 注:旧版本用的是FilterDispatcher过滤器 , 新版本用的StrutsPrepareAndExecuteFilter过滤器 用户通过HttpServletReuqest(用户请求)发送过来,经过一些核心过滤器(比如:FilterDispatcher过滤器); 然后到达ActionMapper,比如你在struts2.xml 配置文件中拦截的是".action"后缀的请求,那么,只有".action"后缀的请求,才会到ActionMapper,然后根据请求参数 去查找,ActionMapper中,有没有指定的action; 如果ActionMapper确定需要调用某个action,FilterDispatcher过滤器,会将控制权交给ActionProxy; ActionProxy会读取struts.xml配置文件,找到具体需要调用的action类; 然后通过ActionProxy代理创建一个ActionInvoaction的实例; 然后再经过一系列的其他拦截器之后,再到Action,执行相关的代码; 然后返回result,也就是一个字符串对象,字符串对象,对应的也就是一个视图(jsp); 然后再经过一系列的其他拦截器,将数据视图打包,通过HttpServletResponse,将数据返回给用户,最后呈现出来.可能叙述的不是很清楚,可以 参考这篇博文: http://blog.csdn.net/csh624366188/article/details/7490638
Struts核心文件:
Struts2核心文件 web.xml : 任何MVC框架都需要和Web应用整合,这就不得不借助于web.xml文件,只有配置在web.xml文件中,Servlet才会被应用加载. 通常,所有的MVC框架都需要Web应用加载一个核心控制器,对于Struts2框架而言,需要加载StrutsPrepareAndExecuteFilter,只要Web应用负责加载StrutsPrepareAndExecuteFilter, StrutsPrepareAndExecuteFilter就会加载Struts2框架. struts.xml(核心配置文件) struts.xml是Strus2的核心配置文件,在开发过程中利用率最高. 该文件主要负责管理应用中的Action映射,以及该Action包含的Result定义等. struts.xml中包含的内容: 1.全局属性 2.用户请求 和 响应Action之间的对应关系 3.Action可能用到的参数和返回结果 4.各种拦截器配置. struts.properties struts2框架的全局属性文件,自动加载.(可有可无)
Struts2 Action搜索顺序 url : http://localhost:8088/Struts2Demo/path1/path2/path3/helloWorld.action 1.判断package是否存在,如 : /path1/path2/path3/ (就是判断package/命名空间是否存在) 存在: 2.判断action是否存在: 如果存在,就去对应的package下,寻找是否有对应的action; 如果有那就直接去执行了; 如果没有直接报错; 如果不存在,则去默认namespace的package里面寻找action 不存在: 2.检查上一级路径的package是否存在(直到默认namespace),重复第一步
在Struts.xml中有一些配置参数解释下:
<constant name="struts.enable.DynamicMethodInvocation" value="false" /> 该属性设置Struts2是否支持动态方法调用,该属性的默认值是true,如果需要关闭动态方法调用,则可设置该属性为false。 使用这个设置后可以这样调用:action!method (动态方法调用)具体: http://blog.csdn.net/itmyhome1990/article/details/9265909 <constant name="struts.devMode" value="true" /> 把它设置为开发模式,发布时要设置为false true时,表示为 开发模式 ,开发模式下使用,这样可以打印出更详细的错误信息 <include file="struts_xml/*.xml" />(uboss中的例子:struts_xml文件夹下所有 .xml结尾的配置文件) 引入其他的Struts2文件,便于分类管理
------------------------------------------------华丽丽的分割线------------------------------------------------
如果项目中action配置太多,需要创建好多个struts.xml, 那么该如何引用?
结构是这样子的.....
struts.xml 下面 引用 其他模块的 struts.xml配置文件....
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> <include file="struts_xml/*.xml"></include> <!-- 是否支持动态调用 (使用感叹号来调用) --> <constant name="struts.enable.DynamicMethodInvocation" value="false" /> <!-- 把它设置为开发模式,发布时要设置为false --> <constant name="struts.devMode" value="true" /> </struts>
<?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"> <!-- 使用通配符来调用 name="helloWorld_*",中的"_" 是用来分隔的,"*"就是对应后面的 method中的"{1}" 如果 name="helloWorld_*_*" ,那么 method="{1}{2}" --> <action name="helloWorld_*" method="{1}" class="com.struts2.action.HelloWorldAction"> <!--<action name="helloWorld" class="com.struts2.action.HelloWorldAction">--> <result name="success">/result.jsp</result> <!-- <result name="add">/add.jsp</result> <result name="update">/update.jsp</result> --> <result name="add">/{1}.jsp</result> <result name="update">/{1}.jsp</result> </action> <!-- <action name="helloWorldAdd" class="com.struts2.action.HelloWorldAction" method="add"> <result name="add">/add.jsp</result> </action> <action name="helloWorldUpdate" class="com.struts2.action.HelloWorldAction" method="update"> <result name="update">/update.jsp</result> </action> --> </package> </struts>
配置默认action方法以后,如果有人输入了错误的URL以后,会统一跳转一个地址,不会出现500 等用户体验不好的错误.
<!--
默认action方法
-->
<default-action-ref name="index"></default-action-ref>
<action name="index">
<result>/error.jsp</result>
</action>