结果的处理大致可以分为四种:转发、重定向、转发到Action以及重定向到Action。
这些方式可以在result标签中通过type属性进行配置。
1. 转发
默认的处理方式是转发ServletDispatcherResult
可以在package org.apache.struts2.dispatcher下查看到其源码,其内部doExcute(String finalLocation, ActionInvocation invocation)
方法的核心内容如下
RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation);
if (StringUtils.isNotEmpty(finalLocation) && finalLocation.indexOf("?") > 0) {
String queryString = finalLocation.substring(finalLocation.indexOf("?") + 1);
Map<String, Object> parameters = this.getParameters(invocation);
Map<String, Object> queryParams = this.urlHelper.parseQueryString(queryString, true);
if (queryParams != null && !queryParams.isEmpty()) {
parameters.putAll(queryParams);
}
}
if (dispatcher == null) {
response.sendError(404, "result '" + finalLocation + "' not found");
return;
}
Boolean insideActionTag = (Boolean)ObjectUtils.defaultIfNull(request.getAttribute("struts.actiontag.invocation"), Boolean.FALSE);
if (!insideActionTag.booleanValue() && !response.isCommitted() && request.getAttribute("javax.servlet.include.servlet_path") == null) {
request.setAttribute("struts.view_uri", finalLocation);
request.setAttribute("struts.request_uri", request.getRequestURI());
dispatcher.forward(request, response);
} else {
dispatcher.include(request, response);
}
我们可以看到这里实际上是传入了result标签中给定的URL,这里的finalLocation也就是dispatcher的最终地址。
2.重定向
ServletRedirectResutl同样是在这个包下,其处理过程,也是类似的。
doExecute(String finalLocation, ActionInvocation invocation)
源码如下
protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
ActionContext ctx = invocation.getInvocationContext();
HttpServletRequest request = (HttpServletRequest)ctx.get("com.opensymphony.xwork2.dispatcher.HttpServletRequest");
//通过应用上下文获得response对象
HttpServletResponse response = (HttpServletResponse)ctx.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse");
if (this.isPathUrl(finalLocation)) {
if (!finalLocation.startsWith("/")) {
ActionMapping mapping = this.actionMapper.getMapping(request, Dispatcher.getInstance().getConfigurationManager());
String namespace = null;
if (mapping != null) {
namespace = mapping.getNamespace();
}
if (namespace != null && namespace.length() > 0 && !"/".equals(namespace)) {
//重定向的最终地址
finalLocation = namespace + "/" + finalLocation;
} else {
finalLocation = "/" + finalLocation;
}
}
if (this.prependServletContext && request.getContextPath() != null && request.getContextPath().length() > 0) {
finalLocation = request.getContextPath() + finalLocation;
}
}
这里我们可以看到,它在内部先获取了HttpServletResponse请求,然后再调用了请求的sendRedirect方法。
3.转发到Action
此时在<result/>
标签内,我们配置type属性为chain,在struts-default.xml中,我们可以查看该类型对应的Result类型。
在result标签下,配置如下属性:
<param name="actionName">Action</param>
<param name="namespace"></param>
actionName表示需要被链式调用的Action,namespace表示被转发到的package的命名空间,默认为当前命名空间。除了这两个之外,还有method以及skipAction两个属性。
4.重定向到Action
在<result/>
标签内,我们配置type属性为sendRediction,在struts-default.xml中,我们可以查看该类型对应的Result类型,并找到其全类名,以便于查看源码。这里依然直接看下它的配置
<param name="actionName">Action</param>
<param name="namespace"></param>
actionName表示重定向的目标Action,这里是重定向,并不能够传递参数。
它对应的类是ServletActionRedirectResult,下面大致地看一下它源码的excute()方法
public void execute(ActionInvocation invocation) throws Exception {
this.actionName = this.conditionalParse(this.actionName, invocation);
if (this.namespace == null) {
this.namespace = invocation.getProxy().getNamespace();
} else {
this.namespace = this.conditionalParse(this.namespace, invocation);
}
if (this.method == null) {
this.method = "";
} else {
this.method = this.conditionalParse(this.method, invocation);
}
String tmpLocation = this.actionMapper.getUriFromActionMapping(new ActionMapping(this.actionName, this.namespace, this.method, (Map)null));
this.setLocation(tmpLocation);
//这里它调用了父类的excute方法,那么关键就在于它的父类,它的父类是ServletRedirectResult,因而借助于父类完成了请求的重定向。
super.execute(invocation);
}