使用 Spring 容器管理 Servlet

 自定义(继承自 javax.servlet.http.HttpServlet)的 Servlet 如何像 Struts1/2 中那样调用 Spring 容器的 service 呢?
        如同 Struts1/2 的配置一样,Spring 在 web.xml 中的配置及其 application*.xml 配置不变:
        web.xml 中:

[html]  view plain  copy
  1. <listener>  
  2.     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
  3. </listener>  


 

[html]  view plain  copy
  1. <context-param>  
  2.     <param-name>contextConfigLocation</param-name>  
  3.     <param-value>/WEB-INF/applicationContext*.xml</param-value>  
  4. </context-param>  



        applicationContext-service.xml 中:

[html]  view plain  copy
  1. <bean id="operationService"  
  2.     class="com.defonds.cds.service.operation.impl.OperationServiceImpl" scope="singleton">  
  3. </bean>  



        如同一般的 Servlet 的配置一样,Servlet 在 web.xml 中的配置不变:

[html]  view plain  copy
  1. <servlet>  
  2.     <servlet-name>downloadServlet</servlet-name>  
  3.     <servlet-class>com.defonds.cds.common.ArcSyncDownloadServlet</servlet-class>  
  4. </servlet>      
  5. <servlet-mapping>  
  6.     <servlet-name>downloadServlet</servlet-name>  
  7.     <url-pattern>/file</url-pattern>  
  8. </servlet-mapping>      



        如同一般的 Struts1/2 的 action 一样注入 service:

[java]  view plain  copy
  1. private OperationService operationService = null;  
  2. public OperationService getOperationService() {  
  3.     return operationService;  
  4. }  
  5.   
  6. public void setOperationService(OperationService operationService) {  
  7.     this.operationService = operationService;  
  8. }  



        在 Servlet 中如同一般的 Struts1/2 的 action 一样调用 service:

[java]  view plain  copy
  1. FileInfo fileInfo = this.getOperationService().getFileByFidAndSecret(Long.parseLong(fileId), secret);  



        唯一需要修改的是 Servlet 的 init 方法:

[java]  view plain  copy
  1. public void init(ServletConfig config) throws ServletException {  
  2.     super.init(config);  
  3.     ServletContext servletContext = this.getServletContext();  
  4.     WebApplicationContext wac = null;   
  5.     wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);  
  6.     this.setOperationService((OperationService) wac.getBean("operationService"));//Spring 配置 中的 bean id  
  7. }     



 Servlet 可否也能像 Struts1/2 的 action 那样作为一个 javaBean 在 Spring 容器里进行管理呢?答案是肯定的。
        自定义(继承自 javax.servlet.http.HttpServlet)的 Servlet 如何像 Struts1/2 中那样调用 Spring 容器的 service 呢?《Servlet 调用 Spring 容器的 service》一文很好地解决了这个问题。美中不足的是,ArcSyncDownloadServlet 在得到其注入的 bean 时,需要显式地写出 bean 在 Spring 配置中的 id 才可以:

[java]  view plain  copy
  1. this.setOperationService((OperationService) wac.getBean("operationService"));//Spring 配置 中的 bean id     



        这样子违背了 Spring 依赖注入的思想。那么如何才可以不在代码中显式调用这个 bean id,而把 bean id 直接写在配置文件中呢?
        本文用一个项目中使用的例子介绍了将 Servlet 和业务对象的依赖关系使用 Spring 来管理,而不用再在 Servlet 中硬编码要引用对象的名字。
        仍然使用《Servlet 调用 Spring 容器的 service》一文中的例子。
        与《Servlet 调用 Spring 容器的 service》的做法相反,web.xml 和 Spring 的 application*.xml 配置需要改变,而 Servlet 不需要做改变。
        如同 Struts1/2 的配置一样,Spring 在 web.xml 中的配置:

[html]  view plain  copy
  1. <listener>  
  2.     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>  
  3. </listener>  
  4. <context-param>  
  5.     <param-name>contextConfigLocation</param-name>  
  6.     <param-value>/WEB-INF/applicationContext*.xml</param-value>  
  7. </context-param>  



        如同 Struts1/2 的配置一样,Spring 在 applicationContext-service.xml 中定义我们的业务逻辑处理类:

[html]  view plain  copy
  1. <bean id="operationService"  
  2.     class="com.defonds.cds.service.operation.impl.OperationServiceImpl" scope="singleton">  
  3. </bean>  



        如同一般的 Struts1/2 的 action 一样在我们的 Servlet 中注入 service:

[java]  view plain  copy
  1. private OperationService operationService = null;  
  2. public OperationService getOperationService() {  
  3.     return operationService;  
  4. }  
  5.   
  6. public void setOperationService(OperationService operationService) {  
  7.     this.operationService = operationService;  
  8. }  



        在 Servlet 中如同一般的 Struts1/2 的 action 一样调用 service:

[java]  view plain  copy
  1. FileInfo fileInfo = this.getOperationService().getFileByFidAndSecret(Long.parseLong(fileId), secret);  



        如同一般的 Servlet 我们的这个 Servlet 需要继承 GenericServlet 或者 HttpServlet:

[java]  view plain  copy
  1. public class ArcSyncDownloadServlet extends HttpServlet  



        无须重写Servlet 的 init 方法,当然如果读者的业务需求需要的话除外。
        新建一个 Servlet 代理类,这个类类似于 DelegatingFilterProxy 那样的代理,通过代理根据配置来找到实际的 Servlet,完成业务逻辑功能。

[java]  view plain  copy
  1. package com.defonds.cds.common;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.Servlet;  
  6. import javax.servlet.ServletContext;  
  7. import javax.servlet.ServletException;  
  8. import javax.servlet.http.HttpServlet;  
  9. import javax.servlet.http.HttpServletRequest;  
  10. import javax.servlet.http.HttpServletResponse;  
  11.   
  12. import org.springframework.web.context.WebApplicationContext;  
  13. import org.springframework.web.context.support.WebApplicationContextUtils;  
  14.   
  15. public class DelegatingServletProxy extends HttpServlet {  
  16.     private static final long serialVersionUID = 1L;  
  17.     private String targetServletBean;  
  18.     private Servlet proxy;  
  19.       
  20.     @Override  
  21.     public void init() throws ServletException {  
  22.         this.targetServletBean = this.getInitParameter("targetServletBean");  
  23.         this.getServletBean();  
  24.         this.proxy.init(this.getServletConfig());  
  25.     }  
  26.   
  27.     @Override  
  28.     protected void service(HttpServletRequest request, HttpServletResponse response)  
  29.             throws ServletException, IOException {  
  30.         proxy.service(request,response);   
  31.     }  
  32.   
  33.     private void getServletBean(){  
  34.         ServletContext servletContext = this.getServletContext();  
  35.         WebApplicationContext wac = null;   
  36.         wac = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);  
  37.         this.proxy = (Servlet) wac.getBean(targetServletBean);  
  38.     }  
  39. }  


 

        不同于一般的 Servlet 在 web.xml 中的配置,需要配置的是 Servlet 代理类,而非 Servlet:

[html]  view plain  copy
  1. <servlet>  
  2.     <servlet-name>proxyDownloadServletBean</servlet-name>  
  3.     <servlet-class>com.defonds.cds.common.DelegatingServletProxy</servlet-class>  
  4.     <init-param>  
  5.         <param-name>targetServletBean</param-name>  
  6.         <param-value>downLoadServletBean</param-value>  
  7.     </init-param>  
  8. </servlet>      
  9. <servlet-mapping>  
  10.     <servlet-name>proxyDownloadServletBean</servlet-name>  
  11.     <url-pattern>/file</url-pattern>  
  12. </servlet-mapping>  



        最后在 applicationContext-service.xml 中将 Servlet 及其业务对象的依赖关系配置到 Spring 容器管理:

[html]  view plain  copy
  1. <bean id="downLoadServletBean" class="com.defonds.cds.common.ArcSyncDownloadServlet">  
  2.     <property name="operationService">  
  3.         <ref bean="operationService"/>  
  4.     </property>  
  5. </bean>     



        注意这里的 downLoadServletBean 要和 web.xml 配置的 downLoadServletBean 对应,operationService 要和 Servlet 中 get/set 得到的 operationService bean 对应。
        如果是多个 Servlet 的话,可以共用同一个代理 Servlet。Servlet 代码和代理 Servlet 代码无须改变,只需要注意一下在 web.xml 里的配置即可:

[html]  view plain  copy
  1. <servlet>  
  2.     <servlet-name>proxyDownloadServletBean</servlet-name>  
  3.     <servlet-class>com.defonds.cds.service.operation.servlet.DelegatingServletProxy</servlet-class>  
  4.     <init-param>  
  5.         <param-name>targetServletBean</param-name>  
  6.         <param-value>downLoadServletBean</param-value>  
  7.     </init-param>  
  8. </servlet>      
  9. <servlet-mapping>  
  10.     <servlet-name>proxyDownloadServletBean</servlet-name>  
  11.     <url-pattern>/file</url-pattern>  
  12. </servlet-mapping>      
  13.   
  14. <servlet>  
  15.     <servlet-name>proxyWebServiceServletBean</servlet-name>  
  16.     <servlet-class>com.defonds.cds.service.operation.servlet.DelegatingServletProxy</servlet-class>  
  17.     <init-param>  
  18.         <param-name>targetServletBean</param-name>  
  19.         <param-value>webServiceServletBean</param-value>  
  20.     </init-param>  
  21. </servlet>      
  22. <servlet-mapping>  
  23.     <servlet-name>proxyWebServiceServletBean</servlet-name>  
  24.     <url-pattern>/WebService</url-pattern>  
  25. </servlet-mapping>      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值