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
com.gqshao.spring.listener.MyListener
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
MyFilter org.springframework.web.filter.DelegatingFilterProxy targetBeanName myFilter MyFilter /* REQUEST FORWARD
2.applicationContext.xml
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
myServlet com.gqshao.spring.servlet.DelegatingServletProxy myServlet /testservlet
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("Hello World
"); out.flush(); out.close(); } }
4.说明
MyServlet使用Spring ApplicationContext来维护,通过@Component来定义
DelegatingServletProxy 通过web.xml文件中servlet-name中的值在Spring ApplicationContext中查找MyServlet,注意名称一致。