Coder 爱翻译 How Tomcat Works 第五章 第三部分
The Context Application
这章的第一个应用,你了解了怎么部署一个只有一个wrapper组成的简单的web应用程序。这个应用中只有一个servlet。在一个应用中,只要一个单独的servlet是可能的,但大多数情况下需要更多。在这种情况下,你需要和wrapper相比不同的容器类型。你就需要一个context。
第二个应用程序演示了怎么使用一个有两个wrapper的context,context包装了两个servlet类。当有多于一个wrapper的时候,你就需要用到一个映射器(mapper)。mapper它是一个帮助容器(本例中是context)选择一个子容器来处理特定的请求的组件。
注意一个mapper只能在Tomcat 4中找到,在Tomcat 5中使用另外一种方式找到一个子容器。
mapper是ex05.pyrmont.core.SimpleContextMapper类的实例,它实现org.apache.catalina.Mapper接口。
一个容器也使用多个mapper来支持多协议。这种情况下,一个mapper支持一种请求协议。例如:一个容器可能有一个为HTTP协议的mapper,另外一个是HTTPS协议的mapper。
Listing 5.13: The Mapper interface package org.apache.catalina; public interface Mapper { public Container getContainer(); public void setContainer(Container container); public String getProtocol(); public void setProtocol(String protocol); public Container map(Request request, boolean update);}
The SimpleContext class's invoke method calls the pipeline's invoke method. public void invoke(Request request, Response response) throws IOException, ServletException { pipeline.invoke(request, response); }public void invoke(Request request, Response response) throws IOException, ServletException { // Invoke the first Valve in this pipeline for this request (new SimplePipelineValveContext()).invokeNext(request, response); }// Select the Wrapper to be used for this Request Wrapper wrapper = null; try { wrapper = (Wrapper) context.map(request, true); }wrapper.invoke(request, response);
public void invoke(Request request, Response response) throws IOException, ServletException { pipeline.invoke(request, response); }public void invoke(Request request, Response response,ValveContext valveContext) throws IOException, ServletException { // Validate the request and response object types if (!(request.getRequest() instanceof HttpServletRequest) || !(response.getResponse() instanceof HttpServletResponse)) { return; } // Disallow any direct access to resources under WEB-INF or META-INF HttpServletRequest hreq = (HttpServletRequest) request.getRequest(); String contextPath = hreq.getContextPath(); String requestURI = ((HttpRequest) request).getDecodedRequestURI(); String relativeURI = requestURI.substring(contextPath.length()).toUpperCase(); Context context = (Context) getContainer(); // Select the Wrapper to be used for this Request Wrapper wrapper = null; try { wrapper = (Wrapper) context.map(request, true); }catch (IllegalArgumentException e) { badRequest(requestURI, (HttpServletResponse) response.getResponse()); return; } if (wrapper == null) { notFound(requestURI, (HttpServletResponse) response.getResponse()); return; } // Ask this Wrapper to process this Request response.setContext(context); wrapper.invoke(request, response); } Listing 5.15: The SimpleContextMapper class package ex05.pyrmont.core; import javax.servlet.http.HttpServletRequest; import org.apache.catalina.Container; import org.apache.catalina.HttpRequest; import org.apache.catalina.Mapper; import org.apache.catalina.Request; import org.apache.catalina.Wrapper; public class SimpleContextMapper implements Mapper { private SimpleContext context = null; public Container getContainer() { return (context); } public void setContainer(Container container) { if (!(container instanceof SimpleContext)) throw new IllegalArgumentException ("Illegal type of container"); context = (SimpleContext) container; } public String getProtocol() { return null; } public void setProtocol(String protocol) { } public Container map(Request request, boolean update) { // Identify the context-relative URI to be mapped String contextPath = ((HttpServletRequest) request.getRequest()).getContextPath(); String requestURI = ((HttpRequest) request).getDecodedRequestURI(); String relativeURI = requestURI.substring(contextPath.length()); // Apply the standard request URI mapping rules from // the specification Wrapper wrapper = null; String servletPath = relativeURI; String pathInfo = null; String name = context.findServletMapping(relativeURI); if (name != null) wrapper = (Wrapper) context.findChild(name); return (wrapper);}}Listing 5.16: The Bootstrap2 class package ex05.pyrmont.startup; import ex05.pyrmont.core.SimpleContext; import ex05.pyrmont.core.SimpleContextMapper; import ex05.pyrmont.core.SimpleLoader; import ex05.pyrmont.core.SimpleWrapper; import ex05.pyrmont.valves.ClientIPLoggerValve; import exO5.pyrmont.valves.HeaderLoggerValve; import org.apache.catalina.Connector; import org.apache.catalina.Context; import org.apache.catalina.Loader; import org.apache.catalina.Mapper; import org.apache.catalina.Pipeline; import org.apache.catalina.Valve; import org.apache.catalina Wrapper; import org.apache.catalina.connector.http.HttpConnector; public final class Bootstrap2 { public static void main(String[] args) { HttpConnector connector = new HttpConnector(); Wrapper wrapper1 = new SimpleWrapper(); Wrapper1.setName("Primitive"); wrapper1.setServletClass("PrimitiveServlet"); Wrapper wrapper2 = new SimpleWrapper(); wrapper2.setName("Modern"); wrapper2.setServletClass("ModernServlet"); Context context = new SimpleContext(); context.addChild(wrapper1); context.addChild(wrapper2); Valve valve1 = new HeaderLoggerValve(); Valve valve2 = new ClientIPLoggerValve(); ((Pipeline) context).addValve(valve1); ((Pipeline) context).addValve(valve2); Mapper mapper = new SimpleContextMapper(); mapper.setProtocol("http"); context.addMapper(mapper); Loader loader = new SimpleLoader(); context.setLoader(loader); // context.addServletMapping(pattern, name); context.addServletMapping("/Primitive", "Primitive"); context.addServletMapping("/Modern", "Modern"); connector.setContainer(context); try { connector.initialize(); connector.start(); // make the application wait until we press a key. System.in.read(); } catch (Exception e) { e.printStackTrace(); } } } HttpConnector connector = new HttpConnector(); Wrapper wrapper1 = new SimpleWrapper(); wrapper1.setName("Primitive"); wrapper1.setServletClass("PrimitiveServlet"); Wrapper wrapper2 = new SimpleWrapper(); wrapper2.setName("Modern"); wrapper2.setServletClass("ModernServlet");Context context = new SimpleContext(); context.addChild(wrapper1); context.addChild(wrapper2); Valve valve1 = new HeaderLoggerValve(); Valve valve2 = new ClientIPLoggerValve(); ((Pipeline) context).addValve(valve1); ((Pipeline) context).addValve(valve2);
Mapper mapper = new SimpleContextMapper(); mapper.setProtocol("http"); context.addMapper(mapper);Loader loader = new SimpleLoader(); context.setLoader(loader);
// context.addServletMapping(pattern, name); context.addServletMapping("/Primitive", "Primitive"); context.addServletMapping("/Modern", "Modern");connector.setContainer(context); try { connector.initialize(); connector.start();