下面接着分析Context容器,该接口最重要的方法是addWrapper()方法与creatWrapper()方法,添加具体的子容器,这里是Wrapper容器实例

这里要分析的是一个简单的Context容器,它针对特定的客户端请求,通过映射器找到要处理该特定请求的子容器实例(Wrapper)

具体流程是,Context容器首先调用额外的阀,最后调用基础阀(这里是SimpleContextValve),在基础阀里面通过映射器找到要 处理该请求的子容器Wrapper实例,然后再调用子容器Wrapper实例的各个阀(本示例的Wrapper只有基础阀)(类似于composte模式 迭代)

下面是SimpleContext类的实现,SimpleContext实现org.apache.catalina.Context接口和org.apache.catalina.Pipeline接口

public class SimpleContext implements Context, Pipeline {public SimpleContext() {pipeline.setBasic(new SimpleContextValve());}// 子容器名称与子容器实例映射protected HashMap children = new HashMap();protected Loader loader = null;protected SimplePipeline pipeline = new SimplePipeline(this);// servlet模式与子容器名称映射protected HashMap servletMappings = new HashMap();// 映射器protected Mapper mapper = null;// 映射器协议与映射器实例映射protected HashMap mappers = new HashMap();private Container parent = null;/*** 添加servlet模式与子容器名称(wrapper)到HashMap servletMappings容器* @param pattern* @param name*/public void addServletMapping(String pattern, String name) {synchronized (servletMappings) {servletMappings.put(pattern, name);}}    /*** 根据servlet模式找到对应的子容器名称(wrapper)(供映射器调用)* @param pattern* @return*/public String findServletMapping(String pattern) {synchronized (servletMappings) {return ((String) servletMappings.get(pattern));}}/*** 获取加载器* @return*/public Loader getLoader() {if (loader != null)return (loader);if (parent != null)return (parent.getLoader());return (null);}/*** 设置加载器* @param loader*/public void setLoader(Loader loader) {this.loader = loader;}/*** 添加子容器实例(wrapper)名称与子容器实例(wrapper)到HashMap children容器* @param child*/public void addChild(Container child) {child.setParent((Container) this);children.put(child.getName(), child);}/*** 根据名称查找子容器实例wrapper(供映射器调用)* @param name* @return*/public Container findChild(String name) {if (name == null)return (null);synchronized (children) {// Required by post-start changesreturn ((Container) children.get(name));}}/*** 查找子容器数组* @return*/public Container[] findChildren() {synchronized (children) {Container results[] = new Container[children.size()];return ((Container[]) children.values().toArray(results));}}/*** 添加映射器实例* @param mapper*/public void addMapper(Mapper mapper) {// this method is adopted from addMapper in ContainerBase// the first mapper added becomes the default mappermapper.setContainer((Container) this); // May throw IAEthis.mapper = mapper;synchronized (mappers) {if (mappers.get(mapper.getProtocol()) != null)throw new IllegalArgumentException("addMapper:  Protocol '"+ mapper.getProtocol() + "' is not unique");mapper.setContainer((Container) this); // May throw IAE
            mappers.put(mapper.getProtocol(), mapper);if (mappers.size() == 1)this.mapper = mapper;elsethis.mapper = null;}}/*** 根据协议查找映射器实例* @param protocol* @return*/public Mapper findMapper(String protocol) {// the default mapper will always be returned, if any,// regardless the value of protocolif (mapper != null)return (mapper);elsesynchronized (mappers) {return ((Mapper) mappers.get(protocol));}}public Mapper[] findMappers() {return null;}/*** 根据请求找到子容器实例wrapper (供基础阀调用该方法)* @param request* @param update* @return*/public Container map(Request request, boolean update) {// this method is taken from the map method in// org.apache.cataline.core.ContainerBase// the findMapper method always returns the default mapper, if any,// regardless the// request's protocolMapper mapper = findMapper(request.getRequest().getProtocol());if (mapper == null)return (null);// Use this Mapper to perform this mapping// 具体过程 (回调该对象下面方法)// 根据request找到处理该请求的子容器wrapper名称 调用方法 String findServletMapping(String pattern)// 根据上面的子容器wrapper名称找到子容器wrapper 调用方法 Container findChild(String name)return (mapper.map(request, update));}public void invoke(Request request, Response response) throws IOException,ServletException {pipeline.invoke(request, response);}// method implementations of Pipelinepublic Valve getBasic() {return pipeline.getBasic();}public void setBasic(Valve valve) {pipeline.setBasic(valve);}public synchronized void addValve(Valve valve) {pipeline.addValve(valve);}public Valve[] getValves() {return pipeline.getValves();}public void removeValve(Valve valve) {pipeline.removeValve(valve);}}

下面我们来分析映射器SimpleContextMapper的实现

public class SimpleContextMapper implements Mapper {/*** The Container with which this Mapper is associated.*/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) {}/*** Return the child Container that should be used to process this Request,* based upon its characteristics.  If no such child Container can be* identified, return <code>null</code> instead.** @param request Request being processed* @param update Update the Request to reflect the mapping selection?** @exception IllegalArgumentException if the relative portion of the*  path cannot be URL decoded*/public Container map(Request request, boolean update) {// Identify the context-relative URI to be mappedString 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 specificationWrapper wrapper = null;String servletPath = relativeURI;String pathInfo = null;String name = context.findServletMapping(relativeURI);if (name != null)wrapper = (Wrapper) context.findChild(name);return (wrapper);}
}

映射器SimpleContextMapper最重要的方法是Container map(Request request, boolean update)

即根据客户端请求找到对应的子容器实例wrapper,里面关键代码是回调context容器实例的方法(持有对SimpleContext实例的引用)

接下里分析基础阀的关键代码(管道持有对基础阀的引用)

public class SimpleContextValve implements Valve, Contained {protected Container container;public void invoke(Request request, Response response, ValveContext valveContext)throws IOException, ServletException {// Validate the request and response object typesif (!(request.getRequest() instanceof HttpServletRequest) ||!(response.getResponse() instanceof HttpServletResponse)) {return;     // NOTE - Not much else we can do generically
    }// Disallow any direct access to resources under WEB-INF or META-INFHttpServletRequest 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 RequestWrapper 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);}  public Container getContainer() {return container;}public void setContainer(Container container) {this.container = container;}private void badRequest(String requestURI, HttpServletResponse response) {try {response.sendError(HttpServletResponse.SC_BAD_REQUEST, requestURI);}catch (IllegalStateException e) {;}catch (IOException e) {;}}private void notFound(String requestURI, HttpServletResponse response) {try {response.sendError(HttpServletResponse.SC_NOT_FOUND, requestURI);}catch (IllegalStateException e) {;}catch (IOException e) {;}}}

基础阀持有对Context容器实例(SimpleContext)的引用,在它的关键方法void invoke(Request request, Response response, ValveContext valveContext)里面,先调用Context容器实例的Container map(Request request, boolean update)方法获取子容器实例wrapper,最后调用子容器实例wrapper的invoke(Request request, Response response)方法

至于管道类SimplePipeline与上文相同,此处不再描述

---------------------------------------------------------------------------

本系列How Tomcat Works系本人原创

转载请注明出处 博客园 刺猬的温驯

本人邮箱: chenying998179#163.com (#改为@)

本文链接 http://www.cnblogs.com/chenying99/p/3235730.html

转载于:https://www.cnblogs.com/chenying99/p/3235730.html

How Tomcat Works(八)相关推荐

  1. How Tomcat Works(二十)

    要使用一个web应用程序,必须要将表示该应用程序的Context实例部署到一个host实例中.在tomcat中,context实例可以用war文件的形式来部署,也可以将整个web应用拷贝到Tomcat ...

  2. How Tomcat works — 四、tomcat启动(3)

    上一节说到StandardService负责启动其子组件:container和connector,不过注意,是有先后顺序的,先启动container,再启动connector,这一节先来看看conta ...

  3. 进来在看《How Tomcat Works》这本书,将读书笔记贴在这里,好记性不如烂笔头。

    进来在看<How Tomcat Works>这本书,将读书笔记贴在这里,好记性不如烂笔头.  最简单的一个服务器,一个很简单的结果.  HttpServer构建ServerSocket,每 ...

  4. How Tomcat Works(十一)

    本文接下来分析tomcat的类载入器,tomcat需要实现一个自定义的载入器,而不能使用系统类载入器 (1)限制serlvet访问当前运行的java虚拟机中环境变量CLASSPATH指明的路径下的所有 ...

  5. 《How Tomcat Works》读书笔记(二)

    <How Tomcat Works>读书笔记(二) 这是<How Tomcat Works>第一二章的读书笔记.第一张主要写了一个静态资源处理的web服务器,第二章加了对ser ...

  6. 《How Tomcat Works》读书笔记(三)Connector

    为什么80%的码农都做不了架构师?>>>    3.1 StringManager 为啥要先讲StringManager呢? 话说tomcat算是一个大型项目了(最新的tomcat7 ...

  7. how tomcat works

    目标 深入剖析tomcat how tomcat works •Java Web 服务性能优化实践2014-11-04阅读225 •How Tomcat work之第十五章之Digester之sett ...

  8. How Tomcat Works(十三)

    本文分析tomcat容器的安全管理,servlet技术支持通过配置部署描述器(web.xml文件)来对受限内容进行访问控制:servlet容器是通过一个名为验证器的阀来支持安全限制的,当servlet ...

  9. 《How Tomcat Works》读书笔记(三)--Connector(连接器)

    <How Tomcat Works>读书笔记(三)--Connector(连接器) 这是<How Tomcat Works>第三四章的读书笔记.主要写了Tomcat4.0默认的 ...

最新文章

  1. 计算机内存知识txt,计算机新手必备内存实用知识.docx
  2. 浏览器插件之ActiveX开发(二
  3. java代码开发规范
  4. 被尘封的故事技能点bug_新月纪元稳定版下载-新月纪元bug修复版1.0 修复版
  5. HTML+CSS+JS实现 ❤️创意时间轮盘时钟特效❤️
  6. LeetCode 154 寻找旋转排序数组中的最小值 II
  7. 学习笔记之进程管理的相关重要命令
  8. 有人说苹果手机的CPU非常强大,为什么会这样?苹果cpu又是谁设计的?
  9. Intel IPP安装和安装测试
  10. Java调用MQ队列
  11. syDataProcess项目
  12. 卷积的发展历程,原理和基于 TensorFlow 的实现
  13. VSCODE+MINGW配置vulkan开发环境
  14. C#设置鼠标光标为自定义图片
  15. #507 Wiggle Sort II
  16. 易康(eCognition)对象几何特征--2:几何(Geometry)_ 形状(Shape)
  17. 微信小程序应用安全分析及设计
  18. JWT授权为啥要在 Authorization标头里加个Bearer 呢
  19. c4droid入门教程(2022干货)- 手机C4DROID编辑器
  20. 征途2经典版服务器双线哪个稳定,征途,别毁了自己和曾经的经典

热门文章

  1. 8.2 matlab曲线对象和曲面对象(曲线对象、曲面对象、光照处理、图形对象的反射特性)
  2. R语言--查看数据类型+类型判断
  3. 【R语言-20行代码】牛顿迭代法求伽马函数极大似然估计法的参数估计
  4. 【r语言】如何将直方图和一条曲线画在一起(叠在一张图上)
  5. 14.6 设置后台线程
  6. Idea中类实现Serializable接口 引入 serialVersionUID
  7. U3D MonoBehaviour
  8. C#线程--5.0之前时代(一)--- 原理和基本使用
  9. .NET 基础 一步步 一幕幕 [注释、命名规则、访问修饰符、数据类型、常量、变量]...
  10. LeetCode - 413. Arithmetic Slices - 含中文题意解释 - O(n) - ( C++ ) - 解题报告