# 7.1.2　添加其他的 Servlet 和 Filter

按照 AbstractAnnotationConfigDispatcherServletInitializer 的定义，它会创建 DispatcherServlet 和 ContextLoaderListener。但是，如果你想注册其他的 Servlet、 Filter 或 Listener 的话，那该怎么办呢？

基于 Java 的初始化器（initializer）的一个好处就在于我们可以定义任意数量的初始化器类。因此，如果我们想往 Web 容器中注册其他组件的话，只需创建一个新的初始化器就可以了。最简单的方式就是实现 Spring 的 WebApplicationInitializer 接口。

例如，如下的程序清单展现了如何创建 WebApplicationInitializer 实现并注册一个 Servlet。

{% code title="程序清单 7.1　通过实现 WebApplicationInitializer 来注册 Servlet" %}

```java
package com.myapp.config;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;
import org.springframework.web.WebApplicationInitializer;
import com.myapp.MyServlet;

public class MyServletInitializer extends WebApplicationInitializer {
  
  @Override
  public void onStartup(ServletContext servletContext) throws ServletException {
    Dynamic myServlet = servlectContext.addServlet("myServlet", MyServlet.class);
    
    myServlect.addMapping("/custom/**");
  }

}
```

{% endcode %}

程序清单 7.1 是相当基础的 Servlet 注册初始化器类。它注册了一个 Servlet 并将其映射到一个路径上。我们也可以通过这种方式来手动注册 Dispatcher-Servlet。（但这并没有必要，因为AbstractAnnotationConfigDispatcher-ServletInitializer 没用太多代码就将这项任务完成得很漂亮。）

类似地，我们还可以创建新的 WebApplicationInitializer 实现来注册 Listener 和 Filter。例如，如下的程序清单展现了如何注册 Filter。

```java
@Override
public void onStartup(ServlectContext servletContext) throws ServletException {

  javax.servlet.FilterRegistration.Dynamic filter = servletContext.addFilter("myFilter", MyFilter.class);
  
  filter.addMappingForUrlPatterns(null, false, "/custom/**");
} 
```

如果要将应用部署到支持 Servlet 3.0 的容器中，那么 WebApplicationInitializer 提供了一种通用的方式，实现在 Java 中注册 Servlet、Filter 和 Listener。不过，如果你只是注册 Filter， 并且该 Filter 只会映射到 DispatcherServlet 上的话，那么在 AbstractAnnotationConfigDispatcherServletInitializer 中还有一种快捷方式。

为了注册 Filter 并将其映射到 DispatcherServlet，所需要做的仅仅是重载 AbstractAnnotationConfigDispatcherServletInitializer 的 getServletFilters() 方法。例如，在如下的代码中，重载了 AbstractAnnotationConfigDispatcher-ServletInitializer 的 getServletFilters() 方法以注册 Filter：

```java
@Override
protected Filter() getServletFilters() {
  return new Filter[] { new MyFilter() };
}
```

我们可以看到，这个方法返回的是一个 javax.servlet.Filter 的数组。在这里它只返回了一个 Filter，但它实际上可以返回任意数量的 Filter。在这里没有必要声明它的映射路径，getServletFilters() 方法返回的所有 Filter 都会映射到 DispatcherServlet 上。

如果要将应用部署到 Servlet 3.0 容器中，那么 Spring 提供了多种方式来注册 Servlet（包括 DispatcherServlet）、Filter 和 Listener，而不必创建 web.xml 文件。但是，如果你不想采取以上所述方案的话，也是可以的。假设你需要将应用部署到不支持 Servlet 3.0 的容器中（或者你只是希望使用 web.xml 文件），那么我们完全可以按照传统的方式，通过 web.xml 配置 Spring MVC。让我们看一下该怎么做。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://potoyang.gitbook.io/spring-in-action-v4/di-7-zhang-spring-mvc-de-gao-ji-ji-shu/untitled-5/untitled-1.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
