
2一个简单的Servlet容器.ppt
19页一个简单的Servlet容器贝毅君 浙江大学软件学院Servletn一个简单的Servlet容器n外观模式优化Servlet容器ServletServlet是一种服务器端的Java应用程序,具有独立于平台和协议的特性,可以生成动态的Web页面 它担当客户请求(Web浏览器或其他HTTP客户程序)与服务器响应(HTTP服务器上的数据库或应用程序)的中间层 Servlet是位于Web 服务器内部的服务器端的Java应用程序,与传统的从命令行启动的Java应用程序不同,Servlet由Web服务器进行加载,该Web服务器必须包含支持Servlet的Java虚拟机npublic void init(ServletConfig config) throws ServletException;npublic void service(ServletRequest request, ServletResponse response) throws ServletExcetion, IOException;npublic void destroy();npublic void ServletConfig getServletConfig();npublic String getServletInfo();n上述5个是Servlet接口中声明的5个方法,其中init(), service()和destroy()方法和servlet生命周期相关。
Servlet生命周期当实例化某个servlet类后,servlet会调用其init()方法将其初始化Servlet容器只会调用该方法一次Servlet接受任何请求之前,必须要经过争取的初始化当servlet的一个客户端请求到达后,servlet容器会调用相应servlet的service()方法,并将servletRequest和servletResponse作为参数传入在Servlet对象的整个生命周期里面,service()方法会被多次调用在将Service实例从服务中移除前, servlet容器会调用destroy()方法一般当servlet容器关闭或servlet容器要释放内存时, 才会将servlet实例移除Servlet生命周期Servlet实例PrimitiveServletpublic class PrimitiveServlet implements Servlet{ public void init(ServletConfig config) throws ServletException{ System.out.println(“init”); } public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException{ System.out.println(“from service”); PrintWriter out = response.getWriter(); out.println(“Hello. Roses are red.”); out.print(“Violets are blue.”); } public void destroy(){ System.out.println(“destroy”); } public void String getServletInfo(){ return null; } public void ServletConfig getServletConfig(){ return null; } }Servlet示例demonPrimitiveServlet在每个方法内部增加后台打印,利用打印的后台信息可以跟踪servlet的生命周期调用。
n本章实现的servlet容器仅仅用到了service()方法,验证生命周期的输出推荐使用完整的tomcat运行一个简单的servlet容器改造HttpServern仅仅需要改造HttpServer中await()方法 nresponse.sendStaticResource(); 替换为下述代码:if (request.getUri().startsWith(“/servlet/“)) {ServletProcessor1 processor = new ServletProcessor1();processor.process(request, response);}else {StaticResourceProcessor processor = new StaticResourceProcessor();processor.process(request, response);}Url类型为 http://XXX/servlet/xxx 为访问servlet, 不带/servelt/路径访问静态资源n因为servlet的service方法会从servlet容器中接受一个ServletRequest实例和一个ServletResponse实例。
因此它们必须作为参数传入的 servlet的service()方法中nRequest需要实现ServletRequest接口nReponse也需要实现ServletResponse接口改造Request和ResponseServletProcessorStaticResourceProcessor类用于处理对静态资源的请求,process过程仅仅重新调用response.sendResource方法ServletProcessor类对servlet资源进行http请求下述为没有补货异常的process过程代码String uri = request.getUri();String servletName = uri.substring(uri.lastIndexOf(“/“) + 1);URL[] urls = new URL[1];URLStreamHandler streamHandler = null;File classPath = new File(Constants.WEB_ROOT);// 类载入器查找目录称为 仓库String repository = (new URL(“file“, null, classPath.getCanonicalPath() + File.separator)).toString() ;urls[0] = new URL(null, repository, streamHandler);//类载入器URLClassLoader loader = new URLClassLoader(urls); Class myClass = loader.loadClass(servletName); // 实例化servlet对象并调用service()方法Servlet servlet = (Servlet) myClass.newInstance();servlet.service((ServletRequest) request, (ServletResponse) response);为什么需要 URLStreamHandl er对象?这里存在什么问题 ?n通过java –classpath ./lib/servlet.jar; ./ ex02.pyrmont.HttpServlet1 可以执行该容器,然后可以测 试应用程序。
n浏览器输入 http://localhost:8080/servlet/PrimitiveServlet 的时候可以看到浏览器仅仅输出Hello. Rose are red, 为什 么?一个简单的servlet容器servlet = (Servlet) myClass.newInstance(); servlet.service((ServletRequest) request, (ServletResponse) response);n在service方法里面,程序员可以通过向下转型获取自定义的Request 和Reponse实例并调用其公共方法parse()或sendStaticResource() 如果将公共方法设置为私有方法,在service内部实际上还是可以直 接调用的,而且它们不能被其它类调用,所以该方法不好nProtect方法也有service直接调用的问题,所以也并不完美n在这里有个完美的解决方案: 外观模式外观模式n外观模式定义了一个高层的接口,让子系统更加容易使用n外观不只是简化了接口,也将客户从组件的子系统中解耦nTomcat利用RequestFacade封装Request接口的属性方法,将ServletRequest方法排除。
外观模式RequestFacadepublic class RequestFacade implements ServletRequest {private ServletRequest request = null;public RequestFacade(Request request) {this.request = request;} public Object getAttribute(String attribute) {return request.getAttribute(attribute);}public Enumeration getAttributeNames() {return request.getAttributeNames();} // 构建返回request的方法 request.getXXXXX();…… }n改造结果改造servletProcessorservlet = (Servlet) myClass.newInstance();servlet.service((ServletRequest) request, (ServletResponse) response);servlet = (Servlet) myClass.newInstance();RequestFacade requestFacade = new RequestFacade(request);ResponseFacade reponseFacade = new ResponseFacade(response);servlet.service((ServletRequest) requestFacade , (ServletResponse) reponseFacade );n如何改造?运行结果运行结果n本章的Servlet容器既可以处理静态资源请 求,也可以处理简单的Servlet请求。
nServlet接口以及相关背景知识n外观模式及其应用总结。
