服务热线:13616026886

技术文档 欢迎使用技术文档,我们为你提供从新手到专业开发者的所有资源,你也可以通过它日益精进

位置:首页 > 技术文档 > JAVA > 新手入门 > 基础入门 > 查看文档

servlet 容器的工作原理 ( 四 )


  application 2
  第一个应用程序里存在一个值得注意的问题。 在servletprocessor1 类的 process 方法里,上溯 (upcast)ex02.pyrmont.request 实例到 javax.servlet.servletrequest,将其作为第一个参数传递给 servlet 的 service 方法。 另上溯(upcast) ex02.pyrmont.response 实例到 javax.servlet.servletresponse ,并将其作为第二个参数传递给 servlet 的 service 方法。
  
  try {
    servlet = (servlet) myclass.newinstance();
    servlet.service((servletrequest) request, (servletresponse) response);
  }
  
  这样会使安全性能大打折扣。 知道 servlet 容器工作原理的程序员可以将 servletrequest 和 servletresponse 实例向下转型 (downcast) 到request 和 response ,并调用它们的 public 方法。 request 实例能调用它的 parse 方法; request 实例能调用它的 sendstaticresource 方法。
  
  可以将 parse 和 sendstaticresource 方法设为 private,因为在 ex02.pyrmont 里将会从其他类里调用它们。 然而,这两个方法在 servlet 内应该是不可用的。 一个解决方法是:给 request 和 response 类一个默认的访问修饰符,以致他们在 ex02.pyrmont 外不能被使用。 但还有一个更好的解决方法: 使用 facade 类。
  
  在第二个应用程序内,添加两个 facade 类:requestfacade 和 responsefacade。 requestfacade 类实现 servletrequest 接口,并通过传递 request 实例来实例化, request 实例将在 servletrequest 对象的构建器里被引用 。 servletrequest 对象本身是 private 类型的,不能在类之外访问。 就构建 requestfacade 对象,并将其传递给 service 方法,而不上溯 (upcast) request 对象给 servletrequest,并将其传递给 service 方法。 servlet 程序员仍旧可以向下转型 (downcast) servletrequest 到 requestfacade,但是,只要访问 servletrequest 接口的可用方法就可以了。 现在,parseuri 就安全了。
  listing 2.5 显示 requestfacade 类部分代码:
  listing 2.5. requestfacade 类
  package ex02.pyrmont;
  
  public class requestfacade implements servletrequest {
    private servletrequest request = null;
  
    public requestfacade(request request) {
      this.request = request;
    }
  
    /* implementation of the servletrequest*/
    public object getattribute(string attribute) {
      return request.getattribute(attribute);
    }
  
    public enumeration getattributenames() {
      return request.getattributenames();
    }
  
    ...
  }
  注意 requestfacade 构造函数。 它会接受一个 request 对象,即刻分配给私有的 servletrequest 对象引用。 还要注意,requestfacade 内的每个方法调用 servletrequest 对象内相应的方法。
  
  responsefacade 类也是如此。
  
  以下是 application 2 所包含的类 httpserver2
  request
  response
  staticresourceprocessor
  servletprocessor2
  constants
  httpserver2 类类似于 httpserver1,只是它在 await 方法内使用了 servletprocessor2 而不是servletprocessor1。
  
  if (request.geturi().startswith("/servlet/")) {
    servletprocessor2 processor = new servletprocessor2();
    processor.process(request, response);
  }
  else {
    ...
  }
  servletprocessor2 类也类似于 servletprocessor1,只是在以下 process 方法的部分代码有点不同:
  
  servlet servlet = null;
  requestfacade requestfacade  = new requestfacade(request);
  responsefacade responsefacade = new responsefacade(response);
  
  try {
    servlet = (servlet) myclass.newinstance();
    servlet.service((servletrequest) requestfacade,
      (servletresponse) responsefacade);
  }
  
  编译并运行该应用程序 
  如果要编译该应用程序,在工作目录下键入以下命令:
  javac -d . -classpath ./lib/servlet.jar src/ex02/pyrmont/*.java
  如果要在 windows 下运行该应用程序,在工作目录下键入以下命令:
  java -classpath ./lib/servlet.jar;./ ex02.pyrmont.httpserver2
  在 linux 环境下,使用分号来隔开类库:
  java -classpath ./lib/servlet.jar:./ ex02.pyrmont.httpserver2
  您可以使用和 application 1 相同的 url 以收到同样的结果。
  
  总结
  本文讨论了简单的能够用于服务静态资源,以及处理如 primitiveservlet 一样简单的 servlet 的 servlet 容器。 同时也提供 javax.servlet.servlet 的背景信息。

扫描关注微信公众号