# Spring `HandlerInterceptor`示例

> [https://howtodoinjava.com/spring-mvc/spring-intercepting-requests-using-handlerinterceptor-with-example/](https://howtodoinjava.com/spring-mvc/spring-intercepting-requests-using-handlerinterceptor-with-example/)

如您所知，servlet 过滤器可以在处理该 servlet 之前和之后对它们处理的每个 Web 请求进行预处理和后处理。 以类似的方式，您可以在 Spring Web 应用程序中使用`HandlerInterceptor`接口来对由 Spring MVC 处理器处理的 Web 请求进行预处理和后处理。 这些处理器通常用于处理返回/提交的模型属性，并将它们传递给视图/处理器。

## `HandlerInterceptor`接口

处理器拦截器是在 Spring 的 Web 应用程序上下文中配置的，因此它们可以利用任何容器功能，并引用容器中声明的任何 bean。 可以为特定的 URL 映射注册处理器拦截器，因此它仅拦截映射到某些 URL 的请求。

每个处理器拦截器都必须实现`HandlerInterceptor`接口，该接口包含要实现的三种回调方法：`preHandle()`，`postHandle()`和`afterCompletion()`。

*   `preHandle()`：在请求处理器处理请求之前。
*   `postHandle()`：请求处理器处理完请求后。 它提供对返回的`ModelAndView`对象的访问，因此您可以在其中操作模型属性。
*   `afterCompletion()`：在完成所有请求处理之后，即在渲染视图之后。

## `HandlerInterceptorAdapter`类

`HandlerInterceptor`接口的问题在于，无论是否需要，新类都必须实现所有三种方法。 为避免覆盖，可以使用`HandlerInterceptorAdapter`类。 此类实现`HandlerInterceptor`并提供默认的空白实现。

因此，无论您想在处理器中覆盖什么方法，都可以从`HandlerInterceptorAdapter`对其进行扩展。

## `HandlerInterceptor`接口示例

我在这里重用为 [**Spring MVC hello world 应用程序**](https://howtodoinjava.com/spring/spring-mvc/spring-mvc-hello-world-example/) 创建的代码。 我正在创建一个`CustomRequestHandler`类。 此类方法（即`preHandle()`，`postHandle()`和`afterCompletion()`）将按照上述讨论进行调用。

```java
package com.howtodoinjava.demo.handlers;

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 CustomRequestHandler extends HandlerInterceptorAdapter 
{

	public boolean preHandle(HttpServletRequest request,
								HttpServletResponse response, 
								Object handler)
				throws Exception 
	{
		long startTime = System.currentTimeMillis();
        request.setAttribute("startTime", startTime);
        return true;
	}

	public void postHandle( HttpServletRequest request,
							HttpServletResponse response, 
							Object handler, 
							ModelAndView modelAndView) 
				throws Exception 
	{
		long startTime = (Long) request.getAttribute("startTime");
        request.removeAttribute("startTime");

        long endTime = System.currentTimeMillis();
        modelAndView.addObject("totalTime", endTime - startTime);

        System.out.println("Request Prcessing Time :: " + (endTime - startTime));
	}

	public void afterCompletion( HttpServletRequest request,
									HttpServletResponse response, 
									Object handler, 
									Exception exceptionIfAny) 
					throws Exception 
	{
		System.out.println("View Rendered !!");
	}
}

```

现在，创建请求处理器后，必须将其声明为 spring 配置文件，以便 spring 可以在适当的时候将请求传递给它。

处理器拦截器已注册到`DefaultAnnotationHandlerMapping` bean，负责将拦截器应用于标有`@Controller`注解的任何类。 您可以在拦截器属性中指定多个拦截器，其类型为数组。

```java
<bean id="customRequestHandler" class="com.howtodoinjava.demo.handlers.CustomRequestHandler" />

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />

<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
	<property name="interceptors">
		<list>
			<ref bean="customRequestHandler" />
		</list>
	</property>
</bean>

```

现在，当您再次运行 hello world 应用程序时，它将在输出下方显示。

```
Request Prcessing Time :: 15
View Rendered !!
```

## 仅将`HandlerInterceptor`接口应用于某些 URL

好吧，使用上述方法，您的处理器将被应用到应用程序中的所有控制器上，而不管它们映射到什么 URL。 如果您只想将处理器映射到某些 URL，则必须使用`<mvc:interceptors>`标签。

```java
<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/somepath_one/*"/>
        <ref bean="customRequestHandler_one" />
    </mvc:interceptor>
	<mvc:interceptor>
        <mvc:mapping path="/somepath_two/*"/>
        <ref bean="customRequestHandler_two" />
    </mvc:interceptor>
</mvc:interceptors>

```

这就是这个快速提示。

**祝您学习愉快！**