类似第八章的应用,这里也是使用默认连接器,使用Context为其主容器并关联一个Wrapper容器。唯一的区别是在Context类会持有一个StandardManager实例来管理Session对象。我们使用第三个Sevlet SessionServlet来测试这个应用,这个servlet由名这wrapper1的Wrapper容器来表示。
Bootstrap Class
Bootstrap类用来启动应用,在Bootstrap类中创建了一个与Context容器关联的org.apache.catalina.session.StandardManager实例。
在主方法中,首先设置一个名为catalina.base的系统变量,并且初始化连接器
System.setProperty("catalina.base",System.getProperty("user.dir"));
Connector connector = new HttpConnector();
为SessionServlet创建一个Wrapper容器wrapper1
Wrapper wrapper1 = new SimpleWrapper();
wrapper1.setName("Session");
wrapper1.setServletClass("SessionServlet");
然后创建一个StandardContext对象,设置它的path和docBase变量,以及将wrapper添加到Context容器中
Context context = new StandardContext();
// StandardContext's start method adds a default mapper
context.setPath("/myApp");
context.setDocBase("myApp");
context.addChild(wrapper1);
接下来,开始方法中会在Context中添加servlet映射
context.addServletMapping("/myApp/Session", "Session");
像前面章节那样,我们这里的Context容器也需要一个监听器和加载器
LifecycleListener listener = new SimpleContextConfig();
((Lifecycle) context).addLifecycleListener(listener);
// here is our loader
Loader loader = new WebappLoader();
// associate the loader with the Context
context.setLoader(loader);
connector.setContainer(context);
接下来就是本章主要介绍的Manager了,我们将StandardManager实例传递给一个Context容器
// add a Manager
Manager manager = new StandardManager();
context.setManager(manager);
最后,我们初始化并启动连接器,以及启动Context容器
connector.initialize();
((Lifecycle) connector).start();
((Lifecycle) context).start();
SimpleWrapperValve Class
回想本章节的开始部分,我们提起通过调用javax.servlet.http.HttpServletRequest接口的getSession方法可以使一个servlet获取到一个Session。当getSession方法被调用时,请求对象Request必须请求与Context容器的关联的Manager组件。这个Manager会创建一个新Session返回或是直接返回一个已有的。为了使用Request对象能够访问到Manager,那么它就必须能够访问到Context容器。为了实现这个目的,你需要在SimpleWrapperValve类的invoke方法中调用org.apache.catalina.Request接口的setContext方法来传递context容器。SimpleWrapperValve类的invoke方法会调用请求的servlet的service方法,所以你需要在调用service方法之前设置Context。
public void invoke(Request request, Response response,
ValveContext valveContext) throws IOException, ServletException {
SimpleWrapper wrapper = (SimpleWrapper) getContainer();
ServletRequest sreq = request.getRequest();
ServletResponse sres = response.getResponse();
Servlet servlet = null;
HttpServletRequest hreq = null;
if (sreq instanceof HttpServletRequest)
hreq = (HttpServletRequest) sreq;
HttpServletResponse hres = null;
if (sres instanceof HttpServletResponse)
hres = (HttpServletResponse) sres;
// -- new addition -----------------------------------
Context context = (Context) wrapper.getParent();
request.setContext(context);
// -------------------------------------
// Allocate a servlet instance to process this request
try {
servlet = wrapper.allocate();
if (hres != null && hreq != null) {
servlet.service(hreq, hres);
} else {
servlet.service(sreq, sres);
}
} catch (ServletException e) {
}
}
在获取到Wrapper容器之后,你可以调用Wrapper容器的getParent方法来获取一个Context容器。获取到Context容器之后,你就可以调用Http请求对象Request的setContext方法来设置容器。
前面已经解释过,org.apache.catalina.connector.HttpRequestBase类中的私有方法doGetSession就可以调用Context接口中的getManager方法来获取Manager组件
// Return the requested session if it exists and is valid Manager manager = null;
if (context != null)
manager = context.getManager();
获取到Manager组件后,你就可以创建或是使用一个现有的Session对象了。