如何在Spring中管理java servlet托管(或DI)?

时间:2013-01-17 07:44:50

标签: java spring tomcat servlets dependency-injection

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

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

<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>

接下来,我在web.xml;

中有我的servlet定义
<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中实现一些接口,保持上面的bean定义在Spring app-context.xml中,然后在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,然后使用web.xml中的HttpRequestHandlerServlet代替当前的servlet。但是我不确定如何实现HttpRequestHandler接口来处理myAbstractServlet中现有的doPost()...

3 个答案:

答案 0 :(得分: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代替Servlet,那么剩下的就是一些“编程柔道”,比如使用Spring utils检索WebApplicationContext并通过“每个名称”从那里获取bean。 Servlet不是由Spring实例化的,因此它无法管理它们。您必须为servlet创建一个基类,并自己管理DI作为初始化步骤。

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

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

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

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

您也可以尝试使用Servlet上的@Configurable注释进行编织,但这可能会或可能不会(我认为Servlet可能会在Spring上下文设置之前初始化,所以它仍然没有可能做到它的神奇之处。

答案 1 :(得分:1)

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

  

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

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

答案 2 :(得分:0)

关于SpringBeanAutowiringSupport,请注意来自javadoc:

注意:如果有一种显式的方式来访问ServletContext,那么更喜欢使用这个类。 WebApplicationContextUtils类允许基于ServletContext轻松访问Spring根Web应用程序上下文。