这里的nextRequestResponse是指RequestHandler中doRequest()函数在最后使用的一个变量,doRequest()会依据nextRequestResponse返回不同的响应给请求者。nextRequestResponse有多种不同的类型,不同的类型处理方式也不一样。

第一种类型是request,表明这是一个请求链,递归调用doRequest()处理下一个请求:

// <request-map uri="main">
// <response name="success" type="request" value="other"/>
// </request-map> if ("request".equals(nextRequestResponse.type)) {
// chained request
doRequest(request, response, nextRequestResponse.value, userLogin, delegator);
}

处理nextRequestResponse时,除了request类型,其它类型都需要执行Postprocessor。Postprocessor不会终止请求过程,如果返回的结果不是success,则以抛出异常的方式处理:

for (ConfigXMLReader.Event event: controllerConfig.getPostprocessorEventList().values()) {
try {
String returnString = this.runEvent(request, response, event, requestMap, "postprocessor");
if (returnString != null && !returnString.equalsIgnoreCase("success")) {
throw new EventHandlerException("Post-Processor event did not return 'success'.");
}
} catch (EventHandlerException e) {
Debug.logError(e, module);
}
}

第二种类型是url,表明这是一个URL重定向:

// <request-map uri="main">
// <response name="success" type="url" value="http://www.baidu.com"/>
// </request-map> if ("url".equals(nextRequestResponse.type)) {
if (Debug.verboseOn())
Debug.logVerbose("[RequestHandler.doRequest]: Response is a URL redirect.", module);
callRedirect(nextRequestResponse.value, response, request);
}

callRedirect()做了两件事,一是将request中可序列化的对象保存到session(这样处理的原因是什么?),二是调用response的sendResponse()执行重定向:

private void callRedirect(String url, HttpServletResponse resp, HttpServletRequest req) throws RequestHandlerException {
if (Debug.infoOn()) Debug.logInfo("Sending redirect to: [" + url + "], sessionId=" + UtilHttp.getSessionId(req), module); // set the attributes in the session so we can access it.
// 将request中可序列化的属性保存到session
Enumeration<String> attributeNameEnum = UtilGenerics.cast(req.getAttributeNames());
Map<String, Object> reqAttrMap = FastMap.newInstance();
while (attributeNameEnum.hasMoreElements()) {
String name = attributeNameEnum.nextElement();
Object obj = req.getAttribute(name);
if (obj instanceof Serializable) {
reqAttrMap.put(name, obj);
}
}
if (reqAttrMap.size() > 0) {
// RequestHandler is not serializable and must be removed first.
reqAttrMap.remove("_REQUEST_HANDLER_");
byte[] reqAttrMapBytes = UtilObject.getBytes(reqAttrMap);
if (reqAttrMapBytes != null) {
req.getSession().setAttribute("_REQ_ATTR_MAP_", StringUtil.toHexString(reqAttrMapBytes));
}
} // send the redirect
// 响应重定向
try {
resp.sendRedirect(url);
} catch (IOException ioe) {
throw new RequestHandlerException(ioe.getMessage(), ioe);
} catch (IllegalStateException ise) {
throw new RequestHandlerException(ise.getMessage(), ise);
}
}

第三种类型是cross-request,表明这是一个跨应用(Cross Application)重定向。什么是跨应用重定向?例如,如果当前请求的是http://localhost:8080/practice/control/main,跨应用重定向后的地址就是http://localhost:8080/other。这里的practice就是一个应用,other是另外一个应用。

// <request-map uri="main">
// <response name="success" type="cross-request" value="other"/>
// </request-map> if ("cross-redirect".equals(nextRequestResponse.type)) {
if (Debug.verboseOn())
Debug.logVerbose("[RequestHandler.doRequest]: Response is a Cross-Application redirect.", module);
String url = nextRequestResponse.value.startsWith("/") ? nextRequestResponse.value : "/" + nextRequestResponse.value;
callRedirect(url + this.makeQueryString(request, nextRequestResponse), response, request);
}

makeQueryString()处理重定向后的请求参数。请求参数有两个来源,一是当前request对象的QueryString,二是nextRequestResponse的redirect-parameter。

public String makeQueryString(HttpServletRequest request, ConfigXMLReader.RequestResponse requestResponse) {
if (requestResponse == null ||
(requestResponse.redirectParameterMap.size() == 0 && requestResponse.redirectParameterValueMap.size() == 0)) {
Map<String, Object> urlParams = UtilHttp.getUrlOnlyParameterMap(request);
String queryString = UtilHttp.urlEncodeArgs(urlParams, false);
if(UtilValidate.isEmpty(queryString)) {
return queryString;
}
return "?" + queryString;
} else {
// redirect-parameter可以使用value指定具体的参数值, 也可以使用from指定参数值的来源。例如:
// <request-map uri="main">
// <response name="success" type="cross-request" value="other">
// <request-parameter name="foo" value="xxx"/>
// <request-parameter name="bar" from="jsessionid"/>
// </response>
// </request-map> StringBuilder queryString = new StringBuilder();
queryString.append("?");
for (Map.Entry<String, String> entry: requestResponse.redirectParameterMap.entrySet()) {
String name = entry.getKey();
String from = entry.getValue(); Object value = request.getAttribute(from);
if (value == null) {
value = request.getParameter(from);
} addNameValuePairToQueryString(queryString, name, (String) value);
}
for (Map.Entry<String, String> entry: requestResponse.redirectParameterValueMap.entrySet()) {
String name = entry.getKey();
String value = entry.getValue(); addNameValuePairToQueryString(queryString, name, (String) value);
}
return queryString.toString();
}
}

第四种类型是request-redirect,表明这是一个请求重定向。什么是请求重定向?例如,如果当前请求的是http://localhost:8080/practice/control/main,请求重定向后的地址就是http://localhost:8080/practice/control/other,都是在同一个应用practice里面。

// <request-map uri="main">
// <response name="success" type="request-request" value="other"/>
// </request-map> if ("request-redirect".equals(nextRequestResponse.type)) {
if (Debug.verboseOn())
Debug.logVerbose("[RequestHandler.doRequest]: Response is a Request redirect.", module);
callRedirect(makeLinkWithQueryString(request, response, "/" + nextRequestResponse.value, nextRequestResponse), response, request);
}

makeLinkWithQueryString()是在makeQueryString()基础上增加了makeLink()的调用:

public String makeLinkWithQueryString(HttpServletRequest request, HttpServletResponse response, String url, ConfigXMLReader.RequestResponse requestResponse) {
String initialLink = this.makeLink(request, response, url);
String queryString = this.makeQueryString(request, requestResponse);
return initialLink + queryString;
} public String makeLink(HttpServletRequest request, HttpServletResponse response, String url) {
return makeLink(request, response, url, false, false, true);
} public String makeLink(HttpServletRequest request, HttpServletResponse response, String url, boolean fullPath, boolean secure, boolean encode) {
Delegator delegator = (Delegator) request.getAttribute("delegator");
String webSiteId = WebSiteWorker.getWebSiteId(request); String httpsPort = null;
String httpsServer = null;
String httpPort = null;
String httpServer = null;
Boolean enableHttps = null; // load the properties from the website entity
GenericValue webSite;
if (webSiteId != null) {
try {
webSite = delegator.findByPrimaryKeyCache("WebSite", UtilMisc.toMap("webSiteId", webSiteId));
if (webSite != null) {
httpsPort = webSite.getString("httpsPort");
httpsServer = webSite.getString("httpsHost");
httpPort = webSite.getString("httpPort");
httpServer = webSite.getString("httpHost");
enableHttps = webSite.getBoolean("enableHttps");
}
} catch (GenericEntityException e) {
Debug.logWarning(e, "Problems with WebSite entity; using global defaults", module);
}
} // fill in any missing properties with fields from the global file
if (UtilValidate.isEmpty(httpsPort)) {
httpsPort = UtilProperties.getPropertyValue("url.properties", "port.https", "443");
}
if (UtilValidate.isEmpty(httpsServer)) {
httpsServer = UtilProperties.getPropertyValue("url.properties", "force.https.host");
}
if (UtilValidate.isEmpty(httpPort)) {
httpPort = UtilProperties.getPropertyValue("url.properties", "port.http", "80");
}
if (UtilValidate.isEmpty(httpServer)) {
httpServer = UtilProperties.getPropertyValue("url.properties", "force.http.host");
}
if (enableHttps == null) {
enableHttps = UtilProperties.propertyValueEqualsIgnoreCase("url.properties", "port.https.enabled", "Y");
} // create the path the the control servlet
String controlPath = (String) request.getAttribute("_CONTROL_PATH_"); String requestUri = RequestHandler.getRequestUri(url);
ConfigXMLReader.RequestMap requestMap = null;
if (requestUri != null) {
requestMap = getControllerConfig().getRequestMapMap().get(requestUri);
} StringBuilder newURL = new StringBuilder(); boolean didFullSecure = false;
boolean didFullStandard = false;
if (requestMap != null && (enableHttps || fullPath || secure)) {
if (Debug.verboseOn()) Debug.logVerbose("In makeLink requestUri=" + requestUri, module);
if (secure || (enableHttps && requestMap.securityHttps && !request.isSecure())) {
String server = httpsServer;
if (UtilValidate.isEmpty(server)) {
server = request.getServerName();
} newURL.append("https://");
newURL.append(server);
if (!httpsPort.equals("443")) {
newURL.append(":").append(httpsPort);
} didFullSecure = true;
} else if (fullPath || (enableHttps && !requestMap.securityHttps && request.isSecure())) {
String server = httpServer;
if (UtilValidate.isEmpty(server)) {
server = request.getServerName();
} newURL.append("http://");
newURL.append(server);
if (!httpPort.equals("80")) {
newURL.append(":").append(httpPort);
} didFullStandard = true;
}
} newURL.append(controlPath); // now add the actual passed url, but if it doesn't start with a / add one first
if (!url.startsWith("/")) {
newURL.append("/");
}
newURL.append(url); String encodedUrl;
if (encode) {
boolean forceManualJsessionid = "false".equals(getServletContext().getInitParameter("cookies")) ? true : false;
boolean isSpider = false; // if the current request comes from a spider, we will not add the jsessionid to the link
if (UtilHttp.checkURLforSpiders(request)) {
isSpider = true;
} // if this isn't a secure page, but we made a secure URL, make sure we manually add the jsessionid since the response.encodeURL won't do that
if (!request.isSecure() && didFullSecure) {
forceManualJsessionid = true;
} // if this is a secure page, but we made a standard URL, make sure we manually add the jsessionid since the response.encodeURL won't do that
if (request.isSecure() && didFullStandard) {
forceManualJsessionid = true;
} if (response != null && !forceManualJsessionid && !isSpider) {
encodedUrl = response.encodeURL(newURL.toString());
} else {
if (!isSpider) {
String sessionId = ";jsessionid=" + request.getSession().getId();
// this should be inserted just after the "?" for the parameters, if there is one, or at the end of the string
int questionIndex = newURL.indexOf("?");
if (questionIndex == -1) {
newURL.append(sessionId);
} else {
newURL.insert(questionIndex, sessionId);
}
}
if (response != null) {
encodedUrl = response.encodeURL(newURL.toString());
} else {
encodedUrl = newURL.toString();
}
}
} else {
encodedUrl = newURL.toString();
}
//if (encodedUrl.indexOf("null") > 0) {
//Debug.logError("in makeLink, controlPath:" + controlPath + " url:" + url, "");
//throw new RuntimeException("in makeLink, controlPath:" + controlPath + " url:" + url);
//} //Debug.logInfo("Making URL, encode=" + encode + " for URL: " + newURL + "\n encodedUrl: " + encodedUrl, module); return encodedUrl;
}

第五种类型是request-redirect-noparam,表明这也是一个请求重定向,类似request-redirect,但是不需要带上参数。参数可能是当前请求的QueryString,也有可能是redirect-parameter。

// <request-map uri="main">
// <response name="success" type="request-request-noparam" value="other"/>
// </request-map> if ("request-redirect-noparam".equals(nextRequestResponse.type)) {
if (Debug.verboseOn())
Debug.logVerbose("[RequestHandler.doRequest]: Response is a Request redirect with no parameters.", module);
callRedirect(makeLink(request, response, nextRequestResponse.value), response, request);
}

第六种类型是view,表明这是一个视图。视图需要在controller.xml中用view-map定义。

// <request-map uri="main">
// <response name="success" type="view" value="main"/>
// </request-map> if ("view".equals(nextRequestResponse.type)) {
if (Debug.verboseOn())
Debug.logVerbose("[RequestHandler.doRequest]: Response is a view.", module); // check for an override view, only used if "success" = eventReturn
String viewName = (UtilValidate.isNotEmpty(overrideViewUri) && (eventReturn == null || "success".equals(eventReturn))) ? overrideViewUri : nextRequestResponse.value;
renderView(viewName, requestMap.securityExternalView, request, response, saveName);
}

第七种类型是view-last。

// <request-map uri="main">
// <response name="success" type="view-last" value="news"/>
// </request-map> if ("view-last".equals(nextRequestResponse.type)) {
if (Debug.verboseOn())
Debug.logVerbose("[RequestHandler.doRequest]: Response is a view.", module); // check for an override view, only used if "success" = eventReturn
String viewName = (UtilValidate.isNotEmpty(overrideViewUri) && (eventReturn == null || "success".equals(eventReturn))) ? overrideViewUri : nextRequestResponse.value; // as a further override, look for the _SAVED and then _HOME and then _LAST session attributes
Map<String, Object> urlParams = null;
if (session.getAttribute("_SAVED_VIEW_NAME_") != null) {
viewName = (String) session.getAttribute("_SAVED_VIEW_NAME_");
urlParams = UtilGenerics.<String, Object>checkMap(session.getAttribute("_SAVED_VIEW_PARAMS_"));
} else if (session.getAttribute("_HOME_VIEW_NAME_") != null) {
viewName = (String) session.getAttribute("_HOME_VIEW_NAME_");
urlParams = UtilGenerics.<String, Object>checkMap(session.getAttribute("_HOME_VIEW_PARAMS_"));
} else if (session.getAttribute("_LAST_VIEW_NAME_") != null) {
viewName = (String) session.getAttribute("_LAST_VIEW_NAME_");
urlParams = UtilGenerics.<String, Object>checkMap(session.getAttribute("_LAST_VIEW_PARAMS_"));
} else if (UtilValidate.isNotEmpty(nextRequestResponse.value)) {
viewName = nextRequestResponse.value;
}
if (urlParams != null) {
for (Map.Entry<String, Object> urlParamEntry: urlParams.entrySet()) {
String key = urlParamEntry.getKey();
// Don't overwrite messages coming from the current event
if (!("_EVENT_MESSAGE_".equals(key) || "_ERROR_MESSAGE_".equals(key)
|| "_EVENT_MESSAGE_LIST_".equals(key) || "_ERROR_MESSAGE_LIST_".equals(key))) {
request.setAttribute(key, urlParamEntry.getValue());
}
}
}
renderView(viewName, requestMap.securityExternalView, request, response, null);
}

第八种类型是view-last-noparam。

// <request-map uri="main">
// <response name="success" type="view-last-noparam" value="news"/>
// </request-map> if ("view-last-noparam".equals(nextRequestResponse.type)) {
if (Debug.verboseOn())
Debug.logVerbose("[RequestHandler.doRequest]: Response is a view.", module); // check for an override view, only used if "success" = eventReturn
String viewName = (UtilValidate.isNotEmpty(overrideViewUri) && (eventReturn == null || "success".equals(eventReturn))) ? overrideViewUri : nextRequestResponse.value; // as a further override, look for the _SAVED and then _HOME and then _LAST session attributes
if (session.getAttribute("_SAVED_VIEW_NAME_") != null) {
viewName = (String) session.getAttribute("_SAVED_VIEW_NAME_");
} else if (session.getAttribute("_HOME_VIEW_NAME_") != null) {
viewName = (String) session.getAttribute("_HOME_VIEW_NAME_");
} else if (session.getAttribute("_LAST_VIEW_NAME_") != null) {
viewName = (String) session.getAttribute("_LAST_VIEW_NAME_");
} else if (UtilValidate.isNotEmpty(nextRequestResponse.value)) {
viewName = nextRequestResponse.value;
}
renderView(viewName, requestMap.securityExternalView, request, response, null);
}

第九种类型是view-home。

// <request-map uri="main">
// <response name="success" type="view-home" value="news"/>
// </request-map> if ("view-home".equals(nextRequestResponse.type)) {
if (Debug.verboseOn())
Debug.logVerbose("[RequestHandler.doRequest]: Response is a view.", module); // check for an override view, only used if "success" = eventReturn
String viewName = (UtilValidate.isNotEmpty(overrideViewUri) && (eventReturn == null || "success".equals(eventReturn))) ? overrideViewUri : nextRequestResponse.value; // as a further override, look for the _HOME session attributes
Map<String, Object> urlParams = null;
if (session.getAttribute("_HOME_VIEW_NAME_") != null) {
viewName = (String) session.getAttribute("_HOME_VIEW_NAME_");
urlParams = UtilGenerics.<String, Object>checkMap(session.getAttribute("_HOME_VIEW_PARAMS_"));
}
if (urlParams != null) {
for (Map.Entry<String, Object> urlParamEntry: urlParams.entrySet()) {
request.setAttribute(urlParamEntry.getKey(), urlParamEntry.getValue());
}
}
renderView(viewName, requestMap.securityExternalView, request, response, null);
}

第十种类型是none,表明不返回任何响应内容。

// <request-map uri="main">
// <response name="success" type="none"/>
// </request-map> if ("none".equals(nextRequestResponse.type)) {
// no view to render (meaning the return was processed by the event)
if (Debug.verboseOn())
Debug.logVerbose("[RequestHandler.doRequest]: Response is handled by the event.", module);
}

OFBiz:处理nextRequestResponse的更多相关文章

  1. OFBiz:解析doRequest()

    这里的doRequest()是指RequestHandler中的同名函数: public void doRequest(HttpServletRequest request, HttpServletR ...

  2. ofbiz 代码日记

    写代码一定要尽善尽美.. //修改方法 //条件查询 用于修改 List<GenericValue> stoList = delegator.findByAnd("YcrossS ...

  3. ofbiz 本地化及邮件设置126邮箱

    ofibz登陆功能有通过电子邮件找会密码的功能,但找回密码功能需要配置一个发送email的邮箱账号和smtp服务器的配置,具体配置如下: 1:在ofbiz数据库的表product_store_emai ...

  4. Apache OFBiz 研究记录01

    作为Apache 的顶级项目: Apache OFBiz,功能十分强大,一般开发者很难用到全部功能. 这次笔者的研究主要集中在电子商务平台这一块,一步一步解构. OFBiz下载地址:http://of ...

  5. OFBIZ:启动之ContainerLoader

    ContainerLoader类实现StartupLoader接口,目的是装入各种Container容器. /** * An OFBiz container. A container can be t ...

  6. OFBIZ:启动之StartupLoader

    任意一个JAVA程序都是从main()开始启动的,OFBIZ也不例外.OFBIZ的main()位于framework/start/src/org/ofbiz/base/start/Start.java ...

  7. ofbiz的部署及安装问题解决办法

    ofbiz是apache下的顶级开源项目之一,非常强大说下正常流程及解决办法. 开发环境:本人开发环境是win7系统 准备: 1.如果使用的是git,从https://github.com/apach ...

  8. ofbiz进击 。 ofbiz 退货流程(包含获取可退货项流程分析 以及 取消退货项的过程分析)

    根据订单获取可退货项流程分析 退货的时候,调用 services_return.xml 中的获取可进行退货的退货项  getReturnableItems  ,该服务调用了Java类 org.ofbi ...

  9. ofbiz进击 第六节。 --OFBiz配置之[widget.properties] 配置属性的分析

    配置内容分析如下 # -- 定义上下文使用者 -- security.context =default # -- 定义密码限制长度最小值 -- password.length.min =5 # -- ...

随机推荐

  1. Android 出现java.lang.NoClassDefFoundError错误

    项目中用到了Retrofit在android4.4以下版本发生的问题 因为项目的build.gradle文件沿用于一个项目的,在defaultConfig z中已经声明了 multiDexEnable ...

  2. Codeforces Round #346 (Div. 2) D. Bicycle Race 叉积

    D. Bicycle Race 题目连接: http://www.codeforces.com/contest/659/problem/D Description Maria participates ...

  3. mysql 部分参数说明

    log_timestamps [5.7] This variable was added in MySQL 5.7.2. Before 5.7.2, timestamps in log message ...

  4. wait, WIFEXITED, WEXITSTATUS

    wait, WIFEXITED, WEXITSTATUS     偶尔翻到了这几个关键字,找到个文章复习了下:“点我”.记录下: wait的函数原型是: #include <sys/types. ...

  5. Fixed DC-DC Regulator Output Uses A Digitally Controlled Potentiometer

    http://electronicdesign.com/print/passives/fixed-dc-dc-regulator-output-uses-digitally-controlled-po ...

  6. hdu 1532 Drainage Ditches (最大流)

    最大流的第一道题,刚开始学这玩意儿,感觉好难啊!哎····· 希望慢慢地能够理解一点吧! #include<stdio.h> #include<string.h> #inclu ...

  7. 【mybatis】mybatis访问报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 或者 feign被调用方使用的mybatis总报空指针异常java.lang.NullPointerException,而变量都没有问题的情况

    mybatis访问报错:org.apache.ibatis.binding.BindingException: Invalid bound statement (not found) 需要检查的步骤: ...

  8. 【JSP EL】EL表达式里日期按照格式显示

    转:http://blog.csdn.net/kaishuaige/article/details/8505174 JSP页面用EL表达式 输出date格式     1.头上引入标签 <%@ t ...

  9. setTimeOut传參数

    function blink(e_Id, second) {var soccer = document.getElementById(e_Id); soccer.style.visibility = ...

  10. arm交叉编译opencv

    问题:undefined reference to `pthread_spin_init'解:修改CMakeCache.txt,CMAKE_EXE_LINKER_FLAGS原来为空,加上-lpthre ...