一、Servlet容器
Servlet的整个生命周期好象都是由Servlet容器来处理的。
如果把它硬放到Spring容器中去创建,Servlet对象是可被Spring容器建出来,但Servlet容器可能跟本就不知此Servlet存在,因不在它的容器中。
所以,servlet交给web server来管理,不要交给spring管理。
二、让Servlet context 加载 spring context,servlet使用spring context中的对象/bean
在使用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
为了能在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
contextConfigLocation /WEB-INF/server-servlet.xml /WEB-INF/server-bean.xml org.springframework.web.context.ContextLoaderListener appServlet org.springframework.web.servlet.DispatcherServlet contextConfigLocation /WEB-INF/server-bean.xml 1 appServlet / ProxyServlet proxyServlet org.ccnt.med.common.DelegatingServletProxy 2 proxyServlet /ProxyServlet
server-servlet.xml
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~~~"); } }
五、总结
到这都配置好了,可以放心得使用spring mvc了。回忆下流程:
1、web.xml中设置spring的listener,导入spring-context.xml。
配置DelegatingServletProxy servlet
2、spring-context.xml中配置bean proxyServlet
3、DelegatingServletProxy.java中,设置代理servlet--proxyServlet