How Tomcat works 4-5: Container

  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();

}

}

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
优化下面代码.bg { width: 100%; height: 100vh; background-image: url('../../assets/img/info-bg.png'); background-size: 100% 100%; background-repeat: no-repeat; position: relative; font-family: AlibabaPuHuiTiR; .goBack { position: absolute; top: 34px; right: 65px; cursor: pointer; color: #ffffff; width: 181px; padding: 15px 10px; background: rgba(24, 31, 30, 0.52); border: 1px solid #4a524e; border-radius: 5px; font-size: 18px; font-family: AlibabaPuHuiTiR; z-index: 111; display: flex; flex-direction: row; justify-content: space-between; align-items: center; } .home-left { position: absolute; top: 18%; left: 40px; width: 41%; height: 76%; font-size: 24px; color: #ffffff; } .unit { font-size: 24px; color: #636363; } .home-left-title { font-size: 24px; color: #ffffff; line-height: 36px; } .home-right { position: absolute; top: 18%; right: 88px; width: 46%; height: 78%; } .model { display: flex; justify-content: center; align-items: center; height: 90%; } #threeContained { width: 100%; height: 100%; } .model-qk-img { width: 82%; height: 90%; background-image: url('../../assets/img/howo.png'); background-size: 100% 100%; background-repeat: no-repeat; } .model-zk-img { width: 56%; height: 90%; background-image: url('../../assets/img/heavyT.png'); background-size: 100% 100%; background-repeat: no-repeat; } .model-gj-img { width: 82%; height: 90%; background-image: url('../../assets/img/transit.png'); background-size: 100% 100%; background-repeat: no-repeat; } .car-online { margin-bottom: 50px; } } .day-data { display: flex; flex-direction: row; justify-content: space-between; align-items: center; height: 29%; margin-left: 30px; } .day-val { width: 40%; } .prefix { display: inline-block; width: 6px; height: 14px; background: #ffffff; margin-right: 20px; } .zh-title { margin-left: 30px; padding-top: 30px; font-size: 30px; font-weight: 700; text-align: left; color: #ffffff; line-height: 32px; letter-spacing: 0.3px; font-family: AlibabaPuHuiTiB; } .en-title { margin-left: 30px; font-size: 14px; font-weight: 400; text-align: left; color: #ffffff; line-height: 32px; letter-spacing: -0.91px; font-family: AlibabaPuHuiTiR; }
05-31
Here are some suggestions to optimize the code: 1. Use shorthand properties whenever possible. For example, instead of writing `background-size: 100% 100%;`, you can write `background-size: cover;`. 2. Consolidate similar styles into classes, instead of repeating them for every element. For example, you can create a class for the font family and apply it to all elements that use that font. 3. Remove unnecessary styles that are not being used or overwritten by other styles. 4. Use more specific selectors to target elements, instead of relying on the order of elements in the HTML. This will make the code more robust and easier to maintain. 5. Consider using a CSS preprocessor like Sass or Less, which can help you write cleaner and more organized code. Here's an example of how the code could be optimized: ``` .bg { width: 100%; height: 100vh; background: url('../../assets/img/info-bg.png') no-repeat center center / cover; position: relative; font-family: AlibabaPuHuiTiR; } .goBack { position: absolute; top: 34px; right: 65px; cursor: pointer; color: #fff; width: 181px; padding: 15px 10px; background: rgba(24, 31, 30, 0.52); border: 1px solid #4a524e; border-radius: 5px; font-size: 18px; font-family: AlibabaPuHuiTiR; z-index: 111; display: flex; flex-direction: row; justify-content: space-between; align-items: center; } .home-left { position: absolute; top: 18%; left: 40px; width: 41%; height: 76%; font-size: 24px; color: #fff; } .unit { font-size: 24px; color: #636363; } .home-left-title { font-size: 24px; color: #fff; line-height: 36px; } .home-right { position: absolute; top: 18%; right: 88px; width: 46%; height: 78%; } .model { display: flex; justify-content: center; align-items: center; height: 90%; } #threeContained { width: 100%; height: 100%; } .model-qk-img { width: 82%; height: 90%; background: url('../../assets/img/howo.png') no-repeat center center / cover; } .model-zk-img { width: 56%; height: 90%; background: url('../../assets/img/heavyT.png') no-repeat center center / cover; } .model-gj-img { width: 82%; height: 90%; background: url('../../assets/img/transit.png') no-repeat center center / cover; } .car-online { margin-bottom: 50px; } .day-data { display: flex; justify-content: space-between; align-items: center; height: 29%; margin-left: 30px; } .day-val { width: 40%; } .prefix { display: inline-block; width: 6px; height: 14px; background: #fff; margin-right: 20px; } .zh-title { margin-left: 30px; padding-top: 30px; font-size: 30px; font-weight: 700; text-align: left; color: #fff; line-height: 32px; letter-spacing: 0.3px; font-family: AlibabaPuHuiTiB; } .en-title { margin-left: 30px; font-size: 14px; font-weight: 400; text-align: left; color: #fff; line-height: 32px; letter-spacing: -0.91px; font-family: AlibabaPuHuiTiR; } .font-alibaba { font-family: AlibabaPuHuiTiR; } .font-alibaba-bold { font-family: AlibabaPuHuiTiB; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值