GrailsDispatcherServlet中的doDispatch方法

@Override
protected void doDispatch(final HttpServletRequest request, HttpServletResponse response) throws Exception {

    request.setAttribute(LOCALE_RESOLVER_ATTRIBUTE, localeResolver);

    HttpServletRequest processedRequest = request;
    HandlerExecutionChain mappedHandler = null;
    int interceptorIndex = -1;

    // Expose current LocaleResolver and request as LocaleContext.
    LocaleContext previousLocaleContext = LocaleContextHolder.getLocaleContext();
    LocaleContextHolder.setLocaleContext(new LocaleContext() {
        public Locale getLocale() {
            return localeResolver.resolveLocale(request);
        }
    });

    // If the request is an include we need to try to use the original wrapped sitemesh
    // response, otherwise layouts won't work properly
    if (WebUtils.isIncludeRequest(request)) {
        response = useWrappedOrOriginalResponse(response);
    }

    GrailsWebRequest requestAttributes = null;
    RequestAttributes previousRequestAttributes = null;
    Exception handlerException = null;
    boolean isAsyncRequest = processedRequest.getAttribute("javax.servlet.async.request_uri") != null;
    try {
        ModelAndView mv;
        boolean errorView = false;
        try {
            Object exceptionAttribute = request.getAttribute(EXCEPTION_ATTRIBUTE);
            // only process multipart requests if an exception hasn't occured
            if (exceptionAttribute == null) {
                processedRequest = checkMultipart(request);
            }
            // Expose current RequestAttributes to current thread.
            previousRequestAttributes = RequestContextHolder.currentRequestAttributes();
            if(previousRequestAttributes instanceof GrailsWebRequest) {
                requestAttributes = new GrailsWebRequest(processedRequest, response, ((GrailsWebRequest)previousRequestAttributes).getAttributes());
            } else {
                requestAttributes = new GrailsWebRequest(processedRequest, response, getServletContext());
            }
            if( previousRequestAttributes != null) {
                copyParamsFromPreviousRequest(previousRequestAttributes, requestAttributes);
            }

            // Update the current web request.
            WebUtils.storeGrailsWebRequest(requestAttributes);

            if (logger.isDebugEnabled()) {
                logger.debug("Bound request context to thread: " + request);
                logger.debug("Using response object: " + response.getClass());
            }

            // Determine handler for the current request.
            mappedHandler = getHandler(processedRequest);
            Object handler = mappedHandler.getHandler();
            if (mappedHandler == null || handler == null) {
                noHandlerFound(processedRequest, response);
                return;
            }

            HandlerInterceptor[] interceptors = mappedHandler.getInterceptors();

            // Apply preHandle methods of registered interceptors.
            if (interceptors != null) {
                int i = 0;
                for (HandlerInterceptor interceptor : interceptors) {
                    if (!interceptor.preHandle(processedRequest, response, handler)) {
                        triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
                        return;
                    }
                    interceptorIndex = i;
                    i++;
                }
            }

            // if this is an async request that has been resumed, then don't execute the action again instead try get the model and view and continue

            if (isAsyncRequest) {
                Object modelAndViewO = processedRequest.getAttribute(GrailsApplicationAttributes.MODEL_AND_VIEW);
                if (modelAndViewO != null) {
                    mv = (ModelAndView) modelAndViewO;
                }
                else {
                    mv = null;
                }
            }else {
                // Actually invoke the handler.
                HandlerAdapter ha = getHandlerAdapter(handler);
                mv = ha.handle(processedRequest, response, handler);
                // if an async request was started simply return
                if (processedRequest.getAttribute(GrailsApplicationAttributes.ASYNC_STARTED) != null) {
                    processedRequest.setAttribute(GrailsApplicationAttributes.MODEL_AND_VIEW, mv);
                    return;
                }

                // Do we need view name translation?
                if ((ha instanceof AnnotationMethodHandlerAdapter || ha instanceof RequestMappingHandlerAdapter) && mv != null && !mv.hasView()) {
                    mv.setViewName(getDefaultViewName(request));
                }
            }

            // Apply postHandle methods of registered interceptors.
            if (interceptors != null) {
                for (int i = interceptors.length - 1; i >= 0; i--) {
                    interceptors[i].postHandle(processedRequest, response, handler, mv);
                }
            }
        }
        catch (ModelAndViewDefiningException ex) {
            handlerException = ex;
            if (logger.isDebugEnabled()) {
                logger.debug("ModelAndViewDefiningException encountered", ex);
            }
            mv = ex.getModelAndView();
        }
        catch (Exception ex) {
            handlerException = ex;
            Object handler = mappedHandler == null ? null : mappedHandler.getHandler();
            mv = processHandlerException(request, response, handler, ex);
            errorView = (mv != null);
        }

        // Did the handler return a view to render?
        if (mv != null && !mv.wasCleared()) {
            // If an exception occurs in here, like a bad closing tag,
            // we have nothing to render.

            try {
                render(mv, processedRequest, response);
                if (isAsyncRequest && (response instanceof GrailsContentBufferingResponse)) {
                    GroovyPageLayoutFinder groovyPageLayoutFinder = getWebApplicationContext().getBean("groovyPageLayoutFinder", GroovyPageLayoutFinder.class);
                    GrailsContentBufferingResponse bufferingResponse = (GrailsContentBufferingResponse) response;
                    HttpServletResponse targetResponse = bufferingResponse.getTargetResponse();
                    Content content = bufferingResponse.getContent();
                    if (content != null) {
                        Decorator decorator = groovyPageLayoutFinder.findLayout(request, content);
                        SiteMeshWebAppContext webAppContext = new SiteMeshWebAppContext(request, targetResponse, getServletContext());
                        if (decorator != null) {
                            if (decorator instanceof com.opensymphony.sitemesh.Decorator) {
                                ((com.opensymphony.sitemesh.Decorator)decorator).render(content, webAppContext);
                            } else {
                                new OldDecorator2NewDecorator(decorator).render(content, webAppContext);
                            }
                        } else {
                            content.writeOriginal(targetResponse.getWriter());
                        }
                    }
                }
                if (errorView) {
                    WebUtils.clearErrorRequestAttributes(request);
                }
            } catch (Exception e) {
                // Only render the error view if we're not already trying to render it.
                // This prevents a recursion if the error page itself has errors.
                if (request.getAttribute(GrailsApplicationAttributes.RENDERING_ERROR_ATTRIBUTE) == null) {
                    request.setAttribute(GrailsApplicationAttributes.RENDERING_ERROR_ATTRIBUTE, Boolean.TRUE);

                    mv = super.processHandlerException(processedRequest, response, mappedHandler, e);
                    handlerException = e;
                    if (mv != null) render(mv, processedRequest, response);
                }
                else {
                    request.removeAttribute(GrailsApplicationAttributes.RENDERING_ERROR_ATTRIBUTE);
                    logger.warn("Recursive rendering of error view detected.", e);

                    try {
                        response.setContentType("text/plain");
                        response.getWriter().write("Internal server error");
                        response.flushBuffer();
                    } catch (Exception e2) {
                        logger.error("Internal server error - problem rendering error view", e2);
                    }

                    requestAttributes.setRenderView(false);
                    return;
                }
            }
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("Null ModelAndView returned to DispatcherServlet with name '" +
                        getServletName() + "': assuming HandlerAdapter completed request handling");
            }
        }

        // Trigger after-completion for successful outcome.
        triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, handlerException);
    }
    catch (Exception ex) {
        // Trigger after-completion for thrown exception.
        triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
        throw ex;
    }
    catch (Error err) {
        ServletException ex = new NestedServletException("Handler processing failed", err);
        // Trigger after-completion for thrown exception.
        triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
        throw ex;
    }
    finally {
        // Clean up any resources used by a multipart request.
        if (processedRequest instanceof MultipartHttpServletRequest) {
            if (multipartResolver != null) {
                multipartResolver.cleanupMultipart((MultipartHttpServletRequest) processedRequest);
            }
        }
        request.removeAttribute(MultipartHttpServletRequest.class.getName());

        // Reset thread-bound holders
        if (requestAttributes != null) {
            requestAttributes.requestCompleted();
            if (previousRequestAttributes instanceof GrailsWebRequest) {
                WebUtils.storeGrailsWebRequest((GrailsWebRequest) previousRequestAttributes);
            }
            else {
                RequestContextHolder.setRequestAttributes(previousRequestAttributes);
            }
        }

        LocaleContextHolder.setLocaleContext(previousLocaleContext);

        if (logger.isDebugEnabled()) {
            logger.debug("Cleared thread-bound request context: " + request);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值