WebWork教程-ServletDispatcher
来源:互联网 发布:mysql分类汇总查询语句 编辑:程序博客网 时间:2024/05/16 12:48
ServletDispatcher是默认的处理Web Http请求的调度器,它是一个JavaServlet,是WebWork框架的控制器。所有对Action调用的请求都将通过这个ServletDispatcher调度。它将在web.xml里配置ServletDispatcher时指定,让所有对WebWork 的Action(默认的是.action的后缀)的请求都对应到该调度的JavaServlet中,具体配置在前面的WebWork-helloWorld中有介绍。
ServletDispatcher接受客户端的HTTP请求,将JavaServlet的很多相关对象进行包装,再传给我们的XWork框架,由我们的XWork框架去解析我们的xwork.xml配置文件,根据配置文件的信息,创建对应的Action,组装并调用相应的拦截器,执行Action,返回执行结果。WebWork使用XWork的核心,主要是由这个ServletDispatcher去实现的
具体调用流程:(Servlet调用流程)
一、 init()方法在web服务器启动时调用。
1、初始化Velocity引擎
2、检查是否支持配置文件重新载入功能。如果webwork.configuration.xml.reload(见webwork.properties文件)设置为true,每个request请求都将重新装载xwork.xml配置文件。在开发环境使用将会非常方便,但在生产环境必需设置为false
代码如下:
if ("true".equalsIgnoreCase(Configuration.getString("webwork.configuration.xml.reload"))) {FileManager.setReloadingConfigs(true);}
3、设置一些文件上传的信息,比如:上传临时目录,上传的最大字节等。都设置在webwork.properties文件里,如果在classpath中找不到这个属性文件,它会去读取默认的default.properties
二、 service()方法,每次客户端的请求都将调用此方法
1、 通过request请求取得action的命名空间(namespace,与xwork.xml配置文件里package标签的name对应)
例如:/foo/bar/MyAction.action,取得的命名空间为/foo/bar在xwork.xml配置文件里应该有这一段:<package name="foo.bar" …….
2、 根据servlet请求的Path,解析出要调用该请求的Action的名字(actionName),例如:(../foo/bar/MyAction.action -> MyAction)
在xwork.xml配置文件里应该有:
<package name="foo.bar" …….
<Action name=” MyAction”……]
3、 创建Action上下文(extraContext)。我们前面介绍的ActionContext上下文的对象,就是在这里设置的。它将JavaServlet相关的对象进行包装,放入到extraContext这个Map对象里。
/**
* 将所有的应用请求和servlet属性保存到一个HashMap中,
* @param requestMap 存放所有request请求属性的Map
* @param parameterMap 存放所有request请求参数的Map
* @param sessionMap存放所有session属性的Map
* @param applicationMap 存放所有servlet上下文属性的Map
* @param request HttpServletRequest 对象
* @param response HttpServletResponse 对象.
* @param servletConfig ServletConfig 对象.
* @return代表Action 上下文的一个 HashMap
*/
public static HashMap createContextMap(Map requestMap, Map parameterMap, Map sessionMap, Map applicationMap, HttpServletRequest request, HttpServletResponse response, ServletConfig servletConfig) {
HashMap extraContext = new HashMap();
extraContext.put(ActionContext.PARAMETERS, parameterMap);
extraContext.put(ActionContext.SESSION, sessionMap);
extraContext.put(ActionContext.APPLICATION, applicationMap);
extraContext.put(ActionContext.LOCALE, request.getLocale());
extraContext.put(HTTP_REQUEST, request);
extraContext.put(HTTP_RESPONSE, response);
extraContext.put(SERVLET_CONFIG, servletConfig);
extraContext.put(COMPONENT_MANAGER, request.getAttribute("DefaultComponentManager"));
// helpers to get access to request/session/application scope
extraContext.put("request", requestMap);
extraContext.put("session", sessionMap);
extraContext.put("application", applicationMap);
extraContext.put("parameters", parameterMap);
AttributeMap attrMap = new AttributeMap(extraContext);
extraContext.put("attr", attrMap);
return extraContext;}
下面我们来看看它是如何将request请求的参数和session进行包装的:
Request包装
protected Map getParameterMap(HttpServletRequest request) throws IOException {
return request.getParameterMap();
}
这个方法比较简单,它直接调用了HttpServletRequest的方法getParameterMap(),将所有request请求的参数封装到一个Map中
Session包装
protected Map getSessionMap(HttpServletRequest request) {
return new SessionMap(request);
}
这个方法取得所有Session中的属性,它调用了com.opensymphony.webwork.dispatcher. SessionMap类,这个类实现了Map接口,在entrySet()方法中列举Session的所有属性,存放在Set中。
4、 根据前面获得的namespace、actionName、extraContext,创建一个ActonProxy
ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, actionName, extraContext);
默认的proxy是com.opensymphony.xwork.DefaultActionProxy,在它的构造函数会进行下面的操作:
1)、根据namespace、actionName读取xwork.xml配置文件里这个Action的所有配置信息
2)、创建ActionInvocation
invocation=ActionProxyFactory.getFactory().createActionInvocation(this, extraContext);默认的invocation是com.opensymphony.xwork.DefaultActionInvocation,它的构造函数操作有:
i. 由com.opensymphony.xwork.ObjectFactory创建我们配置文件描述的Action对象。再将这个Action对象存放入OgnlValueStack中。记得我们前面用户注册的例子吗?当用户提交表达时它会有表达式语言向OgnlValueStack取得Action对象的字段,再把输入框的数据设置到对应的Action字段中,这个Action对象就是在这个时候进栈的
ii. 传入extraContext参数,创建与ActionInvocation对应的Action上下文(ActionContext)。记得我们在介绍ActionContext的最后,提出了一个需要注意的地方:不要在Action构造函数中调用ActionContext.getContext()。现在应该能明白,原来是Action对象实例在ActionContext对象实例之前创建的,所有这样取得ActionContext容器对象就有可能会返回null
iii. 取得这个Action对应的所有拦截器(Interceptor),存放入java.util.Iterator对象中。
5、 执行proxy的execute()方法,这个方法最核心的语句是:retCode = invocation.invoke();, invocation对象的invoke()方法它遍历并执行这个Action对应的所有拦截器,执行Action对应的方法(默认的是execute()),根据Action执行返回的值去调用执行相应的Result(返回结果处理)的方法
Action的单元测试
理解了ServletDispatcher,我们就明白了整个框架调用执行的顺序。Action虽然是与Web无关,可是它的创建、参数设置、执行与我们的WebWork、XWork紧密关联在一起,有我们的控制器ServletDispatcher去统一调度,那我们如何去对Action进行独立的单元测试呢?
请看下面的例子:使用单元测试框架JUnit对register.User. RegisterAction做单元测试
见example.register. RegisterActionTest类testExecuteWithProxyFactory()方法
public void testExecuteWithProxyFactory() throws Exception{
//创建action上下文(actionContext)
Map params = new HashMap();
params.put("user.username","Moxie");
params.put("user.password","mypassword");
params.put("user.email","achqian@yahoo.com.cn");
params.put("user.age",new Integer(23));
Map extraContext = new HashMap();
extraContext.put(ActionContext.PARAMETERS,params);
//创建代理(找出所在的action)
ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy("example", "register", extraContext);
//不要执行出现Success后的代码
proxy.setExecuteResult(false);
//测试代码是否正确
assertEquals(proxy.execute(),"success");
//返回Action,测试action里面的代码是否正确
RegisterAction action = (RegisterAction) proxy.getAction();
assertEquals(action.getUser().getUsername(),"Moxie");
assertEquals(action.getUser().getAge(),23);
}
下面解说这个方法:
1、 对象params表示请求参数的Map,在它里面设置了注册用户的信息。extraContext当然就是我们ActionContext上下文的容器,它里面保存了放置请求参数的对象params
2、 创建我们的ActionProxy,它传入的参数有:“example”-这个Action的命名空间,“register”-Action对应的名字,extraContext-存放Actin上下文里的对象,,执行并将它返回的值与“success”比较,测试Action是否能正确执行完成。注意:proxy.setExecuteResult(false);,因为我们是单元测试,所以Action执行完成就可以了,不用再去调用结果响应的操作,故将是否执行结果设置为“false”。
3、 Action正确执行完成之后,我们也可以测试现在Action的字段里的数据是否按照我们预期的要求正确设置。从ActionProxy对象里取得执行的Action,即RegisterAction对象,再取得它的User模型,将其数据与前面设置参数的数据进行比较,判断它是否等于我们预期设置的数值。
Result Type
前面我们学习了ServletDispatcher,它是WebWork框架机制的核心。它和Action在我们MVC模式中,扮演着控制器的角色,MVC模式通过控制器实现了我们模型和视图的分离。WebWork提供了多种活灵活视图展现方式。
我们先看看前面用户注册例子的展现方式:我们使用的是Jsp和WebWork自带的标签库,Action对应的视图当然是在xwork.xml配置文件里设置:
<action name="register" class="example.register.RegisterAction" >
<result name="success" type="dispatcher">
<param name="location">register-result.jsp</param>
</result>
<interceptor-ref name="params"/>
</action>
Result是Action执行完返回的一个字符串常量,它表示Action执行完成的状态,比如:执行成功、执行失败等。在我们前面Action的介绍中,详细介绍了它默认的标准Result,当然Result我们也可以自己定义,只要是一个字符串常量就可以了。
Result的值在xwork.xml配置文件里就是result标签里“name”的值,name="success"表示Action执行成功,返回“success”就对应此标签的配置,进行视图输出:
“type”就是我们的Result Type,Result Type是一个类,它在Action执行完成并返回Result之后,决定采用哪一种视图技术,将执行结果展现给用户。我们输出的类型是
type="dispatcher",它对应com.opensymphony.webwork.dispatcher.ServletDispatcherResult这个类,它将执行结果通过javax.servlet.RequestDispatcher的forward()或include()方法调度到Jsp页面展现。
我们可以自己开发Result Type,实现我们需要的视图展现方式。Result Type必需要实现com.opensymphony.xwork..Result接口。在WebWork中,它已经为我们提供了很多Result Type,实现了视图部分对JSP, Velocity, FreeMarker, JasperReports,XML等的支持,具体如下表格:
Result Type | Nname | Class |
Dispatcher | dispatcher | com.opensymphony.webwork.dispatcher.ServletDispatcherResult |
Redirect | Redirect | com.opensymphony.webwork.dispatcher.ServletRedirectResult |
Action Chaining | Chain | com.opensymphony.xwork.ActionChainResult |
Velocity | Velocity | com.opensymphony.webwork.dispatcher.VelocityResult |
FreeMarker | freemarker | com.opensymphony.webwork.views.freemarker.FreemarkerResult |
JasperReports | Jasper | com.opensymphony.webwork.views.jasperreports.JasperReportsResult |
XML/XSL | Xslt | com.opensymphony.webwork.views.xslt.XSLTResult |
HttpHeader | com.opensymphony.webwork.dispatcher.HttpHeaderResult |
Dispatcher:通过javax.servlet.RequestDispatcher的forward()或include()方法调度到页面展现,这样的页面一般是Jsp页面。
参数(Parameters) | 是否必需 | 描 述 |
location | 是 | 执行完成之后转向的位置 |
parse | 否 | 默认的是“true”,如果设置为“false”,location参数将不会被OGNL表达式语言解析 |
例子:
<result name="success" type="dispatcher">
<param name="location">register-result.jsp</param>
</result>
也可以简单写成这样:
<result name="success" type="dispatcher">register-result.jsp</result>
Action Chaining:一种特殊的视图结果,将Action执行完之后链接到另一个Action中继续执行。新的Action使用上一个Action的上下文(ActionContext)。
参数(Parameters) | 是否必需 | 描 述 |
actionName | 是 | 将要被链接的Action名字 |
namespace | 否 | 被链接的Action的命名空间(namespace),如果不设置,默认的即是当前的命名空间 |
例子:
<result name="success" type="chain">
<param name="actionName">bar</param>
<param name="namespace">/foo</param>
</result>
将要调用的Action如下:
<action name="bar" class="myPackage.barAction">
...
</action>
Velocity:它类似Jsp的执行环境(使用JavaServlet容器),将Velocity模板转化成数据流的形式,直接通过JavaServlet输出。
参数(Parameters) | 是否必需 | 描 述 |
location | 是 | 执行完成之后转向的位置(一般是.vm页面) |
parse | 否 | 默认的是“true”,如果设置为“false”,location参数将不会被OGNL表达式语言解析 |
例子:
<result name="success" type="velocity">
<param name="location">foo.vm</param>
</result>
FreeMarker:FreeMarker是一个纯Java模板引擎;一个普通的基于模板生成文本的工具,它只能应用在Web应用环境中。
参数(Parameters) | 是否必需 | 描 述 |
location | 是 | 执行完成之后转向的位置 |
parse | 否 | 默认的是“true”,如果设置为“false”,location参数将不会被OGNL表达式语言解析 |
contentType | 否 | 如果不指定,默认的是"text/html" |
例子:
<result name="success" type="freemarker">foo.ftl</result>
JasperReports:将Action执行的结果通过JasperReports报表形式输出,可以指定JasperReports支持的输出格式(PDF、HTML、XLS、CSV、XML等),默认是通过PDF格式输出。
参数(Parameters) | 是否必需 | 描 述 |
location | 是 | 执行完成之后转向的位置 |
parse | 否 | 默认的是“true”,如果设置为“false”,location参数将不会被OGNL表达式语言解析 |
dataSource | 是 | 它是Action的一个字段(通常是一个List),OGNL表达式被用来去value stack(OgnlValueStack)重新找回这个dataSource |
format | 否 | 报表生成的数据格式,默认的是pdf |
例子:
<result name="success" type="jasper">
<param name="location">foo.jasper</param>
<param name="dataSource">mySource</param>
<param name="format">CSV</param>
</result>
或者默认的pdf格式
<result name="success" type="jasper">
<param name="location">foo.jasper</param>
<param name="dataSource">mySource</param>
</result>
XML/XSL:将结果转换为xml输出
参数(Parameters) | 是否必需 | 描 述 |
location | 是 | 执行完成之后转向的位置 |
parse | 否 | 默认的是“true”,如果设置为“false”,location参数将不会被OGNL表达式语言解析 |
例子:
<result name="success" type="xslt">foo.xslt</result>
- WebWork教程-ServletDispatcher
- WebWork教程-ServletDispatcher
- WebWork教程-ServletDispatcher
- WebWork教程-验证框架
- WebWork教程-验证框架
- WebWork教程1
- webwork 教程2
- webwork教程 3
- WebWork教程2 -配置WebWork应用程序
- WebWork教程-表达式与言EL和OGNL
- WebWork教程-表达式与言EL和OGNL
- 最新WebWork教程0.90版
- WebWork教程- Interceptor(拦截器)
- WebWork教程- Interceptor(拦截器)
- WebWork教程- Interceptor(拦截器)
- WebWork教程- Interceptor(拦截器)
- WebWork
- WebWork
- WebWork2教程(中文版)(4.1.1)
- 在WebWork中使用Velocity
- Interceptors 简介
- WebWork教程-验证框架
- WebWork教程-表达式与言EL和OGNL
- WebWork教程-ServletDispatcher
- WebWork教程- Interceptor(拦截器)
- WebWork介绍-Action篇
- WebWork-ActionContext(Action上下文)
- 很好的JAVA群,欢迎大家加入!
- wxWidgets初识
- objdump与readelf的区别
- 最近阅读 C++代码的感想
- MS08-067 漏洞打击了盗版用户的信心