如何在servlet取得spring beans
在使用spring容器的web应用中,业务对象间的依赖关系都可以用spring-context.xml文件来配置,并且由spring容器来负责依赖对象的创建。如果要在servlet中使用spring容器管理业务对象,通常需要使用 WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext()) 来获得WebApplicationContext,然后调用WebApplicationContext.getBean("beanName")来获得对象的引用,这实际上是使用了依赖查找来获得对象,并且在servlet代码中硬编码了应用对象的bean名字。
这种方式,相当于把spring容器中的bean加载到了servlet容器中,即把spring中的bean放到web.xml的bean中。
为了能在servlet中感知spring中bean,可采用如下步骤来实现:
1- 将servlet作为bean定义在spring-context.xml文件中,和要应用的bean定义放在一起;
2- 实现一个代理servlet,该servlet用WebApplicationContext来获得在spring-context.xml中定义的servlet的对象,并将任务委托给spring-context.xml中定义的servlet
3- 在web.xml中用ContextLoaderListener来初始化spring 的context,同时在代理servlet的定义中用初始化参数来定义spring-context.xml中servlet的bean名字。
4- 在web.xml中定义代理servlet的mapping.
利用这种方式就将servlet和业务对象的依赖关系用spring 来进行管理,并且不用在servlet中硬编码要引用的对象名字。
示例代码
web.xml
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<!-- 为了让spring加载znserver-servlet之外的配置文件,需定义servlet监听器ContextLoaderListener -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/server-servlet.xml
/WEB-INF/server-bean.xml
</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<!-- 与上面连起来用 ,加载spring容器
把本地java程序不可用的bean和本地可用的分开放在不同配置文件,为了运行本地java程序-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<!-- 处理应用的请求,/app/..下面 -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/server-bean.xml</param-value><!--server-bean.xml中要有URL处理的bean,比如Controller -->
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<!-- 启动InitialServlet,初始化应用和几个重要对象 -->
<servlet>
<description></description>
<display-name>ProxyServlet</display-name>
<servlet-name>proxyServlet</servlet-name>
<servlet-class>org.ccnt.med.common.DelegatingServletProxy</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>proxyServlet</servlet-name>
<url-pattern>/ProxyServlet</url-pattern>
</servlet-mapping>
server-servlet.xml
<bean id="proxyServlet" class="org.ccnt.med.common.ProxyServlet"/>
DelegatingServletProxy.java
public class DelegatingServletProxy extends GenericServlet {
private String targetBean;
private Servlet proxy;
@Override
public void service(ServletRequest arg0, ServletResponse arg1)
throws ServletException, IOException {
proxy.service(arg0, arg1);
}
@Override
public void init() throws ServletException {
this.targetBean = getServletName();
getServletBean();
proxy.init(getServletConfig());
}
private void getServletBean() {
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
this.proxy = (Servlet)wac.getBean(targetBean);//get proxyBean
}
}
ProxyServlet.java
public class ProxyServlet extends HttpServlet{
private Logger logger = LoggerFactory.getLogger(ProxyServlet.class);
@Autowired
private QueryService queryService;
public void setQueryService(QueryService queryService)
{
this.queryService = queryService;
}
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public ProxyServlet() {
super();
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
}
@Override
public void init(ServletConfig config) throws ServletException {
logger.info("~~~START~~~");
}
}
获取ServletContext对象,比如你可以通过重写Servlet的初始化方法init(ServletConfig config), 然后从config中getServletContxt;也可以在处理请求的时候,从Request中getSession().getServletContext()
根据ServletContext,利用Spring的工具类:WebApplicationContextUtils
执行WebApplicationContextUtils.getWebApplicationContext(ServletContext)拿到了ApplicationContext之后,即拿到了Spring的Bean容器,就可以通过容器获取Bean了,比如现在有一个Bean实现了IHello接口,那么可以通过以下代码获取这个IHello的bean实例: IHello hello = applicationContext.getBean(IHello.class);
context.getBean("beanId");