`
come_for_dream
  • 浏览: 120250 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

写个web容器是不是很酷?

阅读更多

哈,本人现在大三还在为了学业奋斗,这些天很累,好多实验,也快要考试了,自己还负责的web重构和app开发任务还是比较重的。小菜小菜在这些时间里面进步也是蛮多的,为什么要写web服务器呢?不仅仅是因为比较酷哈,这也是我们的课程要求撒吻吻吻吻。当然要写就要写的比较好所以自己对这个实验也是蛮有兴趣的 。

      服务器能够接受来自浏览器发来的的get的静态文件的请求,服务器可以处理来自浏览器的多次请求,因为这个服务器写出来花的时间并不长所以功能也想对来说简单些,不过小菜在日后会不断的完善期功能,当然也会参考Servlet规范写出支持Servlet的容器,不过这些都是后话了先看下面贴出代码并解释其过程:



 这个是我的工程结构

1,程序入口:

package com.zdx.sever;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.zdx.domain.Request;
import com.zdx.domain.Response;
/**
 * 这里使用到了线程池来处理客户端发的多次请求,以节约系统资源,减少线程的创建从而提高系统性能
 * @author zdx
 *
 */
public class MainServer {

	private final int port = 8091;
	// 线程池维护的最小线程数量
	private static int corePoolSize = 3;
	// 线程池维护的最大线程数
	private static int maximumPoolSize = 10;
	// 线程池维护线程所允许的空闲时间
	private static int keepAliveTime=10;
	// 线程池维护线程所允许的空闲时间的单位
	private static TimeUnit timeUnit = TimeUnit.SECONDS;
	// 线程池所使用的缓冲队列
	private BlockingQueue<Runnable> blockingQueue;
	// 线程池
	private ExecutorService executor;

	public MainServer() {

		blockingQueue = new ArrayBlockingQueue<>(5);
                //创建线程池对象
		this.executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
				keepAliveTime, timeUnit, blockingQueue);
	}
/**
*
*处理请求
*
*/
	public  void dealRequest() {

		try {
			ServerSocket serverSocket = new ServerSocket(port);
			Socket socket = null;
			InetAddress inetAddress;
			InputStream inputStream = null;
			OutputStream outputStream = null;
			while (true) {
                               //阻塞
				socket = serverSocket.accept();
				//创建Request对象
				inputStream = socket.getInputStream();
				inetAddress = socket.getInetAddress();
				Request request=new Request(inputStream, inetAddress);
				
				//创建Response;
				outputStream = socket.getOutputStream();
				Response response=new Response(outputStream);
				
				//创建处理线程
				HandlerRunnable handlerRunnable=new HandlerRunnable(request, response);
				//将线程提交到线程池中进行处理
				this.executor.submit(handlerRunnable);
				
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	public static void main(String[] args) {
		MainServer mainServer=new MainServer();
		mainServer.dealRequest();
	}

}

 

2,下面是Request类,其中对请求做了解析和封装处理

package com.zdx.domain;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;

import com.zdx.util.RequestUtil;

public class Request {

	private String requestType;
	private String requestUrl;
	private InputStream inputStream;
	private InetAddress inetAddress;
	private Map<String, Object> paramters;

	public Request(InputStream inputStream, InetAddress inetAddress) {
		this.inputStream = inputStream;
		this.inetAddress = inetAddress;
		this.paramters=new HashMap<String,Object>();
		parseRequest();
	}

	private void parseRequest() {

		BufferedReader bufferedReader = new BufferedReader(
				new InputStreamReader(inputStream));
		String msg;
		try {
			msg = bufferedReader.readLine();
			while (msg == null) {
				return;
			}
                        //获得请求类型
			String requestType = RequestUtil.getRequestType(msg);
			if (requestType.equals("GET")) {
				this.requestType = "GET";
			} else {
				this.requestType = "POST";
			}

			// 设置请求的资源
			this.requestUrl = RequestUtil.getRequestFileName(msg);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public String getRequestType() {
		return requestType;
	}

	public void setRequestType(String requestType) {
		this.requestType = requestType;
	}

	public String getRequestUrl() {
		return requestUrl;
	}

	public void setRequestUrl(String requestUrl) {
		this.requestUrl = requestUrl;
	}

	public InputStream getInputStream() {
		return inputStream;
	}

	public void setInputStream(InputStream inputStream) {
		this.inputStream = inputStream;
	}

}

 

3,设置Resopnse类;

package com.zdx.domain;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.HashMap;
import java.util.Map;

public class Response {

	private OutputStream outputStream;
	private BufferedWriter writer;
	private Map<String, Object> paramter;

	public Response(OutputStream outputStream) {
		this.outputStream=outputStream;
		this.writer=new BufferedWriter(new OutputStreamWriter(outputStream));
		this.paramter = new HashMap<String, Object>();

	}

	public void output(byte[] datas) throws IOException {
		outputStream.write(datas);
	}

	
	
	public OutputStream getOutputStream() {
		return outputStream;
	}

	public void setOutputStream(OutputStream outputStream) {
		this.outputStream = outputStream;
	}

	public Map<String, Object> getParamter() {
		return paramter;
	}

	public void setParamter(Map<String, Object> paramter) {
		this.paramter = paramter;
	}

	public Object addAttribute(String key, Object value) {
		return this.paramter.put(key, value);
	}

	public Object setAttribute(String key, Object value) {
		return this.paramter.put(key, value);
	}

	public Object removeAttribute(String key) {
		return this.paramter.remove(key);
	}
	public void closeWriter() throws IOException{
		this.writer.close();
	}
	public void closeOutPutStream() throws IOException{
		this.outputStream.close();
	}

}

 

4,具体的请求处理线程类:

package com.zdx.sever;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;

import com.zdx.domain.Request;
import com.zdx.domain.Response;
import com.zdx.util.Constant;
import com.zdx.util.RequestUtil;

public class HandlerRunnable implements Runnable {

	private Request request;
	private Response response;

	public HandlerRunnable(Request request, Response response) {
		this.request = request;
		this.response = response;
	}

	@Override
	public void run() {
		try {
			requestHandler();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void requestHandler() throws IOException {

		String requestType = request.getRequestType();
		if (requestType.equals("GET")) {
			String fileName = request.getRequestUrl();
			String filePath = Constant.WEB_ROOT + fileName;
			System.out.println(filePath);

			// GET the OutputSteam object
			OutputStream outputStream = response.getOutputStream();
			// 进行文件的读取
			File file = new File(filePath);
			if (file.exists()) {
				FileInputStream fileInputStream = new FileInputStream(file);
				byte[] bufferByte = new byte[1024];
				int read = fileInputStream.read(bufferByte);
				while (read != -1) {
					outputStream.write(bufferByte, 0, read);
					read = fileInputStream.read(bufferByte, 0, 1024);
				}
			} else {
				outputStream.write("404!!  can not find the file".getBytes());
			}

			outputStream.flush();
			outputStream.close();
			System.out.println("over!!");
		}

	}

	public Request getRequest() {
		return request;
	}

	public void setRequest(Request request) {
		this.request = request;
	}

}

 

这几行代码就可以做到了下面是程序运行后的一个效果图:



 

看上面有图片有文字,哈哈,并可以处理多次请求,但是resopnse的相应头和其他信息都还没有做不过以后会做的,此容器的后续开发回持续更新,请前辈们给点意见指导哈

  • 大小: 35.3 KB
  • 大小: 913 KB
6
5
分享到:
评论
13 楼 残云cruel 2015-06-06  
呀,界面挺好看的啊,嗯呢 不错不错。年轻人 有前途,值得栽培
12 楼 come_for_dream 2015-04-17  
yzsunlight 写道
代码可否共享

https://github.com/zdxit/WebServer
11 楼 yzsunlight 2015-04-17  
代码可否共享
10 楼 come_for_dream 2015-04-16  
yangshangchuan 写道
cool! i mean awful.

thanks any way
9 楼 yangshangchuan 2015-04-16  
cool! i mean awful.
8 楼 come_for_dream 2015-04-16  
killko 写道
很不错!

socket那里可以尝试用nio,效率会更高;
注意一下HTTP的回应的状态码,例如你代码里的404,应该在header里体现出来

这样,好的,我改进一下
7 楼 come_for_dream 2015-04-16  
DreamRoute 写道
楼主才大三就有这理解,很不错,不过如果楼主认为这几行代码就叫做所谓的Web容器的话,那你对Web“容器”的理解未免就有些狭隘了。

恩恩,后续根绝Servlet规范加入支持Servlet的功能才能叫容器,谢谢指点 
6 楼 DreamRoute 2015-04-16  
楼主才大三就有这理解,很不错,不过如果楼主认为这几行代码就叫做所谓的Web容器的话,那你对Web“容器”的理解未免就有些狭隘了。
5 楼 killko 2015-04-16  
很不错!

socket那里可以尝试用nio,效率会更高;
注意一下HTTP的回应的状态码,例如你代码里的404,应该在header里体现出来
4 楼 Tyrion 2015-04-16  
大三的写成这样还不错了已经。
3 楼 come_for_dream 2015-04-16  
kknd97 写道
结构设计的很优雅,流程清晰,思路简介,非常非常好。
作为大三的学生能有如此的功底和基础知识,非常好。
继续努力!

谢谢前辈
2 楼 kknd97 2015-04-16  
结构设计的很优雅,流程清晰,思路简介,非常非常好。
作为大三的学生能有如此的功底和基础知识,非常好。
继续努力!
1 楼 wwwcomy 2015-04-16  
en ....

Tomcat雏形...

相关推荐

    jsp乱码解决超酷,通过web.xml配置

    2. **JSP页面乱码**:JSP文件本身可能使用了特定的字符集,如果Web容器在解析JSP时使用了不同的字符集,也可能导致乱码。 3. **Servlet响应乱码**:在Servlet或JSP中输出非ASCII字符时,需要确保响应头中的`Content...

    很酷很炫的网站

    在"很酷很炫的网站"中,可能应用了以下CSS3特性: 1. **选择器增强**:如伪类选择器`:hover`, `:active`, `:focus`, `:nth-child()`等,更精确地控制元素样式。 2. **边框与背景**:引入圆角边框`border-radius`,...

    彩色超酷CSS+DIVWEB标准模板.rar

    综上所述,这个模板提供了一套使用CSS和DIV技术、注重色彩设计和浏览器兼容性的网页布局方案,对于Web设计师或开发者来说,是一个快速构建吸引眼球的网站的良好起点。同时,它的标准化和模块化设计也便于后期的修改...

    flex style 很酷的例子,快来下载吧

    这个“Flex Style很酷的例子”压缩包很可能是包含了一系列使用Flex布局的示例代码或者网页,旨在帮助学习者或开发者更好地理解和应用Flex布局。 Flex布局的核心概念是“弹性容器”(Flexible Container)和“弹性...

    Flex Style很酷的例子来共享

    在这个“Flex Style很酷的例子”中,我们可以深入学习和理解Flex布局的核心概念和应用。 1. **Flex容器与Flex项目** - **Flex容器**:一个具有`display: flex`或`display: inline-flex`样式的元素,成为Flex容器,...

    wg-gen-web:用于WireGuard的基于Web的简单配置生成器。 演示:

    Dockerized 很酷的外观跑步码头工人运行Wg Gen Web的最简单方法是使用容器映像docker run --rm -it -v /tmp/wireguard:/data -p 8080:8080 -e "WG_CONF_DIR=/data" vx3r/wg-gen-web:latestDocker撰写代码段,用于...

    一些很酷的.Net技巧

    标题 "一些很酷的.Net技巧" 提到的.NET框架是一个由微软开发的全面的软件开发平台,用于构建各种类型的应用程序,包括桌面、Web、移动和云应用。它提供了丰富的类库、编程语言支持(如C#)、编译器和开发工具。C#是...

    divcss.zip_web项目

    总的来说,这个压缩包提供了一个使用`DIV+CSS`实现的多级菜单实例,对于学习和实践Web前端开发,特别是页面布局和交互设计的开发者来说,是一个很有价值的参考资料。通过分析和修改这些文件,可以深入了解和掌握`DIV...

    HTML炫酷时钟 动态 js调用

    这通常包括一个`&lt;div&gt;`标签,作为时钟的容器,以及可能的CSS样式来定义其外观。 JavaScript则负责时钟的动态更新功能。通过使用`setInterval()`函数,我们可以定期执行一段代码,例如每秒一次,来获取当前时间并...

    很酷的flash 3d图片源码

    综上所述,这个"很酷的Flash 3D图片源码"是一个利用ActionScript 3.0编写的,具有创新3D显示效果的Flash应用。它可能包含以下知识点: 1. **ActionScript 3.0基础**:了解变量、函数、类和对象等基本概念,以及如何...

    使用html+CSS实现流星雨特效,可以直接在编辑器中运行或者在浏览器中打开,十分的炫酷

    在这个项目中,我们将探讨如何使用这两种技术来实现一...对于初学者来说,这是一个很好的实践项目,有助于理解这三者之间的协同工作原理。而对于经验丰富的开发者,这样的特效可以作为提升网站或应用吸引力的一种手段。

    HTML超级炫酷相册源码.zip

    HTML超级炫酷相册源码是一个实用的工具,它展示了如何使用HTML、CSS以及可能的JavaScript来创建一个吸引人的、交互式的在线相册。...对于初学者,这是一个很好的实践项目,可以加深对Web开发的理解,提升技能水平。

    html5炫酷效果图片墙

    在"Photo1"这个文件中,很可能是项目的示例图片或者预览图。为了实现四种不同的图片墙效果,我们需要根据不同的设计需求调整图片的布局和样式。例如,平面墙可能简单地将图片并排放置,而圆球墙则需要计算每个图片的...

    flashaxe-webcode-master.zip

    本篇文章将围绕“flashaxe-webcode-master.zip”这个压缩包文件,深入探讨其中蕴含的前端CSS技术,帮助开发者掌握如何实现各种炫酷的网页效果。 首先,我们要了解“前端”是指在用户设备上运行的代码部分,主要包括...

    JSP网站开发四“酷”全书:新闻、论坛、电子商城、博客 源码下载1

    Tomcat是一个开源的Java Servlet和JavaServer Pages(JSP)容器,它实现了Java EE的Web应用程序部分。在本案例中,4.1.24版本是专门为JSP新闻应用设计的。这个版本可能包含了对当时JSP规范的兼容性和性能优化,...

    超酷播放器FLA源码

    超酷播放器FLA源码是一个关于多媒体播放器开发的资源,主要针对的是Adobe Flash平台。FLA是Flash Authoring File的缩写,它是Flash ...对于想要提升自己在Flash开发领域的技能的人来说,这是一个很好的学习材料。

    CSS3实现的动画开关,效果很炫酷

    在Web开发中,用户界面的交互性是提升用户体验的重要因素之一。CSS3(Cascading Style Sheets Level 3)的引入为开发者提供了丰富的动画功能,使得创建炫酷的界面元素变得更加容易。本篇文章将深入探讨如何利用CSS3...

    基于PHP的酷瓜云课堂(腾讯云版).zip

    这意味着它可能是一个完整的Web应用程序,旨在为用户提供一个在云端进行学习和教学的互动环境。 【标签】:“PHP” 【详细知识点】: 1. **PHP**:PHP(Hypertext Preprocessor,超文本预处理器)是一种广泛使用...

    基于SSM开发的的web聊天室项目程序.zip

    这个项目是基于SSM框架实现的一个Web聊天室,让我们来深入了解一下这三个组件及其在项目中的作用。 1. **Spring框架**: Spring是一个全面的Java企业级应用开发框架,提供了依赖注入(Dependency Injection, DI)...

    基于three.js实现的炫酷3D线条背景动画特效

    three.js是一个强大的开源框架,专门用于在Web浏览器中构建三维图形,它利用WebGL技术,为用户提供了一种在网页上展示复杂3D场景的方法。 【描述】"一款小清新风格基于three.js实现的炫酷Canvas 3D线条背景动画特效...

Global site tag (gtag.js) - Google Analytics