2

我有一个带有一些旧 HTTPServlet 的项目,我想要一种方法来管理 Spring 中 Servlet 的创建/生命周期,这样我就可以做一些事情,比如 DI 并通过 Spring/Hibernate 集成传入数据库对象。

首先,我设置了 Spring 应用程序上下文,web.xml如下所示;

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

接下来我有我的 servlet 定义web.xml

<servlet>
    <servlet-name>oldHttpServlet</servlet-name> 
    <display-name>oldHttpServlet</display-name>
    <servlet-class>com.package.MyServlet</servlet-class>
</servlet>

在我的春天application-context.xml,我想做一些 bean def 如下;

<bean id="oldHttpServlet" class="com.package.MyServlet"></bean>

我认为上面我需要在我的servlet中实现一些接口,在Spring app-context.xml中保留上面的bean定义,然后在web.xml中更改servlet定义......我不确定什么是最简单的更改,因为在 MyServelet.java 端需要担心一些继承,看起来像这样;

class MyServlet extends MyAbstractServlet{
  void doStuff(){
     //YOu know...
  }
}

和 MyAbstractServlet;

class MyAbstractServlet extends HttpServlet{
  doPost(){
     //Some post implementation here...
  }
}

在 Spring 中包装 MyServlet 并从那里加载而不是通过 web.xml 实例化的最佳方法是什么?

我假设最好的方法是使用 Springs HttpRequestHandler,然后使用HttpRequestHandlerServletweb.xml 中的 代替当前的 servlet。但是,我不确定如何实现 HttpRequestHandler 接口以使用 myAbstractServlet 中现有的 doPost() 内容...

4

3 回答 3

5

如果您需要将依赖项注入到 servlet 中,那么我会使用 Spring 的 HttpRequestHandlerServlet。您创建 HttpRequestHandler 的实现(它有一个方法:

public void handleRequest(HttpServletRequest request, HttpServletResponse httpServletResponse) throws ServletException, IOException;

你需要实现的 - 它相当于你在 doGet / doPost 中所拥有的。所有 HttpRequestHandler 实现的实例都应该由 spring 处理(设置一个注释驱动的配置并使用@Component 等注释)或使用 XML 配置来设置这些 bean。

在您的 web.xml 中为 HttpRequestHandlerServlet 创建映射。如果您将 servlet 命名为与 HttpRequestHandler 相同的名称,那么 Spring 将使 HttpRequestHandlerServlet 使用匹配的 HttpRequestHandler 自动处理请求。

由于 HttpRequestHandler 是一个 Spring bean,您可以让 Spring 将您需要的所有服务注入其中。

如果您仍然不想使用 HttpRequestHandler 代替 Servlets,那么剩下的就是一些“编程柔道”,例如使用 Spring utils 检索 WebApplicationContext 并通过“每个名称”从那里获取 bean。Servlet 没有被 Spring 实例化,因此它无法管理它们。您必须为您的 servlet 创建一个基类并自己管理 DI 作为初始化步骤。

代码看起来像这样(在 servlet 内):

WebApplicationContext webContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
CertainBeanClass bean = (CertainBeanClass) webContext.getBean("certainBean");

[编辑] 事实上,正如其中一位评论者所建议的那样,还有一个选择。不过,它仍然需要您在 servlets init 方法中进行手动设置。这是它的样子:

public void init(ServletConfig config) {
    super.init(config);
    SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}

您也可以通过编织在 Servlet 上使用 @Configurable 注释来试试运气,但这可能会或可能不会起作用(我认为 Servlet 可能会在设置 Spring 上下文之前被初始化,所以它仍然没有可能发挥它的魔力) .

于 2013-01-17T08:33:54.117 回答
1

Servlet 的理想用途应该是作为 Controller 和底层容器管理它的生命周期,所以我们不需要 Spring 来管理它的实例

所以我可以做一些像 DI 之类的事情,并通过 Spring/Hibernate 集成传入数据库对象。

您永远不应该在您的 dao/services 中依赖 Servlet,您的 servlet 应该调用非常适合使用 Spring DI 上下文管理的服务

于 2013-01-17T08:17:26.863 回答
0

关于 SpringBeanAutowiringSupport,请注意 javadoc:

注意:如果有访问 ServletContext 的显式方式,则首选这种方式而不是使用此类。WebApplicationContextUtils 类允许基于 ServletContext 轻松访问 Spring 根 Web 应用程序上下文。

于 2013-05-06T18:26:58.290 回答