# Spring 拦截器

> 原文： [https://javatutorial.net/interceptors-in-spring](https://javatutorial.net/interceptors-in-spring)

顾名思义，在 Spring，拦截器拦截我们通过实现`HandlerInterceptor`接口来请求。 它为我们提供了一些方法，使我们能够拦截控制器类正在处理的传入请求或控制器类已经处理的响应。

![java-featured-image](img/e0db051dedc1179e7424b6d998a6a772.jpg)

接口提供给我们的方法有：

1.  `preHandle()` – 返回`true`或`false`。 如果返回`true`，则处理程序执行链继续，否则停止。
2.  `postHandle()` – 处理程序执行后调用。
3.  `afterCompletion()` – 在请求完成并生成视图之后调用。

### `HandlerInterceptor`与`HandlerInterceptorAdapter`

首先，我说过我们需要实现`HandlerInterceptor`接口，但是我们也可以实现`HandlerInterceptorAdapter`。 它们之间有 1 个区别，就是`HandlerInterceptor`我们必须覆盖我上面提到的所有三种方法，而`HandlerInterceptorAdapter`允许我们仅覆盖所需的方法。

### 代码实现

通常，这 3 种方法的工作流程会引发`Exception`或返回`true`。

```java
@Component
public class EmployeeInterceptor implements HandlerInterceptor {
   @Override
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler) throws Exception {
	   // Basic validation of password and username
	   String username = request.getParameter("username");
	   String password = request.getParameter("password");

	   if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
	      // throw the exception
		  throw new Exception("Empty username or password.");
	   }

	   // if no exception has been thrown, return true
	   return true;
	}

	@Override
	public boolean postHandle(HttpServletRequest request, HttpServletResponse response,Object handler, ModelAndView modelAndView) throws Exception {
	   log.info(request);
	   return true;
    }				

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response,
									Object handler, Exception exc) throws Exception {
	   if (exc != null) 
	      exc.printStackTrace();
	   else
          log.info("Request: " + request + " / Exception: " + exc); 
	}
}
```

让我们分解上面的代码示例。

首先我们创建我们的类并实现`HandlerInterceptor`，因为它会覆盖所有三个方法。 按照惯例，类名必须在初始名称之后具有`Interceptor`。 然后，我们重写`preHandle()`方法。 它包含 3 个参数 - 请求，响应和处理程序，并且不要忘记`throws Exception`。

### `preHandle()`

我的`preHandle()`方法非常简单–它从请求中获取用户名和密码，然后检查它们是否为空以及是否为空，然后抛出异常，指出“空用户名或密码”。 如果它们不为空，则返回`true`。 在正常环境中，您当然会做更多的验证，但是为了简单起见，我这样做了。

### `postHandle()`

如果没有引发异常并记录请求，我的`postHandle()`方法从返回`true`不会起到什么作用。 它包含 4 个参数 - 请求，响应，处理程序和`modelAndView`。 它还`throws Exception`。通常，此方法用于修改`ModelAndView`（通常通过添加其他属性）或简单地确定处理程序方法处理客户请求所花费的时间。

### `afterCompletion()`

我的`afterCompletion()`方法记录了请求和异常，但是在此之前，它通过说`exc != null`来检查是否有异常，如果存在，那么我们说`exc.printStackTrace()`。

### 配置

我们的拦截器尚未添加到 Spring 配置中。 要添加它，我们必须实现一个自定义`@Configuration`文件，该文件扩展了`WebMvcConfigurerAdapter`，该文件在`addInterceptors`方法内添加了拦截器。

```java
@Configuration
public class AppConfig extends WebMvcConfigurerAdapter {
   @Override
   public void addInterceptors(InterceptorRegistry registry) {
      registry.addInterceptor(new EmployeeInterceptor()).addPathPatterns("/account/signin/process");
   }
}
```

另外，请记住，您必须在`addInterceptors`方法中指定适当的路径模式。