OFBiz:处理nextRequestResponse
这里的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的更多相关文章
- OFBiz:解析doRequest()
这里的doRequest()是指RequestHandler中的同名函数: public void doRequest(HttpServletRequest request, HttpServletR ...
- ofbiz 代码日记
写代码一定要尽善尽美.. //修改方法 //条件查询 用于修改 List<GenericValue> stoList = delegator.findByAnd("YcrossS ...
- ofbiz 本地化及邮件设置126邮箱
ofibz登陆功能有通过电子邮件找会密码的功能,但找回密码功能需要配置一个发送email的邮箱账号和smtp服务器的配置,具体配置如下: 1:在ofbiz数据库的表product_store_emai ...
- Apache OFBiz 研究记录01
作为Apache 的顶级项目: Apache OFBiz,功能十分强大,一般开发者很难用到全部功能. 这次笔者的研究主要集中在电子商务平台这一块,一步一步解构. OFBiz下载地址:http://of ...
- OFBIZ:启动之ContainerLoader
ContainerLoader类实现StartupLoader接口,目的是装入各种Container容器. /** * An OFBiz container. A container can be t ...
- OFBIZ:启动之StartupLoader
任意一个JAVA程序都是从main()开始启动的,OFBIZ也不例外.OFBIZ的main()位于framework/start/src/org/ofbiz/base/start/Start.java ...
- ofbiz的部署及安装问题解决办法
ofbiz是apache下的顶级开源项目之一,非常强大说下正常流程及解决办法. 开发环境:本人开发环境是win7系统 准备: 1.如果使用的是git,从https://github.com/apach ...
- ofbiz进击 。 ofbiz 退货流程(包含获取可退货项流程分析 以及 取消退货项的过程分析)
根据订单获取可退货项流程分析 退货的时候,调用 services_return.xml 中的获取可进行退货的退货项 getReturnableItems ,该服务调用了Java类 org.ofbi ...
- ofbiz进击 第六节。 --OFBiz配置之[widget.properties] 配置属性的分析
配置内容分析如下 # -- 定义上下文使用者 -- security.context =default # -- 定义密码限制长度最小值 -- password.length.min =5 # -- ...
随机推荐
- Android 杀掉当前程序的进程
在销毁所有活动的代码后面再加上杀掉当前进程的代码,以保证程序完全退出,杀掉进程的代码如下所示: android.os.Process.killProcess(android.os.Process.my ...
- yaf学习
<?php 安装 phpize ./configure --with-php-config=/usr/local/php/bin/php-config 路由类 final Yaf_Router ...
- HDU 4618 Palindrome Sub-Array 暴力
Palindrome Sub-Array 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=4618 Description A palindrome s ...
- Dart格式化输出
类似于保留几位小数,直接 n.toStringAsFixed() 例如: 1.toStringAsFixed(3); // 1.000 (4321.12345678).toStringAsFixed( ...
- mvc-单例多线程模式
以spring mvc 为例子 spring mvc 的Controller类默认Scope是单例(singleton) 测试结果发现spring3中的controller默认是单例的,若是某个con ...
- MySQL的max_user_connections拒绝连接的一次踩雷经验
近期线上的数据遇到一个问题,最终原因为max_user_connections和max_connections的一个bug导致,具体过程如下 现象 前端页面不断的出现错误页面. 排查处理过程 按照数据 ...
- CentOS 6.9/7通过yum安装指定版本的Redis
一.安装 // 安装依赖 # wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm && ...
- GNU 是什么?
https://www.gnu.org/ GNU 是什么? GNU is a Unix-like operating system that is free software—it respects ...
- Android Binder总结
1. MediapplayerService 的启动,怎样在ServiceManager注冊的,不解说详细的细节 ServiceManager 是整个系统的Service总管,其余的系统服务都是通过d ...
- jQuery EasyUI API 中文文档 - Panel面板
<html> <head> <title>布局管理器--控制面板</title> <script src="jquery-easyui/ ...