如何用Spring將Service注入到Servlet中(註解模式)





項目背景:由於工作需要,原本需要在Extjs4.2 MVC +DWR3 +Spring3.1 + Hibernate3.3.2下做一個分頁查詢,以Extjs的gridpanel作爲頁面組件,以DWR作爲控制器。然而,在多日翻牆查看英文資料依然未能解決的情況下(諸如各種版本的DWRProxy,ListRange等等),無奈用Servlet代替DWR,將Servlet與Spring進行整合,使Service層能注入到Servlet中,當然,這裏的Servlet是純正的Servlet 3,而不是Struts的ActionServlet或者是SpringMVC啥啥的。


解決方法有兩種(推薦使用第二種)


方法一:


直接重寫Servlet的Init()方法,代碼如下:


public void init(ServletConfig servletConfig) throws ServletException {
ServletContext servletContext = servletConfig.getServletContext();
WebApplicationContext webApplicationContext = WebApplicationContextUtils
.getWebApplicationContext(servletContext);
AutowireCapableBeanFactory autowireCapableBeanFactory = webApplicationContext
.getAutowireCapableBeanFactory();
autowireCapableBeanFactory.configureBean(this, BEAN_NAME);
}


這裏的BEAN_NAME即爲我們需要注入到Spring容器中的服務,但這並不是一個好的方法,因爲我們需要在每一個Servlet中都進行這樣的操作。


方法二:


我們可以寫一個類似於“org.springframework.web.struts.DelegatingRequestProcessor”的委託的Bean,然後通過配置的方法把我們的服務注入到servlet中,具體方法如下,


Step 1:編寫委託類DelegatingServletProxy


package com.telek.pba.base.util;
 
import java.io.IOException;
 
import javax.servlet.GenericServlet;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
 
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
 
 
/**
 * 以下是類似org.springframework.web.struts.DelegatingRequestProcessor的一個委託
 * 用於通過配置的方法,在Servlet中注入Service
 * @author liyinwei
 * 
 */
public class DelegatingServletProxy extends GenericServlet{
 
/**

*/
private static final long serialVersionUID = 1L;
private String targetBean;
private Servlet proxy;
 
@Override
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
proxy.service(req, res);
}
 
/**
* 初始化
*/
public void init() throws ServletException {
this.targetBean = getServletName();
getServletBean();
proxy.init(getServletConfig());
}
 
/**
* 獲取Bean
*/
private void getServletBean() {
WebApplicationContext wac = WebApplicationContextUtils
.getRequiredWebApplicationContext(getServletContext());
this.proxy = (Servlet) wac.getBean(targetBean);
}
 
}


Step 2:修改Web.xml配置


在純Servlet模式下,我們的配置方式如下(以下由於代碼高亮插件的問題,請將代碼中的#替換成尖括號)


<servlet>
  <description>活動發起模塊活動查詢分頁Servlet</description>
  #display-name#launchActivityQueryServlet#/display#
  #servlet-name#LaunchActivityQueryServlet#/servlet-name#
  #servlet-class#com.telek.pba.launch.servlet.LaunchActivityQueryServlet#/servlet-class#
#servlet#
 
#servlet-mapping#
  #servlet-name#LaunchActivityQueryServlet#/servlet-name#
  #url-pattern#/servlet/launch/LaunchActivityQueryServlet#/url-pattern#
#/servlet-mapping#
</servlet>


如果採用我們這種代理的方法,則配置應該修改爲:


<servlet>
  <description>活動發起模塊活動查詢分頁Servlet</description>
  #display-name#launchActivityQueryServlet#/display#
  #servlet-name#launchActivityQueryServlet#/servlet-name#
  #servlet-class#com.telek.pba.base.util.DelegatingServletProxy#/servlet-class#
#servlet#
 
#servlet-mapping#
  #servlet-name#launchActivityQuery#/servlet-name#
  #url-pattern#/servlet/launch/LaunchActivityQueryServlet#/url-pattern#
#/servlet-mapping#
</servlet>


注意:默認情況下,Servlet的配置中,LaunchActivityQuery的首字母一般爲大寫,而我們的標題中已註明,我們採用Spring的註解模式,如果是自動掃描註解的話,默認情況下,註解的value值爲首字母小寫,即:launchActivityQuery,因此,在我們新的配置中,要注意將首字母改爲小寫,否則會報無法找到Bean的錯誤。


Step 3:至此,我們就可以像SSH的注入方式一樣,注入Servlet了,以下是個小示例:


package com.telek.pba.launch.servlet;
 
import java.io.IOException;
 
import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
 
import com.telek.pba.base.model.PbaUserInfo;
import com.telek.pba.launch.dao.IPbaActivityInfoCurrentDAO;
 
@Component
public class LaunchActivityQueryServlet extends HttpServlet {
 
private static final long serialVersionUID = 1L;
 
//注入IPbaActivityInfoCurrentDAO
@Resource
private IPbaActivityInfoCurrentDAO pbaActivityInfoCurrentDAO;
 
 
/**
* Constructor of the object.
*/
public LaunchActivityQueryServlet() {
super();
}
 
/**
* Destruction of the servlet. <br />
*/
public void destroy() {
super.destroy(); // Just puts "destroy" string in log
// Put your code here
}
 
/**
* The doGet method of the servlet. <br />
*
* This method is called when a form has its tag value method equals to get.

* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//sth to do
}
 
/**
* The doPost method of the servlet. <br />
*
* This method is called when a form has its tag value method equals to post.

* @param request the request send by the client to the server
* @param response the response send by the server to the client
* @throws ServletException if an error occurred
* @throws IOException if an error occurred
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//sth to do
}
 
/**
* Initialization of the servlet. <br />
*
* @throws ServletException if an error occurs
*/
public void init() throws ServletException {
// Put your code here
}
 
}


最後,請留心在Spring配置文件中,配置上自動掃描包的路徑:


<context:component -scan base-package="com.telek.pba.*.dao.impl,
  com.telek.pba.*.service.impl,
  com.telek.pba.*.servlet"></context:component>


大功告成!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章