📄 dispatcherservlet.java
字号:
interceptor.postHandle(processedRequest, response, mappedHandler.getHandler(), mv);
}
}
}
catch (ModelAndViewDefiningException ex) {
logger.debug("ModelAndViewDefiningException encountered", ex);
mv = ex.getModelAndView();
}
catch (Exception ex) {
Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
mv = processHandlerException(request, response, handler, ex);
}
// Did the handler return a view to render?
if (mv != null && !mv.isEmpty()) {
render(mv, processedRequest, response);
}
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, null);
}
catch (Exception ex) {
// Trigger after-completion for thrown exception.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, ex);
throw ex;
}
catch (Error err) {
// Trigger after-completion for thrown error (rare case).
// Better trigger callback without exception argument rather than no callback at all;
// after-completion callbacks offen perform finally-style cleanup.
triggerAfterCompletion(mappedHandler, interceptorIndex, processedRequest, response, null);
throw err;
}
finally {
// Clean up any resources used by a multipart request.
if (processedRequest instanceof MultipartHttpServletRequest && processedRequest != request) {
this.multipartResolver.cleanupMultipart((MultipartHttpServletRequest) processedRequest);
}
}
}
/**
* Override HttpServlet's <code>getLastModified</code> method to evaluate
* the Last-Modified value of the mapped handler.
*/
protected long getLastModified(HttpServletRequest request) {
try {
HandlerExecutionChain mappedHandler = getHandler(request, true);
if (mappedHandler == null || mappedHandler.getHandler() == null) {
// Ignore -> will reappear on doService.
logger.debug("No handler found in getLastModified");
return -1;
}
HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());
long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
if (logger.isDebugEnabled()) {
logger.debug("Last-Modified value for [" + request.getRequestURI() + "] is [" + lastModified + "]");
}
return lastModified;
}
catch (Exception ex) {
// Ignore -> will reappear on doService.
logger.debug("Exception thrown in getLastModified", ex);
return -1;
}
}
/**
* Convert the request into a multipart request, and make multipart resolver available.
* If no multipart resolver is set, simply use the existing request.
* @param request current HTTP request
* @return the processed request (multipart wrapper if necessary)
*/
protected HttpServletRequest checkMultipart(HttpServletRequest request) throws MultipartException {
if (this.multipartResolver != null && this.multipartResolver.isMultipart(request)) {
if (request instanceof MultipartHttpServletRequest) {
logger.info("Request is already a MultipartHttpServletRequest - if not in a forward, " +
"this typically results from an additional MultipartFilter in web.xml");
}
else {
request.setAttribute(MULTIPART_RESOLVER_ATTRIBUTE, this.multipartResolver);
return this.multipartResolver.resolveMultipart(request);
}
}
// If not returned before: return original request.
return request;
}
/**
* Return the HandlerExecutionChain for this request.
* Try all handler mappings in order.
* @param request current HTTP request
* @param cache whether to cache the HandlerExecutionChain in a request attribute
* @return the HandlerExceutionChain, or null if no handler could be found
*/
protected HandlerExecutionChain getHandler(HttpServletRequest request, boolean cache) throws Exception {
HandlerExecutionChain handler =
(HandlerExecutionChain) request.getAttribute(HANDLER_EXECUTION_CHAIN_ATTRIBUTE);
if (handler != null) {
if (!cache) {
request.removeAttribute(HANDLER_EXECUTION_CHAIN_ATTRIBUTE);
}
return handler;
}
Iterator it = this.handlerMappings.iterator();
while (it.hasNext()) {
HandlerMapping hm = (HandlerMapping) it.next();
if (logger.isDebugEnabled()) {
logger.debug("Testing handler map [" + hm + "] in DispatcherServlet with name '" +
getServletName() + "'");
}
handler = hm.getHandler(request);
if (handler != null) {
if (cache) {
request.setAttribute(HANDLER_EXECUTION_CHAIN_ATTRIBUTE, handler);
}
return handler;
}
}
return null;
}
/**
* No handler found -> set appropriate HTTP response status.
* @param request current HTTP request
* @param response current HTTP response
* @throws IOException if thrown by the HttpServletResponse
*/
protected void noHandlerFound(HttpServletRequest request, HttpServletResponse response) throws IOException {
if (pageNotFoundLogger.isWarnEnabled()) {
pageNotFoundLogger.warn("No mapping for [" + request.getRequestURI() +
"] in DispatcherServlet with name '" + getServletName() + "'");
}
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
/**
* Return the HandlerAdapter for this handler object.
* @param handler the handler object to find an adapter for
* @throws ServletException if no HandlerAdapter can be found for the handler.
* This is a fatal error.
*/
protected HandlerAdapter getHandlerAdapter(Object handler) throws ServletException {
Iterator it = this.handlerAdapters.iterator();
while (it.hasNext()) {
HandlerAdapter ha = (HandlerAdapter) it.next();
if (logger.isDebugEnabled()) {
logger.debug("Testing handler adapter [" + ha + "]");
}
if (ha.supports(handler)) {
return ha;
}
}
throw new ServletException("No adapter for handler [" + handler +
"]: Does your handler implement a supported interface like Controller?");
}
/**
* Determine an error ModelAndView via the registered HandlerExceptionResolvers.
* @param request current HTTP request
* @param response current HTTP response
* @param handler the executed handler, or null if none chosen at the time of
* the exception (for example, if multipart resolution failed)
* @param ex the exception that got thrown during handler execution
* @return a corresponding ModelAndView to forward to
* @throws Exception if no error ModelAndView found
*/
protected ModelAndView processHandlerException(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
ModelAndView exMv = null;
for (Iterator it = this.handlerExceptionResolvers.iterator(); exMv == null && it.hasNext();) {
HandlerExceptionResolver resolver = (HandlerExceptionResolver) it.next();
exMv = resolver.resolveException(request, response, handler, ex);
}
if (exMv != null) {
if (logger.isDebugEnabled()) {
logger.debug("HandlerExceptionResolver returned ModelAndView [" + exMv + "] for exception");
}
logger.warn("Handler execution resulted in exception - forwarding to resolved error view", ex);
return exMv;
}
else {
throw ex;
}
}
/**
* Render the given ModelAndView. This is the last stage in handling a request.
* It may involve resolving the view by name.
* @param mv the ModelAndView to render
* @param request current HTTP servlet request
* @param response current HTTP servlet response
* @throws Exception if there's a problem rendering the view
*/
protected void render(ModelAndView mv, HttpServletRequest request, HttpServletResponse response)
throws Exception {
// Determine locale for request and apply it to the response.
Locale locale = this.localeResolver.resolveLocale(request);
response.setLocale(locale);
View view = null;
if (mv.isReference()) {
// We need to resolve the view name.
view = resolveViewName(mv.getViewName(), mv.getModelInternal(), locale, request);
if (view == null) {
throw new ServletException("Could not resolve view with name '" + mv.getViewName() +
"' in servlet with name '" + getServletName() + "'");
}
}
else {
// No need to lookup: the ModelAndView object contains the actual View object.
view = mv.getView();
if (view == null) {
throw new ServletException("ModelAndView [" + mv + "] neither contains a view name nor a " +
"View object in servlet with name '" + getServletName() + "'");
}
}
// Delegate to the View object for rendering.
if (logger.isDebugEnabled()) {
logger.debug("Rendering view [" + view + "] in DispatcherServlet with name '" + getServletName() + "'");
}
view.render(mv.getModelInternal(), request, response);
}
/**
* Resolve the given view name into a View object (to be rendered).
* <p>Default implementations asks all ViewResolvers of this dispatcher.
* Can be overridden for custom resolution strategies, potentially based
* on specific model attributes or request parameters.
* @param viewName the name of the view to resolve
* @param model the model to be passed to the view
* @param locale the current locale
* @param request current HTTP servlet request
* @return the View object, or null if none found
* @throws Exception if the view cannot be resolved
* (typically in case of problems creating an actual View object)
* @see ViewResolver#resolveViewName
*/
protected View resolveViewName(String viewName, Map model, Locale locale, HttpServletRequest request)
throws Exception {
for (Iterator it = this.viewResolvers.iterator(); it.hasNext();) {
ViewResolver viewResolver = (ViewResolver) it.next();
View view = viewResolver.resolveViewName(viewName, locale);
if (view != null) {
return view;
}
}
return null;
}
/**
* Trigger afterCompletion callbacks on the mapped HandlerInterceptors.
* Will just invoke afterCompletion for all interceptors whose preHandle
* invocation has successfully completed and returned true.
* @param mappedHandler the mapped HandlerExecutionChain
* @param interceptorIndex index of last interceptor that successfully completed
* @param ex Exception thrown on handler execution, or null if none
* @see HandlerInterceptor#afterCompletion
*/
private void triggerAfterCompletion(
HandlerExecutionChain mappedHandler, int interceptorIndex,
HttpServletRequest request, HttpServletResponse response, Exception ex)
throws Exception {
// Apply afterCompletion methods of registered interceptors.
if (mappedHandler != null) {
if (mappedHandler.getInterceptors() != null) {
for (int i = interceptorIndex; i >= 0; i--) {
HandlerInterceptor interceptor = mappedHandler.getInterceptors()[i];
try {
interceptor.afterCompletion(request, response, mappedHandler.getHandler(), ex);
}
catch (Throwable ex2) {
logger.error("HandlerInterceptor.afterCompletion threw exception", ex2);
}
}
}
}
}
/**
* Restore the request attributes after an include.
* @param request current HTTP request
* @param attributesSnapshot the snapshot of the request attributes
* before the include
*/
private void restoreAttributesAfterInclude(HttpServletRequest request, Map attributesSnapshot) {
logger.debug("Restoring snapshot of request attributes after include");
// Need to copy into separate Collection here, to avoid side effects
// on the Enumeration when removing attributes.
Set attrsToCheck = new HashSet();
Enumeration attrNames = request.getAttributeNames();
while (attrNames.hasMoreElements()) {
String attrName = (String) attrNames.nextElement();
if (this.cleanupAfterInclude || attrName.startsWith(DispatcherServlet.class.getName())) {
attrsToCheck.add(attrName);
}
}
// Iterate over the attributes to check, restoring the original value
// or removing the attribute, respectively, if appropriate.
for (Iterator it = attrsToCheck.iterator(); it.hasNext();) {
String attrName = (String) it.next();
Object attrValue = attributesSnapshot.get(attrName);
if (attrValue != null) {
if (logger.isDebugEnabled()) {
logger.debug("Restoring original value of attribute [" + attrName + "] after include");
}
request.setAttribute(attrName, attrValue);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Removing attribute [" + attrName + "] after include");
}
request.removeAttribute(attrName);
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -