通过Java编写一个服务器理解动态Web,静态Web

静态Web

说到Servlet自然就要说到Web,Web分为静态Web和动态Web,之前我一直都傻傻分不清两者的区别,直到用JAVA编写了一个服务器后才明白二者的区别,所谓静态Web,实际上就是指,客户端要请求的资源文件,服务器已经提前把它放在了文件系统(磁盘)上,看下面用Java实现的一个静态Web服务器
public class HTTPService {private static HashMap<String,Servlet> servletCache = new HashMap<>();public static void init(){servletCache.put("HTTPServlet",new HTTPServlet());}public static void main(String[] args) {init();int port;ServerSocket serversocket;port=8080;try {serversocket = new ServerSocket(port);  //默认服务器套接字ip为本地地址System.out.println("服务器正在监听端口:8080");while (true) {try{Socket socket = serversocket.accept();//会进入阻塞状态,直到客户端与服务器TCP建立System.out.println("建立了与客户端的一个新的tcp连接,客户端地址为" + socket.getInetAddress() + ":" + socket.getPort());service(socket);}catch (Exception e){System.out.println("客户端请求资源不存在");}}} catch (Exception e) {System.out.println("客户端请求资源不存在");}}public static void service(Socket socket) throws Exception {InputStream socketIn = socket.getInputStream();//获得客户端请求信息流Thread.sleep(500);  //与客户端TCP请求已建立,还需要等待客户端发送http请求,如果在TCP后立马响应HTTP,socket内容可能为空int size = socketIn.available();byte[] buffer = new byte[size];socketIn.read(buffer);String request = new String(buffer);int endIndex = request.indexOf("\r\n");if (endIndex==-1)endIndex = request.length();String firstLineOfRequest = request.substring(0,endIndex);String[] parts = firstLineOfRequest.split(" ");String uri="";String contentType="";if (parts.length>=2){uri = parts[1];}//静态webif (uri.indexOf("html") != -1)contentType = "text/html";else if (uri.indexOf("jpg") != -1)contentType = "image/jepg";elsecontentType = "application/octet-stream";String firstLineOfResponse = "HTTP/1.1 200 OK\r\n";  //响应行String responseHeader = "Content-Type:" + contentType + "\r\n\r\n";// FileInputStream in = new FileInputStream("E:\\IDEA WORKSPACE\\ServiceDemo\\resources\\index.html");System.out.println(HttpServer.class.getResource(""));InputStream in = HTTPService.class.getResourceAsStream("root/" + uri);System.out.println(HTTPService.class.getResource("root/" + uri));OutputStream output = socket.getOutputStream();output.write(firstLineOfResponse.getBytes());output.write(responseHeader.getBytes());buffer = new byte[1024];int len = 0;while ((len = in.read(buffer)) != -1) {System.out.println(1);output.write(buffer, 0, len);}Thread.sleep(1000);//睡眠1秒,等待客户端接收http响应结果,socket代表两者间的tcp连接,如果立马断开,客户端可能就收不到响应结果了socket.close();}}

将事先准备好的index.html文件放在磁盘上,将代码运行起来,此时HTTPServer就作为一个服务开始监听电脑上的8080端口了,打开浏览器,在url地址栏输入localhost:8080/index.html,结果如下:
在这里插入图片描述
在这里插入图片描述
工作原理如下:
在这里插入图片描述

HTTPServer接收到来自客户端的请求后,就会在磁盘上查找客户端请求的资源文件,然后把文件响应给客户端,index.html就事先存放在磁盘上,然后当浏览器请求index.html,HTTPServer就把html文件响应给浏览器,浏览器再解析html文件后,就是我们看到的Hello页面了。

动态Web

网上经常能看见一句话,动态Web就是每个用户看到的东西是不一样的,这句话没错,但是还不太能够帮助我们理解动态Web。那么动态Web到底是什么,动态Web就是指客户端可以与服务器进行交互,并且客户端请求的资源文件,是由服务器动态生成的。举这么一个例子,假设D是一个在某城市居住了很久的人,这一天A向D问路X街怎么走,D经过思考后,告诉了A,此时B又来问路Y街怎么走,对于C来说,简直轻而易举。上述中A,B看作客户端,D是服务器,而问路可以看作客户端向服务器请求的资源文件,去某城市可以看作是客户端与服务器的交互,很明显,A和B得到的响应内容都是不同的,服务器在得到客户端的请求后,执行业务逻辑操作,得出了通往某城市怎么走,然后响应给客户端。
public class HTTPService {private static HashMap<String,Servlet> servletCache = new HashMap<>();public static void init(){servletCache.put("HTTPServlet",new HTTPServlet());}public static void main(String[] args) {init();int port;ServerSocket serversocket;port=8080;try {serversocket = new ServerSocket(port);  //默认服务器套接字ip为本地地址System.out.println("服务器正在监听端口:8080");while (true) {try{Socket socket = serversocket.accept();//会进入阻塞状态,直到客户端与服务器TCP建立System.out.println("建立了与客户端的一个新的tcp连接,客户端地址为" + socket.getInetAddress() + ":" + socket.getPort());service(socket);}catch (Exception e){System.out.println("客户端请求资源不存在");}}} catch (Exception e) {System.out.println("客户端请求资源不存在");}}public static void service(Socket socket) throws Exception {InputStream socketIn = socket.getInputStream();//获得客户端请求信息流Thread.sleep(500);  //与客户端TCP请求已建立,还需要等待客户端发送http请求,如果在TCP后立马响应HTTP,socket内容可能为空int size = socketIn.available();byte[] buffer = new byte[size];socketIn.read(buffer);String request = new String(buffer);int endIndex = request.indexOf("\r\n");if (endIndex==-1)endIndex = request.length();String firstLineOfRequest = request.substring(0,endIndex);String[] parts = firstLineOfRequest.split(" ");String uri="";String contentType="";if (parts.length>=2){uri = parts[1];}System.out.println(uri);if(uri.indexOf("servlet")!=-1){   //动态webString servletName = "";if (uri.indexOf("?")!=-1)servletName = uri.substring(uri.indexOf("servlet/")+8,uri.indexOf("?"));elseservletName = uri.substring(uri.indexOf("servlet/")+8,uri.length());System.out.println(servletName);Servlet servlet = servletCache.get(servletName);System.out.println(servletCache);System.out.println(servlet);if (servlet == null)throw new Exception();servlet.init();servlet.service(request,socket.getOutputStream());}else {//静态webif (uri.indexOf("html") != -1)contentType = "text/html";else if (uri.indexOf("jpg") != -1)contentType = "image/jepg";elsecontentType = "application/octet-stream";String firstLineOfResponse = "HTTP/1.1 200 OK\r\n";  //响应行String responseHeader = "Content-Type:" + contentType + "\r\n\r\n";// FileInputStream in = new FileInputStream("E:\\IDEA WORKSPACE\\ServiceDemo\\resources\\index.html");System.out.println(HttpServer.class.getResource(""));InputStream in = HTTPService.class.getResourceAsStream("root/" + uri);System.out.println(HTTPService.class.getResource("root/" + uri));OutputStream output = socket.getOutputStream();output.write(firstLineOfResponse.getBytes());output.write(responseHeader.getBytes());buffer = new byte[1024];int len = 0;while ((len = in.read(buffer)) != -1) {System.out.println(1);output.write(buffer, 0, len);}}Thread.sleep(1000);//睡眠1秒,等待客户端接收http响应结果,socket代表两者间的tcp连接,如果立马断开,客户端可能就收不到响应结果了socket.close();}}
public class HTTPServlet implements Servlet{@Overridepublic void init() {}@Overridepublic void service(String request, OutputStream out) throws IOException {int endIndex = request.indexOf("/r/n");String firstOfRequest = "";if (endIndex!=-1)firstOfRequest = request.substring(0,endIndex);elsefirstOfRequest = request;String[] parts = firstOfRequest.split(" ");String method = parts[0];String uri = parts[1];String userName="";if (method.equalsIgnoreCase("get")){if (uri.indexOf("username=")!=-1){String[] params = uri.substring(uri.indexOf("?") + 8, uri.length()).split("&");String[] params_parts = params[0].split("=");userName = params_parts[1];}}if (method.equalsIgnoreCase("post")){if (request.indexOf("\r\n\r\n")!=-1){String content = request.substring(request.indexOf("\r\n\r\n"+4,request.length()));if (content.indexOf("username=")!=-1){String[] contentParts = content.split("&");userName = (contentParts[0].split("="))[1];}}}userName = URLDecoder.decode(userName,"utf-8");System.out.println(userName);out.write("HTTP/1.1 200 OK\r\n".getBytes());out.write("Content-Type:text/html\r\n\r\n".getBytes());out.write(("<meta charset=\"UTF-8\"> <h1>Hello,"+userName+"</h1>").getBytes());}
}
public interface Servlet {public void init();public void service(String request, OutputStream out) throws IOException;
}

前面说过,动态Web中服务器在接收到请求后,会执行业务逻辑操作,这个业务逻辑操作其实就是由服务器内的servlet模块实现的,下面的图就是上述的代码的执行原理
在这里插入图片描述

如果客户端的URL访问的是servlet目录下,那么就代表是访问动态资源,服务器就会交给servlet处理,否则就会当成普通静态文件处理,从磁盘上取出响应即可。学习过一点如何编写webapp的同学会发现,上述代码中的servlet缓冲池(servletCache)与web.xml中的servlet映射很相似,都是通过名字来映射到一个具体的servlet实现类,服务器动态加载servlet类实现业务逻辑操作也体现了动态Web的特性。
在浏览器的url地址栏输入http://localhost:8080/servlet/HTTPServlet?username=“王小虎”,结果如下在这里插入图片描述
在动态Web中,客户端可以与服务器交互,服务器通过与客户端的交互,来动态响应客户端。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/310647.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hystrix在网关Zuul使用中遇到问题

Hystrix在网关Zuul使用中遇到问题 Zuul默认隔离策略级别是信号量隔离&#xff0c;默认最大隔离信号量是100 信号量隔离和线程隔离的区别&#xff1a;https://blog.csdn.net/liaojiamin0102/article/details/94394956默认的设置如源码&#xff1a; //在ZuulProperties 类下游…

C++ 实现无向图的最小生成树Prim算法(附完整代码)

实现Prim算法&#xff0c;需设置两个辅助一维数组lowcost和closevertex。 其中lowcost用来保存集合V-U中各顶点与集合U中各顶点构成的边中具有最小权值的边的权值&#xff1b;数组closevertex用来保存依附于该边的在集合U中的顶点。 过程: 假设初始状态时&#xff0c;U{u0}&a…

中国速度之二神山建设(2):完善的项目计划,高效能价值流 | IDCF DevOps案例研究...

内容来源&#xff1a;DevOps案例深度研究第4期 – 火神山雷神山 DevOps实践研究战队&#xff08;本文只展示部分PPT及研究成果&#xff0c;全程视频请移步文末。&#xff09;本案例内容贡献者&#xff1a;赖泽薇、张扬、邓茜芸、韦一、刘德权、候利涛、冯利娟、常相宇、张力、韩…

C++ 实现无向图的最小生成树Kruskal算法(完整代码)

按照Kruskal思想&#xff0c;n个结点的生成树有n-1条边&#xff0c;故反复上述过程&#xff0c;直到选取了n-1条边为止&#xff0c;就构成了一棵最小生成树。 实现Kruskal算法的关键问题是&#xff1a; 当一条边加入T的边集中后&#xff0c;如何判断是否构成回路。 一种解决方…

MySql 内连接,外连接查询方式区别

MySql 内连接&#xff0c;外连接查询方式 CREATE TABLE question_test (q_id int(11) DEFAULT NULL,q_name varchar(10) DEFAULT NULL,q_part varchar(10) DEFAULT NULL ) ENGINEInnoDB DEFAULT CHARSETutf8CREATE TABLE answer_test (a_id int(11) DEFAULT NULL,a_name varch…

让我的 .NET Core 博客系统支持 Docker

点击上方蓝字关注“汪宇杰博客”导语我的博客&#xff08;https://edi.wang&#xff09;所使用的博客系统 Moonglade 开源已经一年多了。目前已有至少4位社区朋友使用此系统在 Azure、阿里云上部署了自己的博客。可惜长久以来该系统一直缺乏 Docker 支持&#xff0c;而 .NET Co…

C++ 实现带权有向图的单源点最短路径Dijkstra算法(完整代码)

首先&#xff0c;引进一个辅助向量D&#xff0c;它的每个分量D[i]表示当前所找到的从始点v0到每个终点vi的最短路径的长度。 它的初态为&#xff1a;若从v0到vi有弧&#xff0c;则D[i]为弧上的权值&#xff1b;否则&#xff0c;置D[i]为∞。 显然&#xff0c;长度为 D[j]Min{…

[ASP.NET Core MVC] 如何实现运行时动态定义Controller类型?

昨天有个朋友在微信上问我一个问题&#xff1a;他希望通过动态脚本的形式实现对ASP.NET Core MVC应用的扩展&#xff0c;比如在程序运行过程中上传一段C#脚本将其中定义的Controller类型注册到应用中&#xff0c;问我是否有好解决方案。这是一个挺有意思的问题&#xff0c;我们…

C++ 实现带权有向图的每对顶点之间的最短路径Floyd算法(完整代码)

基本思想是&#xff1a; 假设求从顶点vi到vj的最短路径。 如果从vi到vj有弧&#xff0c;则从vi到vj存在一条长度为arcs[i][j]的路径&#xff0c;该路径不一定是最短路径&#xff0c;尚需进行n次试探。 首先考虑路径&#xff08;vi, v0, vj&#xff09;是否存在&#xff08;判别…

等额本息,等额本金区别

等额本金&#xff0c;等额本息区别 买房银行贷款分为两种&#xff1a; 等额本金和等额本息 等额本息 等额本息定义&#xff1a;还款本金占比逐月递增&#xff0c;利息占比逐月递减&#xff0c;月还款数不变由于每月的还款额度是一样的&#xff0c;其中每个月的还款包括了根…

【视频回放与课件】Build your AI solution with MLOps

4月8日在Global AI Community on Vitural Tour与大家分享了Build your AI solution with MLOps的专题&#xff0c;本课程主要介绍了微软Azure Machine Learning如何使用 , 以及如何通过Azure Machine Learning 结合 MLOps的概念完成机器学习项目的工作。本次Global AI Communit…

C++ 实现分块查找(顺序存储结构)(完整代码)

代码如下: #include <iostream> using namespace std; const int Maxsize 1000; const int MINNUM -999999; class Index_table {friend class SeqList; private:int key;int address; };class SeqList {//该顺序表从下标为0开始 public:~SeqList(){delete[] elem;del…

《五分钟商学院》管理篇学习笔记

【商业知识】| 作者 / Edison Zhou这是恰童鞋骚年的第213篇原创文章在商业篇中&#xff0c;主要探讨的是企业如何处理与外部&#xff08;比如客户&#xff09;的关系。而在管理篇中&#xff0c;关注的重点则是企业如何处理与内部的关系。外部的世界很精彩&#xff0c;而内部的世…

如何在.NET应用程序中分析CPU使用率过高的问题

原文来自互联网&#xff0c;由长沙DotNET技术社区编译。如译文侵犯您的署名权或版权&#xff0c;请联系小编&#xff0c;小编将在24小时内删除。限于译者的能力有限&#xff0c;个别语句翻译略显生硬&#xff0c;还请见谅。作者:胡安帕勃罗希达&#xff0c;JUAN PABLO SCIDA是一…

HashMap实现原理

HashMap HashMap基础数据结构&#xff1a; 如上结构课看出&#xff0c;HashMap主要是有一个链表的形式来存储数据 &#xff0c;上面Node类和C语言中的结构体很像&#xff0c;如上可以看出HashMap底层由是一个数组结构&#xff0c;数组中的每一项又是一个链表&#xff0c;新建一…

做好技术管理,你必须要跨越的4道槛

点击蓝字关注&#xff0c;回复“职场进阶”获取职场进阶精品资料一份读者群里有不少刚开始做管理的技术人&#xff0c;很多都和我谈过他们的困惑。总结下来主要是不知道继续晋升需要培养哪方面的能力。技术经理其实是技术人最难做好的管理岗&#xff0c;原因主要有两方面&#…

图的最小生成树和最短路径算法思路总结(Prim,Kruskal,Dijkstra,Floyd)

带权无向图—>最小生成树算法—>Prim算法: 思路: 首先&#xff0c;我们先设置两个集合&#xff0c;U_{}&#xff1a;一个用来放最小生成树的顶点&#xff0c;T_{}&#xff1a;一个用来放最小生成树的边。选取最开始的点V_0&#xff0c;将V_0放入U_{}中&#xff0c;得到U_…

玩转控件:对Dev的GridControl控件扩展

缘由一切实现来源于需求&#xff0c;目的在于不盲目造轮子&#xff0c;有小伙伴儿在看了《玩转控件:对Dev中GridControl控件的封装和扩展》文章后&#xff0c;私信作者说&#xff0c;因公司业务逻辑比较复杂&#xff0c;展示字段比较多&#xff0c;尤其网格列表控件展示数据太多…

二叉排序树(搜索树BST)-详解结点的删除

在二叉排序树中删除一个结点时&#xff0c;需保证删除后的二叉树仍然是二叉排序树。为讨论方便&#xff0c;假定被删除结点为p&#xff0c;其双亲结点为f。删除的过程可按下述的两种情况分别处理。 在这里我们用红色三角形表示我们要删除的结点&#xff0c;蓝色表示我们要改变指…

java调优方法,jvm监控工具

graph LR A-->B性能概述 程序性能表现形式 执行速度&#xff1a;程序响应速度&#xff0c;总耗时是否足够短内存分配&#xff1a;内存分配是否合理&#xff0c;是否过多消耗内存或者存在泄漏启动时间&#xff1a;程序运行到可以正常处理业务需要的时间负载承受能力 性能测…