ITEEDU

Handler Interceptor

如 果您在 Controller 执行的前后,或者是在 View 绘制之后打算作一些记录或栏截请求等动作, 您可以实作 org.springframework.web.servlet.HandlerInterceptor  介面,在这个介面中规范了三个 必须实作的方法, 其定义如下所示:

package org.springframework.web.servlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface HandlerInterceptor {
	boolean preHandle(HttpServletRequest request, 
				HttpServletResponse response, Object handler) 
				throws Exception;
	void postHandle(HttpServletRequest request, 
				HttpServletResponse response, 
				Object handler,	
				ModelAndView modelAndView) 
				throws Exception;
	void afterCompletion(HttpServletRequest request, 
				HttpServletResponse response, 
				Object handler,
				Exception ex) 
				throws Exception;
}

preHandler()会在Controller处理请求之前被呼叫,传回的boolean快定是否呼叫接下来的Handler Interceptor或是Controller来处理请求,如果传回false,则接下来的Interceptor或Controller就不处 理请 求,postHandler()则会在Controller处理完请求之后被呼叫,afterCompletion()方法会在View 绘制完成之后被呼 叫。

您可以直接继承org.springframework.web.servlet.handler.HandlerInterceptorAdapter ,它实作了 HandlerInterceptor介面,您只要针对您有兴趣的方法进行重新定义就可以了,例如可以修改 第 一个 Spring MVC  程式,在当中实作一个LoggingInterceptor,在请求被控制物件处理的前、后来 作记录:

•      LoggingInterceptor.java
package onlyfun.caterpillar;
import java.util.logging.Logger;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet. handler.HandlerInterceptorAdapter;
public class LoggingInterceptor
extends HandlerInterceptorAdapter {
	private Logger logger = Logger.getLogger(this.getClass().getName());
	public boolean preHandle(HttpServletRequest request,
				HttpServletResponse response,
				Object handler) 
				throws Exception {
		logger.info(handler.getClass().getName() + " 开始执行...");
		return true;
	}
	public void postHandle(HttpServletRequest request, 
				HttpServletResponse response,
					Object handler,
					ModelAndView modelAndView) 
					throws Exception {
		logger.info(handler.getClass().getName() + " 执行完毕...");
	}
	public void afterCompletion(HttpServletRequest request, 
				HttpServletResponse response,
				Object handler,
				Exception ex) 
				throws Exception {
		logger.info("请求处理完毕...");
	}
}

要使用定义好的 HandlerInterceptor,必须在 Bean 定义档中进行定义,例如:

•      beans‐config.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC
"-//SPRING/DTD BEAN/EN""http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
	<bean id="loggingInterceptor" class="onlyfun.caterpillar.LoggingInterceptor"/>
	<bean id="viewResolver" class="org.springframework.web.servlet.
		→ view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/WEB-INF/jsp/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>
	<bean id="urlHandlerMapping" class="org.springframework.web.servlet.
		→ handler.SimpleUrlHandlerMapping">
		<property name="interceptors">
			<list>
				<ref bean="loggingInterceptor"/>
			</list>
		</property>
		<property name="mappings">
			<props>
				<prop key="/hello.do">helloController</prop>
			</props>
		</property>
	</bean>
	<bean id="helloController" class="onlyfun.caterpillar.HelloController">
		<property name="viewPage">
			<value>hello</value>
		</property>
	</bean>
</beans>

注意到这边所使用的 UrlHandlerMapping 是 SimpleUrlHandlerMapping;当您透过 DispatcherServlet 请求时,则在请求被处理的前后都会被记录下动作及所处理请求的控制物件,在控制台所看到的 资讯如下所示:

2005/12/30  上 午    12:03:24   onlyfun.caterpillar.LoggingInterceptor preHandle
资讯: onlyfun.caterpillar.HelloController 开始执行...
2005/12/30  上 午    12:03:24   onlyfun.caterpillar.LoggingInterceptor postHandle
资讯: onlyfun.caterpillar.HelloController 执行完毕...
2005/12/30  上 午    12:03:24   onlyfun.caterpillar.LoggingInterceptor afterCompletion

资讯: 请求处理完毕...