自定义简易版tomcat--基于网络编程

手动搭建简易tomcat 通过以上步骤,我们实现了一个简易版的Tomcat服务器。虽然它功能简单,但已经包含了Web服务器的基本原理。你可以在此基础上进一步扩展,比如支持更多的HTTP方法、动态页面处理等。 阅读详情

自定义简易版tomcat

项目目录结构

目录结构

核心代码

package com.yc.web.core;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;

import javax.sound.sampled.ReverbType;

import org.jaxen.function.StringFunction;

import com.yc.tomcat.core.ConstantInfo;
import com.yc.tomcat.core.ParseWebXml;
import com.yc.utils.StringUtil;

/**
*
* @author : 外哥
* 邮箱 : liwai2012220663@163.com
* 创建时间:2021年1月2日 下午9:30:43
*/
public class HttpServletResponse implements ServletResponse {
	private OutputStream os = null ;
	private String basePath = ConstantInfo.BASE_PATH ;
	private String projectName ; // 项目名
	
	public HttpServletResponse(OutputStream os , String projectName ) {
		this.os = os ;
		this.projectName = "/" + projectName ;
	}

	@Override
	public void sendRedirect(String url) {
		if ( StringUtil.checkNull( url )) {
			// TODO 404错误
			error404( url );
			return ;
		} 
		
		// 如果不是访问路径不是以项目名开头
		if ( !url.startsWith(projectName)) {
			send302(projectName + "/" + url );
			return ;
		}
		
		// 一般访问路径格式   /项目名/文件名
		if ( url.startsWith("/") && url.indexOf("/") == url.lastIndexOf("/") ) {
//			表示这个路径的格式为:/项目名
			send302(url + "/");
			return ;
		} else {
			if ( url.endsWith("/")) {
//				表示这个路径的格式为: /项目名/
				
				// 获取默认资源,通过解析配置文件得到
				String defaultPath = ConstantInfo.DEFAULT_RESOURCE;
				
				File fl = new File( basePath , url.substring(1).replace("/", "\\") + defaultPath ) ;
				if ( !fl.exists() || !fl.isFile() ) {
					error404(url);
					return ;
				}
				
				send200( readFile(fl) , url.substring( url.lastIndexOf(".") + 1 ).toLowerCase() );
				return ;
			}
			
			// 表示这个路径的格式为/项目名/文件名
			File fl = new File( basePath , url.substring(1).replace("/", "\\")) ;
			if ( !fl.exists() || !fl.isFile() ) {
				error404(url);
				return ;
			}
			send200( readFile(fl) , url.substring( url.lastIndexOf(".") + 1 ).toLowerCase() );

		}
		 
	}
	
	
	/**
	 * 发送
	 * @param bt 要发送的数据
	 * @param extension 扩展名
	 */
	private void send200(byte[] bt, String extension) {
		
		String contentType = "text/html;charset=utf-8" ;
		String type = ParseWebXml.getContentType( extension ) ;
		if ( !StringUtil.checkNull( type )) {
			contentType = type ;
		}
		
		try {
			String responseHeader = "HTTP/1.1 200 OK\r\nContent-Type: " + contentType + "\r\nContent-Length:"+ bt.length +"\r\n\r\n" ;
			os.write( responseHeader.getBytes() );
			os.write(bt);
			os.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if ( os!= null ) {
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 302重定向
	 * @param url
	 */
	private void send302( String url ) {
		try {
			String responseHeader = "HTTP/1.1 302 Moved Temporarily\r\nContent-Type: text/html;charset=utf-8\r\nLocation:"+ url +"\r\n\r\n" ;
			os.write( responseHeader.getBytes() );
			os.flush();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if ( os!= null ) {
				try {
					os.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	 
	/**
	 * 读取指定文件
	 * @param fl
	 * @return
	 */
	private byte[] readFile( File fl ) {
		byte[] bt = null ;
		FileInputStream fis = null ;
		try {
			fis = new FileInputStream(fl) ;
			bt = new byte[ fis.available() ] ;
			fis.read(bt) ;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if ( fis != null ) {
				try {
					fis.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
		return bt ;
	}

	
	/**
	 * 404报错
	 * @param url
	 */
	private void error404(String url) {
		try {
			String data = "<h1> HTTP Status 404 - " + url + "</h1>" ;
			String responseHeader = "HTTP/1.1 404 File Not Found\r\nContent-Type: text/html;charset=utf-8\r\nContent-Length:" + data.length() + "\r\n\r\n" ;
			os.write(responseHeader.getBytes());
			os.write(data.getBytes());
			os.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}finally {
			try {
				os.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	@Override
	public PrintWriter getWriter() throws IOException {
		String responseHeader = "HTTP/1.1 200 OK\r\nContent-Type: text/html;charset=utf-8\r\n\r\n" ;
		os.write( responseHeader.getBytes() );
		os.flush();  
		
		return new PrintWriter(os);
	}

}

package com.yc.tomcat.core;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;

import com.yc.utils.StringUtil;
import com.yc.web.core.HttpServletRequest;
import com.yc.web.core.HttpServletResponse;
import com.yc.web.core.Servlet;
import com.yc.web.core.ServletRequest;
import com.yc.web.core.ServletResponse;

/**
* 负责处理请求信息的类
* @author : 外哥
* 邮箱 : liwai2012220663@163.com
* 创建时间:2021年1月2日 下午7:33:36
*/
public class ServerService implements Runnable {
	private Socket sk = null ;
	private InputStream is = null ;
	private OutputStream os = null ;

	public ServerService(Socket sk) {
		this.sk = sk ; 
	}

	@Override
	public void run() {
		try {
			this.is = sk.getInputStream() ;
			this.os = sk.getOutputStream() ;
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		// 解析请求头信息
		ServletRequest request = new HttpServletRequest( is );
		
		// 从请求头中获取请求地址 /tickets/index.html
		String url = request.getUrl();
		// 去掉最前边的斜杠 tickets/index.html
		String temp = url.substring(1) ;
		// 获取项目名称
		String projectName = temp.contains("/")? temp.substring( 0 , temp.indexOf("/")) : temp ;
		
		try {
			url = URLDecoder.decode(url,"UTF-8") ;
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		
		ServletResponse response = new HttpServletResponse( os , projectName ) ;
		
		// 是不是动态访问
		String clazz = ParseUrlPattern.getClass(url) ;
		if ( StringUtil.checkNull( clazz )) {
			// 如果没有这个类,说明是静态资源,直接重定位即可
			response.sendRedirect(url); 
			return ;
		}
		
		URLClassLoader loader = null ;
		URL classPath = null ;
		
		try {
			// 获取资源的路径		协议		IP地址	路径
			classPath = new URL("file" , null , ConstantInfo.BASE_PATH + "\\" + projectName + "\\bin") ;
			
			// 创建类加载器
			loader = new URLClassLoader( new URL[] {classPath} ) ;
			
			// 到指定路径下加载指定的类
			Class<?> cls = loader.loadClass(clazz);
			
			// 获取类的对象
			Servlet servlet = (Servlet) cls.newInstance() ; 
			// 调用service方法
			servlet.service(request, response);
			
		} catch (Exception e) {
			send500( e ) ;
			e.printStackTrace(); 
		}    
	}

	private void send500(Exception e) {
		
		try {
			String responseHeader = "HTTP/1.1 500 Error\r\n\r\n" + e.getMessage() ;
			os.write( responseHeader.getBytes() ); 
			os.flush();
		} catch (IOException e1) {
			e1.printStackTrace();
		} finally {
			if ( os != null ) {
				try {
					os.close();
				} catch (IOException e1) {
					e1.printStackTrace();
				}
			}
		} 	
				
	} 

}

小编提供了源码,有兴趣的小伙伴可以下载了解
自定义tomcat源码https://download.youkuaiyun.com/download/Simple__Code/14090571

Java 领域 Tomcat 与 Netty 的网络编程集成 本文旨在为Java开发者提供一个全面的Tomcat与Netty集成指南,涵盖从基础概念到高级优化的所有关键环节。两种框架的核心差异与互补性集成的架构设计方案具体实现细节和性能考量实际应用案例和最佳实践首先介绍Tomcat和Netty的核心概念然后分析集成方案的设计原理接着通过代码示例展示具体实现最后探讨性能优化和实际应用Tomcat: Apache开发的Servlet容器,支持Java EE规范Netty: 高性能异步事件驱动的网络应用框架NIO。 阅读详情

相关推荐

创建简易版Tomcat网络容器的实践项目

在本章中,我们将逐步构建一个简易版的Tomcat网络容器,其核心功能是能够接收HTTP请求并返回响应。通过这个过程,我们不仅能够更好地理解Web服务器的运行机制,还能学会如何在Java中进行网络编程。Java I/O流是Java处理输入输出的核心机制,它允许程序读取数据和将数据写入各种类型的系统资源。I/O流可以分为两大类:字节流和字符流。字节流主要用于处理二进制数据,而字符流则处理字符数据。

weixin_35754676的博客 986

Tomcat的自定义与使用

创建lib文件夹,导入dom4j-1.1.jar包和log4j-1.2.12.jar包,创建日志工具类MyLogger在类中创建开启服务器方法,在方法中实现服务器的开启,接着用while(true)循环实现不中断地使用服务器,且在方法中实现多线程的开启。start();try {MyLogger.log("服务器已启动");System.out.println("连接成功");//启动线程}finally {= null) {try {

weixin_42533428的博客 909

自己实现Tomcat

此篇博客Mytomcat实现的功能只能访问静态资源(图片处理点问题),我们把项目部署到Mytomcat的webapps目录下,开启MyTomcat服务后,就可以进行访问了!博客:https://blog.youkuaiyun.com/m0_37499059/article/details/80779823

自定义Tomcat

一、Tomcat_v1 Tomcat服务器本质上就是一个 Server的程序,所以这里我们先写一个Server的程序和Socket程序,先完成最基本的通讯功能 Server.java: package com.tomcat_v1.mySocket_v1; import java.io.IOException; import java.io.InputStream; import java...

AN_ERA的博客 1691

tomcat自定义Web部署文件中docBase和workDir的区别介绍

本文主要介绍的是tomcat自定义Web部署文件中docBase和workDir的区别,下面话不多说,直接来看详细介绍。 首先看这段tomcat配置文件: <Context path=/web reloadable=false docBase=D:\CAPRuntime\src\main\webapp workDir=D:\CAPRuntime\src\main\webapp/> 其中的docBase和workDir分别指的是什么意思呢? 让我们做一个深入的剖析: 先解析workDir: jsp运行时都要先转换成servlet,使用tomcat时会在tomcat安装目录下

Python实战:用MNE-Python从脑电数据中提取P300成分(附完整代码)

本文提供了一份使用MNE-Python从脑电数据中提取P300成分的完整实战指南。通过详细的代码示例,系统讲解了从环境搭建、数据加载、预处理(滤波、分段、伪迹剔除)到P300波形提取、可视化与参数量化的全流程。重点介绍了如何利用零相位滤波和叠加平均技术,从EEG信号中精准分离出反映认知加工的P300事件相关电位,适用于脑机接口与认知神经科学研究。

weixin_29240343的博客 339

如何自己动手写一个 Tomcat

最近刚好工作中有遇到一个安全问题,IE 在 URL 地址栏中输入 < 这种特殊字符的时候,将会抛出异常打印异常堆栈信息,这样你的系统是不安全的,而且即使你在项目中使用了拦截器、过滤器等进行拦截都没用办法处理。原因是<并没有进入我们自己的web应用而是在中间间层tomcat容器就已经报错了。原因tomcat8.5.30之后拦截特殊字符解决办法 待续… ...

Just do it 1761

计算机三级考试嵌入式系统重点精简汇总

第一章 嵌入式系统概论 1.1.1嵌入式系统 (1)特点:(1)专用性;(2)隐蔽性;(3)资源受限;(4)高可靠性;(5)实时性;(6)软件固化。 (2)应用:(1)冰箱、洗衣机、电饭煲、空调、摄影机、DVD播放器等;(2)数控机床、飞机、汽车、电梯、X光机、血压计等;(3)电话机、传真机、打印机、pos机、GPS导航仪、路由器等。 1.1.2嵌入式系统组成与分类 (1)逻辑组成:硬件和软件,分为处理器、存储器、I|0设备与I|O接口,数据总线; (2)处理器:分为主处理器(CPU)和协处

chemkrik的博客 1万+

普通java项目中,配置tomcat服务器

下载tomcat服务器,并在普通java项目中使用。

m0_67598987的博客 784

SAP Parallel Accounting(平行分类账业务)配置及操作手册【适用于多国家会计准则】

在SAP系统中,分类账(Ledger)是用于会计核算的核心概念,它允许企业根据不同的会计原则和货币进行财务记录。定义分类账是配置平行账(Parallel Accounting)的第一步。分类账的创建:通过事务代码OX18可以创建新的分类账。通常,一个SAP系统会有一个主分类账(如0L),它代表法定会计和实时传输至管理会计(CO)的账本。分类账属性:在创建分类账时,需要定义其属性,如会计年度变式、货币、会计原则等。这些属性将决定分类账的核算规则和适用性。

数字化2025 4619

TGK-planner编译报错PLUGINLIB_EXPORT_CLASS解决

TGK-planner编译报错解决。

latter97的博客 857

Tomcat对String的编码处理

转载:请注明http://youkuaiyun.com作者:ggyy1977@hotmail.com Tomcat的中文处理(一)看到很多朋友问关于中文的处理问题,下面我们以tomcat4.0为servlet,jsp引擎来说说unicode的处理。1)       从客户端接受请求当客户端请求tomcat的一个jsp文档的时候,tomcat会构造相应的httpServletReques

ggyy的专栏 1413

【近源攻击】badusb制作

BadUSB是利用伪造HID设备执行攻击载荷的一种攻击方式。HID(Human InterfaceDevice)设备通常指的就是键盘鼠标等与人交互的设备,用户插入BadUSB,就会自动执行预置在固件中的恶意代码。BadUsb插入后,会模拟键盘鼠标对电脑进行操作,通过这些操作打开电脑的命令终端,并执行一条命令,这条命令将从指定网址下载其他代码并于后台静默运行。这些代码功能包括:窃取信息、反弹shell、发送邮件等,从而实现控制目标机或者窃取信息的目的。

qinjilll的博客 2550

网络编程之自己动手写简易版tomcat机制

tomcat是Apache、Sun 和其他一些公司及个人共同开发而成。经常用于与并发性不高的中小型系统中。为了了解web编程我们对类似于tomcat的服务器软件进行初探析并且自己动手写简易版tomcat。 前面我们编写了网络编程多个客户端的相互交互程序。现在我们将浅谈一下与浏览器之间的交互。当然我们从最基础的http协议开始。http协议是在tcp协议上再次进行包装,是应用层间的协议。即在tcp...

学海无涯 1054

Unreal5 从入门到精通之 学习Niagara特效系统

UE5 Niagara粒子系统解析 Niagara是UE5中的高性能粒子特效系统,相比传统粒子系统具有完全可编程性和可视化节点编辑两大特点。核心单元发射器(Emitter)分为模板发射器(预设效果如喷泉、火焰)和空白发射器(高度自定义)。系统提供13种预设模板,包括吹飞粒子、五彩纸屑爆发、动态光束等常见特效。 Niagara采用三级模块化设计: 系统级:全局参数设置与更新 发射器级:控制粒子生成规则与行为 粒子级:处理单个粒子的生命周期和渲染 关键模块包括初始化粒子属性、物理模拟、颜色渐变等,支持GPU加速

TxNet 1127

让openclaw接入web端的deepseek或着qwen,使用无限token

🪟 Windows: 提供原生的 PowerShell 一键安装支持!配置过程和官方版本是相同的,唯一的区别就是再选则model时要选择带Browser字样的deepseek或者qwen。安装之前需要先清理官方版本的安装痕迹,否则openclaw版本跳转不到这个中文版本。因为此版本与官方版本存在代差,在配置飞书时可能会出现无法安装飞书的情况。剩下的配置保持和官方版本一致操作即可。选中之后需要进行一次网页端的登录。登录后会出现可选择的model。安装完成后会跳到这个中文界面。涉及到接入飞书机器人的操作。

z1872385的博客 302

Netty核心组件介绍及手写简易版Tomcat

Netty是什么: 异步事件驱动框架,用于快速开发高i性能服务端和客户端 封装了JDK底层BIO和NIO模型,提供高度可用的API 自带编码解码器解决拆包粘包问题,用户只用关心业务逻辑 精心设计的Reactor线程模型支持高并发海量连接 自带协议栈,无需用户关心   Netty 是一款提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务...

吴振照 1073

【虚幻引擎UE】UE5 可编辑动态样条线轨迹及AI跟随路径移动(含工程源码)

【虚幻引擎UE】可编辑动态样条线轨迹及AI跟随路径移动

灵境引路人 6227

手写个Tomcat雏型

前言 目的: 网络编程在编程领域随处可见,本文尝试手写一个简单的HttpServer,了解网络请求后台的大致思路及为学习Tomcat打好基础。 准备知识: OOP:面向对象编程思想 collection:Java常用容器 IO:网络IO操作 Thread:多线程 Socket:网络编程 XML:配置文件解析 reflect:框架基石反射 HTML:HTML基本语法 HTTP:网络传输协议 思路 先说下大致流程: 服务端开启一个服务,进入一个死循环来给前端提供服务。 客户端发送一个HTTP请.

sowhat 2081

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

网络编程与Tomcat服务器

浏览器⽹⻚上看到的所有内容都称为 web 资源,⽐如⽂字,图⽚,⾳频,视频,链接等等内容。软件服务器: 其实就是⼀个软件:提供了B(browser)/S(server)应⽤运⾏的环境(管理了Web应⽤) ,作⽤:可以将我们开发好的静态资源或动态资源提供给外界(浏览器)访问。硬件服务器: 其实就是⼀台电脑,该电脑安装了软件服务器。

cylcjsg的博客 1433

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

解析Java网络编程基础:理解tomcat的原理

Tomcat是一个开源的Java Servlet容器和Web服务器。它本质上是使用Java的ServerSocket类实现基于TCP协议的Socket监听,从而处理传入的HTTP请求。

编程小蜜蜂 491

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

java网络编程_Java网络编程与NIO详解10:深度解读Tomcat中的NIO模型

本文转自:http://www.sohu.com/a/203838233_827544本系列文章将整理到我在GitHub上的《Java面试指南》仓库,更多精彩内容请到我的仓库里查看https://github.com/h2pl/Java-Tutorial喜欢的话麻烦点下Star哈文章将同步到我的个人博客:http://www.how2playlife.com本文是微信公众号【Java技术江湖】的《...

weixin_39698255的博客 175

Java网络编程学习与Tomcat配置

由于后端基本用框架实现,本次学习不再提供过于复杂的代码,只需大致了解通信、传输协议与传输方式,以及重点:Tomcat 即可 目录一、基本要素1.双方通讯地址2.规则3.万物皆对象二、端口公有端口程序动态端口三、通信协议四、Tomcat 一、基本要素 javaweb 网页编程 B/S TCP/IP 网络编程 C/S 1.双方通讯地址 ip 端口号 2.规则 TCP/IP参考类型 网络编程重点:TCP,UDP 如何定位到网络上一台或多台主机 3.万物皆对象 在java的net包内有包含了IP的函数方法

Hoorus的窝 872

Java网络编程详解

计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路和通信设备连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统。传播交流信息,数据交换,通信如何准确的定位到一台主机。端口:定位到这个计算机上的某个资源找到了这个主机,如何传输数据?

xzh202206的博客 2124

框架基础-网络编程+Tomcat服务器+XML

XML:英文名称Extensible Markup Language,中文名称是可扩展标记语言,通过标签为数据赋予意义的行为称为标记,为标记定义规则的语言叫做标记语言。

ZWJAS的博客 1620
上一篇: 简易版多人聊天室——NIO
下一篇: 自定义简易版mybatis
夕卜
博客等级 码龄6年 18粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值