首页 > 其他分享 >SpringMVC-拦截器

SpringMVC-拦截器

时间:2022-11-19 20:00:17浏览次数:45  
标签:拦截器 SpringMVC mappedHandler request interceptor null response processedRequest

一、拦截器
SpringMVC提供了拦截器在处理请求之前,之后,渲染视图后执行逻辑处理。接口是HandlerInterceptor。preHandle方法在处理请求之前执行,postHandle方法是在处理请求后渲染视图视图之前执行。afterCompletion方法在渲染视图后执行。

二、解析interceptor

<mvc:interceptors>
	<mvc:interceptor>
		<mvc:mapping path="/*"/>
		<bean id="myInteceptor" class="mvc.inteceptor.MyInteceptor"/>
	</mvc:interceptor>
</mvc:interceptors>

interceptor标签由InterceptorsBeanDefinitionParser解析。

InterceptorsBeanDefinitionParser.parse(Element element, ParserContext context)

public BeanDefinition parse(Element element, ParserContext context) {
	context.pushContainingComponent(
			new CompositeComponentDefinition(element.getTagName(), context.extractSource(element)));

	RuntimeBeanReference pathMatcherRef = null;
	if (element.hasAttribute("path-matcher")) {
		pathMatcherRef = new RuntimeBeanReference(element.getAttribute("path-matcher"));
	}

	List<Element> interceptors = DomUtils.getChildElementsByTagName(element, "bean", "ref", "interceptor");
	for (Element interceptor : interceptors) {
		RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
		mappedInterceptorDef.setSource(context.extractSource(interceptor));
		mappedInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

		ManagedList<String> includePatterns = null;
		ManagedList<String> excludePatterns = null;
		Object interceptorBean;
		if ("interceptor".equals(interceptor.getLocalName())) {
			includePatterns = getIncludePatterns(interceptor, "mapping");
			excludePatterns = getIncludePatterns(interceptor, "exclude-mapping");
			Element beanElem = DomUtils.getChildElementsByTagName(interceptor, "bean", "ref").get(0);
			interceptorBean = context.getDelegate().parsePropertySubElement(beanElem, null);
		}
		else {
			interceptorBean = context.getDelegate().parsePropertySubElement(interceptor, null);
		}
		mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, includePatterns);
		mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, excludePatterns);
		mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(2, interceptorBean);

		if (pathMatcherRef != null) {
			mappedInterceptorDef.getPropertyValues().add("pathMatcher", pathMatcherRef);
		}

		String beanName = context.getReaderContext().registerWithGeneratedName(mappedInterceptorDef);
		context.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, beanName));
	}

	context.popAndRegisterContainingComponent();
	return null;
}

将每个interceptor元素解析成MappedInterceptor。

三、执行拦截器

RequestMappingHandlerMapping继承了ApplicationObjectSupport抽象类,ApplicationObjectSupport实现了ApplicationContextAware接口。在实例化RequestMappingHandlerMapping会调用ApplicationContextAware.setApplicationContext方法。会调用到AbstractHandlerMapping.initApplicationContext():

protected void initApplicationContext() throws BeansException {
	extendInterceptors(this.interceptors);
	detectMappedInterceptors(this.adaptedInterceptors);
	initInterceptors();
}


protected void detectMappedInterceptors(List<HandlerInterceptor> mappedInterceptors) {
	mappedInterceptors.addAll(BeanFactoryUtils.beansOfTypeIncludingAncestors(
			obtainApplicationContext(), MappedInterceptor.class, true, false).values());
}

detectMappedInterceptors从beanFactory中获取类型为MappedInterceptor的所有bean并加入mappedInterceptors集合中.

DispatcherServlet在处理请求获取handle时,会调用AbstractHandlerMapping.getHandlerExecutionChain

	protected HandlerExecutionChain getHandlerExecutionChain(Object handler, HttpServletRequest request) {
	HandlerExecutionChain chain = (handler instanceof HandlerExecutionChain ?
			(HandlerExecutionChain) handler : new HandlerExecutionChain(handler));

	for (HandlerInterceptor interceptor : this.adaptedInterceptors) {
		if (interceptor instanceof MappedInterceptor) {
			MappedInterceptor mappedInterceptor = (MappedInterceptor) interceptor;
			if (mappedInterceptor.matches(request)) {
				chain.addInterceptor(mappedInterceptor.getInterceptor());
			}
		}
		else {
			chain.addInterceptor(interceptor);
		}
	}
	return chain;
}

遍历adaptedInterceptors集合,如果HandlerInterceptor是MappedInterceptor类型,则判断MappedInterceptor是否匹配请求,如果匹配则加入HandlerExecutionChain。通过在配置拦截器mvc:mapping的path和请求路径是否匹配来判断MappedInterceptor是否匹配请求。如果HandlerInterceptor不是MappedInterceptor类型则加入HandlerExecutionChain。

DispatcherServlet.doDispatch(HttpServletRequest request, HttpServletResponse response)处理请求时:

protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
	HttpServletRequest processedRequest = request;
	HandlerExecutionChain mappedHandler = null;
	boolean multipartRequestParsed = false;

	WebAsyncManager asyncManager = WebAsyncUtils.getAsyncManager(request);

	try {
		ModelAndView mv = null;
		Exception dispatchException = null;

		try {
			processedRequest = checkMultipart(request);
			multipartRequestParsed = (processedRequest != request);

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

			// Determine handler adapter for the current request.
			HandlerAdapter ha = getHandlerAdapter(mappedHandler.getHandler());

			// Process last-modified header, if supported by the handler.
			String method = request.getMethod();
			boolean isGet = "GET".equals(method);
			if (isGet || "HEAD".equals(method)) {
				long lastModified = ha.getLastModified(request, mappedHandler.getHandler());
				if (new ServletWebRequest(request, response).checkNotModified(lastModified) && isGet) {
					return;
				}
			}

			if (!mappedHandler.applyPreHandle(processedRequest, response)) {
				return;
			}

			// Actually invoke the handler.
			mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

			if (asyncManager.isConcurrentHandlingStarted()) {
				return;
			}

			applyDefaultViewName(processedRequest, mv);
			mappedHandler.applyPostHandle(processedRequest, response, mv);
		}
		catch (Exception ex) {
			dispatchException = ex;
		}
		catch (Throwable err) {
			// As of 4.3, we're processing Errors thrown from handler methods as well,
			// making them available for @ExceptionHandler methods and other scenarios.
			dispatchException = new NestedServletException("Handler dispatch failed", err);
		}
		processDispatchResult(processedRequest, response, mappedHandler, mv, dispatchException);
	}
	catch (Exception ex) {
		triggerAfterCompletion(processedRequest, response, mappedHandler, ex);
	}
	catch (Throwable err) {
		triggerAfterCompletion(processedRequest, response, mappedHandler,
				new NestedServletException("Handler processing failed", err));
	}
	finally {
		if (asyncManager.isConcurrentHandlingStarted()) {
			// Instead of postHandle and afterCompletion
			if (mappedHandler != null) {
				mappedHandler.applyAfterConcurrentHandlingStarted(processedRequest, response);
			}
		}
		else {
			// Clean up any resources used by a multipart request.
			if (multipartRequestParsed) {
				cleanupMultipart(processedRequest);
			}
		}
	}
}

调用getHandler获取HandlerExecutionChain后,调用mappedHandler.applyPreHandle(processedRequest, response)执行拦截器的preHandle方法,如果有一个拦截器返回false,则退出。调用HandlerAdapter.handle执行实际处理请求。在调用mappedHandler.applyPostHandle逆序执行拦截器postHandle的方法。processDispatchResult渲染视图和处理异常完成后调用mappedHandler.triggerAfterCompletion执行拦截器的afterCompletion方法。

标签:拦截器,SpringMVC,mappedHandler,request,interceptor,null,response,processedRequest
From: https://www.cnblogs.com/shigongp/p/16906836.html

相关文章

  • 第4章SpringMVC核心技术-请求转发和重定向
    第4章SpringMVC核心技术-请求转发和重定向1请求重定向和转发概念当处理器对请求处理完毕后,向其它资源进行跳转时,有两种跳转方式:请求转发与重定向。而根据所要跳转......
  • SpringMVC-处理异常
    DispatcherServlet.doDispatchprotectedvoiddoDispatch(HttpServletRequestrequest,HttpServletResponseresponse)throwsException{ HttpServletRequestprocess......
  • SpringMVC-处理404
    一、解析mvc:default-servlet-handler/mvc.xml中<mvc:default-servlet-handler/>由DefaultServletHandlerBeanDefinitionParser负责解析。DefaultServletHandlerBeanDefi......
  • springMVC
    SpringMVCssm:mybatis+Spring+SpringMVCSpringMVC:SpringMVC的执行流程SpringMVC:SSM框架整合MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规......
  • 框架进行时——SpringMVC流程简析(一)
    基于SpringWeb(5.3.23)的接口请求分析前情提要假定当前Web项目中有如下实体类和接口:packagecom.example.entity;publicclassWebUser{privateStringname;......
  • SpringMVC 拦截异常Exception返回Json,适合Java做后台业务项目
    publicclassExceptionHandlerimplementsHandlerExceptionResolver{@OverridepublicModelAndViewresolveException(HttpServletRequestreque......
  • 用SpringMVC 实现断点续传 (HTTP)
    ​ 一、概述 所谓断点续传,其实只是指下载,也就是要从文件已经下载的地方开始继续下载。在以前版本的HTTP协议是不支持断点的,HTTP/1.1开始就支持了。一般断点下载时才用......
  • SpringMVC 学习记录
    SpringMVC什么是MVCMVC是一种软件架构的思想,将软件按照模型、视图、控制器来划分M:Model,模型层,指工程中的avaBean,作用是处理数据JavaBean分为两类:一类称为实体......
  • 字符编码拦截器延伸出的拦截器
    方案一AdviceAdapter+Interceptorget使用拦截器校验,post请求使用@ControllerAdvicehttps://cloud.tencent.com/developer/article/1516443packagecom.shendi.dolphin......
  • intellij springmvc项目报错:[RMI TCP Connection(3)-127.0.0.1] org.apache.jasper.se
    idea部署项目报错信息:[RMITCPConnection(3)-127.0.0.1]org.apache.jasper.servlet.TldScanner.scanJarsAtleastoneJARwasscannedforTLDsyetcontainednoTLDs.......