• 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 + "
     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);
    }
  • 相关阅读:
    awk线程号
    std::string::substr函数
    计数器表的简单使用
    vim + oh-my-zsh + git搭建开发环境
    <<代码大全>>阅读笔记之二 变量名的力量
    <<代码大全>>阅读笔记之一 使用变量的一般事项
    压测工具ab的简单使用
    nginx配置文件详解
    numba初体验
    Linux查找文件内容小技巧
  • 原文地址:https://www.cnblogs.com/eastson/p/3584621.html
Copyright © 2020-2023  润新知