我有一个带有一些旧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-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()...
答案 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应用程序上下文。