我发现的一个有趣的问题是我经常希望我的 servlet 是 Spring 管理的 bean。这样,它可以完成所有依赖注入等。但通常,您必须在 web.xml 中指定您的 servlet,这意味着您的容器(例如 Tomcat)而不是 Spring 将创建 servlet。
有一种方法可以解决这个问题,使用HttpRequestHandlerServlet。我的 web.xml 文件包括以下几行:
<servlet>
<servlet-name>dataProvider</servlet-name>
<servlet-class>
org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>documentCreator</servlet-name>
<servlet-class>
org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dataProvider</servlet-name>
<url-pattern>/dataProvider/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>documentCreator</servlet-name>
<url-pattern>/documentCreator/*</url-pattern>
</servlet-mapping>
这告诉 Spring 它将使用它的两个 bean 作为 servlet,一个称为 dataProvider,另一个称为 documentCreator。它必须使用 xml 配置文件或注释来确定这些 bean 是什么。我更喜欢注解,例如@Controller。
那么当 Tomcat 收到一个请求时会发生什么,例如 GET /dataProvider/test 从 servlet-mapping 部分,它知道它必须将该请求提供给它创建的第一个 HttpRequestHandlerServlet。该类知道它的名称为 dataProvider,它在 Spring 上下文中查找名为 dataProvider 的 bean。然后它调用该 bean 上的 handleRequest 方法。
我的 DataProvider 类如下所示:
@Controller
public class DataProvider extends HttpServlet implements HttpRequestHandler {
@Autowired
private OtherBeanType otherBean
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
// my doGet method
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
// my doPost method
}
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (request.getMethod().equalsIgnoreCase("GET")) {
doGet(request, response);
} else if (request.getMethod().equalsIgnoreCase("POST")) {
doPost(request, response);
}
}
}
我认为我们需要该 handleRequest() 方法有点不幸(如果您使用 Get 和 Post 以外的任何方法,则需要在其中添加它们)。如果 HttpRequestHandlerServlet 可以为您完成这项工作会更好,但这就是它现在的工作方式。