How Tomcat Works(八)
下面接着分析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(八)相关推荐
- How Tomcat Works(二十)
要使用一个web应用程序,必须要将表示该应用程序的Context实例部署到一个host实例中.在tomcat中,context实例可以用war文件的形式来部署,也可以将整个web应用拷贝到Tomcat ...
- How Tomcat works — 四、tomcat启动(3)
上一节说到StandardService负责启动其子组件:container和connector,不过注意,是有先后顺序的,先启动container,再启动connector,这一节先来看看conta ...
- 进来在看《How Tomcat Works》这本书,将读书笔记贴在这里,好记性不如烂笔头。
进来在看<How Tomcat Works>这本书,将读书笔记贴在这里,好记性不如烂笔头. 最简单的一个服务器,一个很简单的结果. HttpServer构建ServerSocket,每 ...
- How Tomcat Works(十一)
本文接下来分析tomcat的类载入器,tomcat需要实现一个自定义的载入器,而不能使用系统类载入器 (1)限制serlvet访问当前运行的java虚拟机中环境变量CLASSPATH指明的路径下的所有 ...
- 《How Tomcat Works》读书笔记(二)
<How Tomcat Works>读书笔记(二) 这是<How Tomcat Works>第一二章的读书笔记.第一张主要写了一个静态资源处理的web服务器,第二章加了对ser ...
- 《How Tomcat Works》读书笔记(三)Connector
为什么80%的码农都做不了架构师?>>> 3.1 StringManager 为啥要先讲StringManager呢? 话说tomcat算是一个大型项目了(最新的tomcat7 ...
- how tomcat works
目标 深入剖析tomcat how tomcat works •Java Web 服务性能优化实践2014-11-04阅读225 •How Tomcat work之第十五章之Digester之sett ...
- How Tomcat Works(十三)
本文分析tomcat容器的安全管理,servlet技术支持通过配置部署描述器(web.xml文件)来对受限内容进行访问控制:servlet容器是通过一个名为验证器的阀来支持安全限制的,当servlet ...
- 《How Tomcat Works》读书笔记(三)--Connector(连接器)
<How Tomcat Works>读书笔记(三)--Connector(连接器) 这是<How Tomcat Works>第三四章的读书笔记.主要写了Tomcat4.0默认的 ...
最新文章
- 计算机内存知识txt,计算机新手必备内存实用知识.docx
- 浏览器插件之ActiveX开发(二
- java代码开发规范
- 被尘封的故事技能点bug_新月纪元稳定版下载-新月纪元bug修复版1.0 修复版
- HTML+CSS+JS实现 ❤️创意时间轮盘时钟特效❤️
- LeetCode 154 寻找旋转排序数组中的最小值 II
- 学习笔记之进程管理的相关重要命令
- 有人说苹果手机的CPU非常强大,为什么会这样?苹果cpu又是谁设计的?
- Intel IPP安装和安装测试
- Java调用MQ队列
- syDataProcess项目
- 卷积的发展历程,原理和基于 TensorFlow 的实现
- VSCODE+MINGW配置vulkan开发环境
- C#设置鼠标光标为自定义图片
- #507 Wiggle Sort II
- 易康(eCognition)对象几何特征--2:几何(Geometry)_ 形状(Shape)
- 微信小程序应用安全分析及设计
- JWT授权为啥要在 Authorization标头里加个Bearer 呢
- c4droid入门教程(2022干货)- 手机C4DROID编辑器
- 征途2经典版服务器双线哪个稳定,征途,别毁了自己和曾经的经典
热门文章
- 8.2 matlab曲线对象和曲面对象(曲线对象、曲面对象、光照处理、图形对象的反射特性)
- R语言--查看数据类型+类型判断
- 【R语言-20行代码】牛顿迭代法求伽马函数极大似然估计法的参数估计
- 【r语言】如何将直方图和一条曲线画在一起(叠在一张图上)
- 14.6 设置后台线程
- Idea中类实现Serializable接口 引入 serialVersionUID
- U3D MonoBehaviour
- C#线程--5.0之前时代(一)--- 原理和基本使用
- .NET 基础 一步步 一幕幕 [注释、命名规则、访问修饰符、数据类型、常量、变量]...
- LeetCode - 413. Arithmetic Slices - 含中文题意解释 - O(n) - ( C++ ) - 解题报告