Java深入-Spring異常処理HandlerException Resolaver

5855 ワード

Springの異常統一処理はとても簡単です.まずSpringで定義されているHandlerException Resolaverインターフェースを見たいです.
/**
 * Interface to be implemented by objects than can resolve exceptions thrown
 * during handler mapping or execution, in the typical case to error views.
 * Implementors are typically registered as beans in the application context.
 *
 * 

Error views are analogous to the error page JSPs, but can be used with * any kind of exception including any checked exception, with potentially * fine-granular mappings for specific handlers. * * @author Juergen Hoeller * @since 22.11.2003 */ public interface HandlerExceptionResolver { /** * Try to resolve the given exception that got thrown during on handler execution, * returning a ModelAndView that represents a specific error page if appropriate. *

The returned ModelAndView may be {@linkplain ModelAndView#isEmpty() empty} * to indicate that the exception has been resolved successfully but that no view * should be rendered, for instance by setting a status code. * @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, * or null for default processing */ ModelAndView resolveException( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex); }

彼は、我々が異常を処理するには、このインターフェースクラスを実現する必要があります.そして、resoveException方法を実現し、resoveException方法で自分の異常な論理を処理します.
例えば、カスタムの異常処理クラスを設計します.
/**
 *             
 * @author zhuli
 * @date 2014-9-3
 */
public class MyExceptionResolver implements HandlerExceptionResolver {

    private static final Logger logger = LoggerFactory.getLogger(MyExceptionResolver.class);

    @Override
    public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        
        //            
        if (ex instanceof org.springframework.web.HttpRequestMethodNotSupportedException) {
            logger.warn(Logger.ACTION.DEFAULT, "Http Method Error");
        }
        return null;
    }

}
そして、私たちがカスタマイズしたMyException Resolover類をbeanに注入する必要があります.
具体的なSpringはどうやって呼びますか?まずSpringのdoDisplatch方法を見てもいいです.このようなコードがあります.
			catch (ModelAndViewDefiningException ex) {
				logger.debug("ModelAndViewDefiningException encountered", ex);
				mv = ex.getModelAndView();
			}
			catch (Exception ex) {
				Object handler = (mappedHandler != null ? mappedHandler.getHandler() : null);
				mv = processHandlerException(processedRequest, response, handler, ex);
				errorView = (mv != null);
			}
その中のプロcessHandlerException方法は異常処理を捕獲するためのものです.プロcessHandlerExceptionを引き続き見ます.
	protected ModelAndView processHandlerException(HttpServletRequest request, HttpServletResponse response,
			Object handler, Exception ex) throws Exception {

		// Check registered HandlerExceptionResolvers...
		ModelAndView exMv = null;
		for (HandlerExceptionResolver handlerExceptionResolver : this.handlerExceptionResolvers) {
			exMv = handlerExceptionResolver.resolveException(request, response, handler, ex);
			if (exMv != null) {
				break;
			}
		}
		if (exMv != null) {
			if (exMv.isEmpty()) {
				return null;
			}
			// We might still need view name translation for a plain error model...
			if (!exMv.hasView()) {
				exMv.setViewName(getDefaultViewName(request));
			}
			if (logger.isDebugEnabled()) {
				logger.debug("Handler execution resulted in exception - forwarding to resolved error view: " + exMv, ex);
			}
			WebUtils.exposeErrorRequestAttributes(request, ex, getServletName());
			return exMv;
		}

		throw ex;
	}
この方法の中のhandle Exception Resoliver.resoveExceptionは異常を捕獲するために用いられ、Springは複数のカスタムの異常なクラスの実現を可能にします.
this.handlee Exception Resoolversの方法を見て、追跡して入ることができます.
private void initHandlerExceptionResolvers(ApplicationContext context) {
		this.handlerExceptionResolvers = null;

		if (this.detectAllHandlerExceptionResolvers) {
			// Find all HandlerExceptionResolvers in the ApplicationContext, including ancestor contexts.
			Map matchingBeans = BeanFactoryUtils
					.beansOfTypeIncludingAncestors(context, HandlerExceptionResolver.class, true, false);
			if (!matchingBeans.isEmpty()) {
				this.handlerExceptionResolvers = new ArrayList(matchingBeans.values());
				// We keep HandlerExceptionResolvers in sorted order.
				OrderComparator.sort(this.handlerExceptionResolvers);
			}
		}
		else {
			try {
				HandlerExceptionResolver her =
						context.getBean(HANDLER_EXCEPTION_RESOLVER_BEAN_NAME, HandlerExceptionResolver.class);
				this.handlerExceptionResolvers = Collections.singletonList(her);
			}
			catch (NoSuchBeanDefinitionException ex) {
				// Ignore, no HandlerExceptionResolver is fine too.
			}
		}

		// Ensure we have at least some HandlerExceptionResolvers, by registering
		// default HandlerExceptionResolvers if no other resolvers are found.
		if (this.handlerExceptionResolvers == null) {
			this.handlerExceptionResolvers = getDefaultStrategies(context, HandlerExceptionResolver.class);
			if (logger.isDebugEnabled()) {
				logger.debug("No HandlerExceptionResolvers found in servlet '" + getServletName() + "': using default");
			}
		}
	}
この方法はハンドルException Resolversを初期化し、カスタムの異常処理クラス(複数可)をthis.handlee Exception Resoliversに書き込むことです.