How Tomcat works 4-5: Container

本文详细解析了Tomcat容器的内部结构,包括Engine、Host、Context和Wrapper等关键概念,探讨了它们之间的关系及如何通过Pipeline机制执行请求处理流程。同时,介绍了自定义Valve实现特定功能的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. Container概述

(1)主要包含四种:Engine:整个catalina servlet容器, Host:一个虚拟主机包含多个context容器, Context:一个web应用容器,包含一道多个Wrapper容器, Wrapper:独立servlet容器

(2)UML图

(3)添加/移除/查找子容器:

container.addChild(container) -> container.removeChild(container)->container.findChild(name)->Container[] container.findChildren

(4)包含组件:Loader/Logger/Manager/Realm

  1. Pipeline任务:

Tomcat启动时通过读取server.xml的配置决定使用哪个容器来执行,其中原理运用pipeline技术

  1. pipeline任务重要的四个接口:pipeline/valve/valveContext/Contained

  1. Pipeline interface code:
    public interface Pipeline {
    Valve getBasic();
    
    void setBasic(Valve basic);
    
    void addValves(Valve valve);
    
    Valve[] getValves();
    
    void removeValves();
    
    void invoke(Request request, Response response) throws IOException,ServletException;
    
    }

     

 

  1. Valve interface code:
public interface Valve {

String getInfo();

void invoke(Request request, Response response, VavleContext context) throws IOException, ServletException;

}

 

  1. ValveContext interface code:
public interface ValveContext {

String getInfo();

void invokeNext(Request request, Response response) throws IOException, ServletException;

}

 

 

  1. Wrapper接口:

(1)wrapper的实现类作用:

用于管理独立servlet类的lifecycle,调用servlet的init, destroy, service方法。wrapper处于容器层次底部,不能添加子容器

(2)重要方法

public interface Wrapper {

Servlet allocate() throws ServletException; // 是否实现SingleThreadModel

void load() throws ServletException; // 加载和初始化servlet实例

}

 

  1. Wrapper容器应用实例:

业务流程图:

(1)UML结构图

(2)SimpleWrapperLoader code:

public class SimpleWrapperLoader implements Loader{

URLClassLoader loader = null;

Container container = null;

public SimpleWrapperLoader() {

// 实现URL class loader

try {

URL[] urls = new URL[1];

URLStreamHandler streamHandler = null;

File classPath = new File(Constants.WEB_SERVLET_ROOT);



// 从org.apache.catalina.loader.StandardClassLoader/startup.ClassLoaderFactory中获取该code

String repository = (new URL("file", null, classPath.getCanonicalPath()+File.separator)).toString();

urls[0] = new URL(null, repository, streamHandler);

loader = new URLClassLoader(urls);                        

}catch (IOException e) {

System.out.println(e.toString());

}

}

(3)SimplePipeline code:

package com.cisco.tomcat.container;



import java.io.IOException;

import javax.servlet.ServletException;

import org.apache.catalina.Container;

import org.apache.catalina.connector.Request;

import org.apache.catalina.connector.Response;



public class SimplePipeline implements Pipeline {

Valve basic;

Valve[] valves;

Container container;



public SimplePipeline(Container container) {

this.container = container;

}



@Override

public Valve getBasic() {

return basic;

}



@Override

public void setBasic(Valve basic) {

this.basic = basic;

((Contained)basic).setContainer(container);

}



@Override

public void addValves(Valve valve) {

if(valve instanceof Contained) {

((Contained)valve).setContainer(container);

}

synchronized (valves) {

Valve results[] = new Valve[valves.length+1];

System.arraycopy(valves,0, results, 0, valves.length);

results[valves.length] = valve;

valves = results;

}



}



@Override

public Valve[] getValves() {

return valves;

}



@Override

public void removeValves() {                

}



@Override

public void invoke(Request request, Response response) throws IOException, ServletException {

// 调用内部类的StandardValveContext的invokeNext方法,内部会调用每个valves的invoke方法

// 在调用的valve中会继续调用valveContext.invokeNext的方法,然后调用自身的动作,实现pipeline的所有动作

(new StandardValveContext()).invokeNext(request, response);

}



protected class StandardValveContext implements ValveContext{

int stage = 0;

@Override

public String getInfo() {

return null;

}



@Override

public void invokeNext(Request request, Response response) throws IOException, ServletException {

int subscript = stage;

stage = stage + 1;

if(subscript < valves.length) {

valves[subscript].invoke(request, response, this);

}else if((subscript == valves.length) && basic != null){

basic.invoke(request, response, this);

}else {

throw new ServletException("no valves");

}

}



}



}

(4)SimpleWrapperValve:代表basic valve,所以只需要执行加载执行servlet动作,无需调用valveContext.invokeNext()

Code:

package com.cisco.tomcat.container;



import java.io.IOException;



import javax.servlet.Servlet;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;



import org.apache.catalina.Container;

import org.apache.catalina.connector.Request;

import org.apache.catalina.connector.Response;



public class SimpleWrapperValve implements Valve,  Contained  {



protected Container container;

@Override

public String getInfo() {

System.out.println("this is SimpleWrapperValve");

return null;

}



@Override

public void invoke(Request request, Response response, ValveContext context) throws IOException, ServletException {

SimpleWrapper wrapper = (SimpleWrapper)getContainer();

ServletRequest sreq = request.getRequest();

ServletResponse sresp = response.getResponse();

HttpServletRequest hreq = null;

HttpServletResponse hresp = null;

Servlet servlet = null;

if(sreq instanceof HttpServletRequest) {

hreq = (HttpServletRequest)sreq;

}

if(sresp instanceof HttpServletResponse) {

hresp = (HttpServletResponse) sresp;

}

try {

servlet = wrapper.allocate();

if(hreq!=null && hresp!=null) {

servlet.service(hreq, hresp);

}else {

servlet.service(sreq, sresp);

}                        

}catch(ServletException e) {



}





}



@Override

public void setContainer(Container container) {

this.container = container;                

}



@Override

public Container getContainer() {

return container;

}



}

 

(5)ClientIPValve:

添加的addition valve. 实现打印client ip功能:首先调用context.invokeNext(),然后执行自身动作

Code:

package com.cisco.tomcat.container;



import java.io.IOException;



import javax.servlet.Servlet;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;



import org.apache.catalina.Container;

import org.apache.catalina.connector.Request;

import org.apache.catalina.connector.Response;



public class ClientIPValve implements Valve, Contained{



private Container container;

@Override

public void setContainer(Container container) {

this.container = container;

}



@Override

public Container getContainer() {

return container;

}



@Override

public String getInfo() {

return null;

}



@Override

public void invoke(Request request, Response response, ValveContext context) throws IOException, ServletException {

context.invokeNext(request, response);

System.out.println("ClinetIP Valve invoke method...");

ServletRequest sreq = request.getRequest();

System.out.println("IP:"+sreq.getRemoteAddr());

}



}

(6)HeaderLoggerValve

添加的addition valve.实现打印header功能,首先调用context.invokeNext()。然后执行自身动作

package com.cisco.tomcat.container;



import java.io.IOException;

import java.util.Enumeration;



import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;



import org.apache.catalina.Container;

import org.apache.catalina.connector.Request;

import org.apache.catalina.connector.Response;



public class HeaderLoggerValve implements Valve, Contained{



private Container container;

@Override

public void setContainer(Container container) {

this.container = container;

}



@Override

public Container getContainer() {

return container;

}



@Override

public String getInfo() {

return null;

}



@Override

public void invoke(Request request, Response response, ValveContext context) throws IOException, ServletException {

context.invokeNext(request, response);

System.out.println("打印Http Header日志......");

if(request instanceof HttpServletRequest){

HttpServletRequest hreq = (HttpServletRequest) request;

Enumeration<String> headerNames = hreq.getHeaderNames();

while (headerNames.hasMoreElements()) {

String headerName = headerNames.nextElement().toString();

String headerValue = hreq.getHeader(headerName);

System.out.println(headerName + ": " + headerValue);

}

}else {

System.out.println("没有Header");

}



}



}

(7)BootStrap类:

package com.cisco.tomcat.container;



import java.io.IOException;



import org.apache.catalina.Loader;



public class Bootstrap {

public static void main(String[] args) {

Wrapper wrapper = new SimpleWrapper();

Loader loader = new SimpleWrapperLoader();

wrapper.setLoader(loader);

Valve clientIpValve = new ClientIPValve();

Valve headerLoggerValve = new HeaderLoggerValve();

wrapper.addValves(clientIpValve);

wrapper.addValves(headerLoggerValve);

wrapper.setServletClass("PrimitiveServlet");



HttpConnector connector = new HttpConnector();

connector.setContainer(wrapper);



connector.initialize();

connector.start();



try {

System.in.read();

} catch (IOException e) {

e.printStackTrace();

}

}

}

 

内容概要:本文深入探讨了Kotlin语言在函数式编程和跨平台开发方面的特性和优势,结合详细的代码案例,展示了Kotlin的核心技巧和应用场景。文章首先介绍了高阶函数和Lambda表达式的使用,解释了它们如何简化集合操作和回调函数处理。接着,详细讲解了Kotlin Multiplatform(KMP)的实现方式,包括共享模块的创建和平台特定模块的配置,展示了如何通过共享业务逻辑代码提高开发效率。最后,文章总结了Kotlin在Android开发、跨平台移动开发、后端开发和Web开发中的应用场景,并展望了其未来发展趋势,指出Kotlin将继续在函数式编程和跨平台开发领域不断完善和发展。; 适合人群:对函数式编程和跨平台开发感兴趣的开发者,尤其是有一定编程基础的Kotlin初学者和中级开发者。; 使用场景及目标:①理解Kotlin中高阶函数和Lambda表达式的使用方法及其在实际开发中的应用场景;②掌握Kotlin Multiplatform的实现方式,能够在多个平台上共享业务逻辑代码,提高开发效率;③了解Kotlin在不同开发领域的应用场景,为选择合适的技术栈提供参考。; 其他说明:本文不仅提供了理论知识,还结合了大量代码案例,帮助读者更好地理解和实践Kotlin的函数式编程特性和跨平台开发能力。建议读者在学习过程中动手实践代码案例,以加深理解和掌握。
内容概要:本文深入探讨了利用历史速度命令(HVC)增强仿射编队机动控制性能的方法。论文提出了HVC在仿射编队控制中的潜在价值,通过全面评估HVC对系统的影响,提出了易于测试的稳定性条件,并给出了延迟参数与跟踪误差关系的显式不等式。研究为两轮差动机器人(TWDRs)群提供了系统的协调编队机动控制方案,并通过9台TWDRs的仿真和实验验证了稳定性和综合性能改进。此外,文中还提供了详细的Python代码实现,涵盖仿射编队控制类、HVC增强、稳定性条件检查以及仿真实验。代码不仅实现了论文的核心思想,还扩展了邻居历史信息利用、动态拓扑优化和自适应控制等性能提升策略,更全面地反映了群体智能协作和性能优化思想。 适用人群:具备一定编程基础,对群体智能、机器人编队控制、时滞系统稳定性分析感兴趣的科研人员和工程师。 使用场景及目标:①理解HVC在仿射编队控制中的应用及其对系统性能的提升;②掌握仿射编队控制的具体实现方法,包括控制器设计、稳定性分析和仿真实验;③学习如何通过引入历史信息(如HVC)来优化群体智能系统的性能;④探索中性型时滞系统的稳定性条件及其在实际系统中的应用。 其他说明:此资源不仅提供了理论分析,还包括完整的Python代码实现,帮助读者从理论到实践全面掌握仿射编队控制技术。代码结构清晰,涵盖了从初始化配置、控制律设计到性能评估的各个环节,并提供了丰富的可视化工具,便于理解和分析系统性能。通过阅读和实践,读者可以深入了解HVC增强仿射编队控制的工作原理及其实际应用效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值