The Application 应用
这章的应用程序与第八章的相似。它使用默认的连接器并有一个上下文和一个封装作为其容器。唯一区别是这个应用中有一个StandardManager实例来管理会话对象。
The BootStrap类
这一章的BootStrap类与第八章的相似,区别是这一章的BootStrap类创建一个StandardManager类的实例,并将之与Context关联。
其main方法以设置Catalina.base系统属性值和初始化默认连接器开始
System.setProperty("catalina.base",
System.getProperty("user.dir"));
Connector connector = new HttpConnector();
对于这个ServletSession,它创建了一个名叫wrapper1的wrapper‘
Wrapper wrapper1 = new SimpleWrapper();
wrapper1.setName("Session");
wrapper1.setServletclass("SessionServlet");
之后,创建一个StandardContext对象,设置它的路径和docBase属性,并添加wrapper到上下文。
Context context = new StandardContext();
context.setPath( "/myApp");
context.setDocBase("myApp");
context.addChild(wrapper1);
下一步,start方法继续增加一个servlet映射。这个映射不同于第八章的。作为/Session的替换,我们使用/myApp/Session作为替换。这样要求是因为我们设置了context的路径/myApp。这个路径名将用于发送Session cookie,并且浏览器也仅发送cookie返回给服务器,如果路径也被设置为/myApp。
context.addServletMapping("/myApp/Session", "Session");
URL用于请求SessionServlet 如下:
http://localhost:8080/myApp/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。
Manager manager = new StandardManager();
context.setManager(manager);
最后,我们初始化连接器并启动上下文
connector.initialize();
((Lifecycle) connector).start();
((Lifecycle) context).start();
SimpleWrapperValue类
重新回顾这章的开始,我们提到servlet可以通过调用HttpServletRequest接口的getSession方法取得一个Session对象。当getSession方法被调用的时候,Request对象必将在某一时间调用与之context关联的manager。manager要不创建一个新的Session对象,要不返回一个已经存在的Session对象。为了请求对象能够访问manager,它必须能访问context。为了完成这个,在SimpleWrapperValue类的invoke方法中,你调用Request接口的setContext方法,传递context。记住SimpleWrapperValue类的invoke方法调用了请求的servlet的service方法。因此,你必须在servlet的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;
// pass the Context to the Request object so that
// the Request object can call the Manager
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了,这样,你可以通过Container接口的getParaent方法获取上下文了。注意wrapper已经添加到context中了。只有有了context,之后你就能调用Request接口的setContext方法了。
如同开始演示的一样,私有方法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对象,自然的获取一个会话对象或者创建一个新的。
总结
这章讨论了Manager,这个组件在Session管理中管理会话。演示了管理器类型和如何持续化Session对象到一个store中。在这章结尾处,你已经学会了如何构建一个应用,使用一个StandardManager实例来运行servlet,这个servlet使用Session 对象来存储值。