轉載聲明:本文章轉載自https://sgq0085.iteye.com/blog/2191110
1.背景
ServletContext,是一個全局的儲存信息的空間,服務器開始建立,服務器關閉銷燬。request,每次請求一個;session,一個會話一個;而servletContext,所有用戶共用一個。
ServletContext維護着一個服務器中的一個特定URL名字空間(比如,/myapplication)下的所有Servlet,Filter,JSP,JavaBean等Web部件的集合。
也就是說Servlet和Filter並不是由Spring ApplicationContext維護的,所以使用autowire註解來進行注入會產生問題。
一般都是通過下面這個方法解決
WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(servletContextEvent.getServletContext());
2.準備工作
準備一個由Spring ApplicationContext維護Bean,分別在Listener、Filter和Servlet中調用其中的方法
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component("springBean")
public class SpringBean {
private static final Logger logger = LoggerFactory.getLogger(SpringBean.class);
public void listener() {
logger.info("listener use spring bean");
}
public void servlet() {
logger.info("servlet use spring bean");
}
public void filter() {
logger.info("filter use spring bean");
}
}
2.Listener
1.web.xml
<!-- test listener use spring bean -->
<listener>
<listener-class>com.gqshao.spring.listener.MyListener</listener-class>
</listener>
2.MyListener
package com.gqshao.spring.listener;
import com.gqshao.spring.bean.SpringBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
/**
* 功能說明:測試自定義Listener使用spring使用註解定義的bean
*/
public class MyListener implements ServletContextListener {
private static final Logger logger = LoggerFactory.getLogger(MyListener.class);
@Override
public void contextInitialized(ServletContextEvent event) {
WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
SpringBean bean = (SpringBean) springContext.getBean("springBean");
bean.listener();
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
logger.info("MyListener contextDestroyed");
}
}
3.Filter
針對Filter,Spring提供了DelegatingFilterProxy解決
1.web.xml
<!-- test filter use spring bean -->
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetBeanName</param-name>
<param-value>myFilter</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
2.applicationContext.xml
<bean name="myFilter" class="com.gqshao.spring.filter.MyFilter"/>
3.MyFilter
package com.gqshao.spring.filter;
import com.gqshao.spring.bean.SpringBean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(MyFilter.class);
@Autowired
private SpringBean springBean;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
logger.info("MyFilter init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
springBean.filter();
filterChain.doFilter(request, response);
}
@Override
public void destroy() {
logger.info("MyFilter destroy");
}
}
3.Servlet
Servlet我們仿照Spring對Filter的處理寫一個DelegatingServletProxy這樣的代理Servlet
1.web.xml
<!-- test servlet use spring bean -->
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class>com.gqshao.spring.servlet.DelegatingServletProxy</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myServlet</servlet-name>
<url-pattern>/testservlet</url-pattern>
</servlet-mapping>
2.DelegatingServletProxy
package com.gqshao.spring.servlet;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import javax.servlet.*;
import java.io.IOException;
public class DelegatingServletProxy extends GenericServlet {
private String targetBean;
private Servlet proxy;
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException,
IOException {
proxy.service(request, response);
}
@Override
public void init() throws ServletException {
this.targetBean = getServletName();
setServletBean();
proxy.init(getServletConfig());
}
private void setServletBean() {
WebApplicationContext wac = WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
this.proxy = (Servlet) wac.getBean(targetBean);
}
}
3.MyServlet
package com.gqshao.spring.servlet;
import com.gqshao.spring.bean.SpringBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
@Component
public class MyServlet extends HttpServlet {
@Autowired
private SpringBean springBean;
public void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
springBean.servlet();
PrintWriter out = response.getWriter();
out.println("<h3>Hello World</h3>");
out.flush();
out.close();
}
}
4.說明
MyServlet使用Spring ApplicationContext來維護,通過@Component來定義
DelegatingServletProxy 通過web.xml文件中servlet-name中的值在Spring ApplicationContext中查找MyServlet,注意名稱一致。