哈,本人现在大三还在为了学业奋斗,这些天很累,好多实验,也快要考试了,自己还负责的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的相应头和其他信息都还没有做不过以后会做的,此容器的后续开发回持续更新,请前辈们给点意见指导哈
相关推荐
2. **JSP页面乱码**:JSP文件本身可能使用了特定的字符集,如果Web容器在解析JSP时使用了不同的字符集,也可能导致乱码。 3. **Servlet响应乱码**:在Servlet或JSP中输出非ASCII字符时,需要确保响应头中的`Content...
在"很酷很炫的网站"中,可能应用了以下CSS3特性: 1. **选择器增强**:如伪类选择器`:hover`, `:active`, `:focus`, `:nth-child()`等,更精确地控制元素样式。 2. **边框与背景**:引入圆角边框`border-radius`,...
综上所述,这个模板提供了一套使用CSS和DIV技术、注重色彩设计和浏览器兼容性的网页布局方案,对于Web设计师或开发者来说,是一个快速构建吸引眼球的网站的良好起点。同时,它的标准化和模块化设计也便于后期的修改...
这个“Flex Style很酷的例子”压缩包很可能是包含了一系列使用Flex布局的示例代码或者网页,旨在帮助学习者或开发者更好地理解和应用Flex布局。 Flex布局的核心概念是“弹性容器”(Flexible Container)和“弹性...
在这个“Flex Style很酷的例子”中,我们可以深入学习和理解Flex布局的核心概念和应用。 1. **Flex容器与Flex项目** - **Flex容器**:一个具有`display: flex`或`display: inline-flex`样式的元素,成为Flex容器,...
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框架是一个由微软开发的全面的软件开发平台,用于构建各种类型的应用程序,包括桌面、Web、移动和云应用。它提供了丰富的类库、编程语言支持(如C#)、编译器和开发工具。C#是...
总的来说,这个压缩包提供了一个使用`DIV+CSS`实现的多级菜单实例,对于学习和实践Web前端开发,特别是页面布局和交互设计的开发者来说,是一个很有价值的参考资料。通过分析和修改这些文件,可以深入了解和掌握`DIV...
这通常包括一个`<div>`标签,作为时钟的容器,以及可能的CSS样式来定义其外观。 JavaScript则负责时钟的动态更新功能。通过使用`setInterval()`函数,我们可以定期执行一段代码,例如每秒一次,来获取当前时间并...
综上所述,这个"很酷的Flash 3D图片源码"是一个利用ActionScript 3.0编写的,具有创新3D显示效果的Flash应用。它可能包含以下知识点: 1. **ActionScript 3.0基础**:了解变量、函数、类和对象等基本概念,以及如何...
在这个项目中,我们将探讨如何使用这两种技术来实现一...对于初学者来说,这是一个很好的实践项目,有助于理解这三者之间的协同工作原理。而对于经验丰富的开发者,这样的特效可以作为提升网站或应用吸引力的一种手段。
HTML超级炫酷相册源码是一个实用的工具,它展示了如何使用HTML、CSS以及可能的JavaScript来创建一个吸引人的、交互式的在线相册。...对于初学者,这是一个很好的实践项目,可以加深对Web开发的理解,提升技能水平。
在"Photo1"这个文件中,很可能是项目的示例图片或者预览图。为了实现四种不同的图片墙效果,我们需要根据不同的设计需求调整图片的布局和样式。例如,平面墙可能简单地将图片并排放置,而圆球墙则需要计算每个图片的...
本篇文章将围绕“flashaxe-webcode-master.zip”这个压缩包文件,深入探讨其中蕴含的前端CSS技术,帮助开发者掌握如何实现各种炫酷的网页效果。 首先,我们要了解“前端”是指在用户设备上运行的代码部分,主要包括...
Tomcat是一个开源的Java Servlet和JavaServer Pages(JSP)容器,它实现了Java EE的Web应用程序部分。在本案例中,4.1.24版本是专门为JSP新闻应用设计的。这个版本可能包含了对当时JSP规范的兼容性和性能优化,...
超酷播放器FLA源码是一个关于多媒体播放器开发的资源,主要针对的是Adobe Flash平台。FLA是Flash Authoring File的缩写,它是Flash ...对于想要提升自己在Flash开发领域的技能的人来说,这是一个很好的学习材料。
在Web开发中,用户界面的交互性是提升用户体验的重要因素之一。CSS3(Cascading Style Sheets Level 3)的引入为开发者提供了丰富的动画功能,使得创建炫酷的界面元素变得更加容易。本篇文章将深入探讨如何利用CSS3...
这意味着它可能是一个完整的Web应用程序,旨在为用户提供一个在云端进行学习和教学的互动环境。 【标签】:“PHP” 【详细知识点】: 1. **PHP**:PHP(Hypertext Preprocessor,超文本预处理器)是一种广泛使用...
这个项目是基于SSM框架实现的一个Web聊天室,让我们来深入了解一下这三个组件及其在项目中的作用。 1. **Spring框架**: Spring是一个全面的Java企业级应用开发框架,提供了依赖注入(Dependency Injection, DI)...
three.js是一个强大的开源框架,专门用于在Web浏览器中构建三维图形,它利用WebGL技术,为用户提供了一种在网页上展示复杂3D场景的方法。 【描述】"一款小清新风格基于three.js实现的炫酷Canvas 3D线条背景动画特效...