一个简单的Web服务器-支持Servlet请求
上接 一个简单的Web服务器-支持静态资源请求,这个服务器可以处理静态资源的请求,那么如何处理Servlet请求的呢?
判断是否是Servlet请求
首先Web服务器需要判断当前请求是否是Servlet请求。
像Tomcat,通过解析HTTP报文拿到请求url后,就可以根据web.xml来查找是否有匹配的Servlet,如果有匹配则认定为是一个有效的Servlet请求,然后将request,response传给对应的servlet的service()方法。
这里既然要实现一个简单的Web服务器,就怎么简单怎么来。认定以“/servlet”为前缀的url为Servlet请求,比如http://localhost:8080/servlet/cn.edu.jxau.tomcat.PrimitiveServlet,则是一个请求cn.edu.jxau.tomcat.PrimitiveServlet的Servlet请求。判定逻辑如下
// HttpServer 类的service()方法,是整个服务器的入口
while (true) {
try (Socket socket = serverSocket.accept()) {
System.out.println("客户端建立连接:" + socket);
Request request = new Request(socket.getInputStream());
if (Objects.isNull(request.getUri())) {
continue;
}
if (isShutdownComment(request)) { //如果是shutdown命令,则关闭服务器
break;
}
Response response = new Response(request, socket.getOutputStream());
if (request.getUri().startsWith("/servlet/")) { // 请求Servlet资源
new ServletProcessor().process(request, response);
} else { // 请求静态资源
response.sendStaticResource();
// 书上使用了StaticResourceProcessor new StaticResourceProcessor().process(request,response);
}
} catch (Exception e) {
e.printStackTrace();
}
}
加载Servlet
如果确实是Servlet请求,下一步就是实例化Servlet并调用service()方法。
首先需要知道请求是哪个Servlet:根据url拿到Servlet的名称
然后需要调用Servlet的service()方法:使用ClassLoader加载对应的Servlet字节码,然后实例化Servlet,调用service()方法,传入request,response。
// ServletProcessor 类的process()方法,用于处理Servlet请求
public void process(Request request, Response response) throws IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, ServletException { String uri = request.getUri();
String servletName = uri.substring(uri.lastIndexOf("/") + 1);
File file = new File(Constants.WEB_ROOT);
String urlStr = new URL("file", null, file.getCanonicalPath() + File.separator).toString(); //使用File协议
URL[] urlArr = new URL[1];
urlArr[0] = new URL(urlStr);
System.out.println(Arrays.toString(urlArr));
URLClassLoader loader = new URLClassLoader(urlArr);
Class clazz = loader.loadClass(servletName); // 根据Servlet的全路径名加载Servlet字节码
Servlet servlet = (Servlet) clazz.newInstance(); // 实例化Servlet
servlet.service(request, response); //调用Servlet.service()
}
PrimitiveServlet的实现如下,实现了Servlet接口,service()方法的实现是重点。
public class PrimitiveServlet implements Servlet {
public void init(ServletConfig config) throws ServletException {
System.out.println("-----init");
}
public void service(ServletRequest request, ServletResponse response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("HTTP/1.1 200 Status OK\r\n");
out.println("Content-Type: text/html\r\n");
out.println("Content-Length: 36\r\n");
out.println("\r\n");
out.println("<h1>Status OK</h1>");
out.print("<h1>Status OK</h1>");
}
public void destroy() {
System.out.println("-------destroy");
}
public String getServletInfo() {
return null;
}
public ServletConfig getServletConfig() {
return null;
}
}
参考
1.《How Tomcat Works》 - Budi Kurniawan
一个简单的Web服务器-支持Servlet请求的更多相关文章
- 一个简单的Web服务器-支持静态资源请求
目标 实现一个简单的Web服务器,能够根据HTTP请求的URL响应对应的静态资源,如果静态资源不存在则响应404. HttpServer 使用ServerSocket实现的一个服务器,request根 ...
- Tomcat剖析(一):一个简单的Web服务器
Tomcat剖析(一):一个简单的Web服务器 1. Tomcat剖析(一):一个简单的Web服务器 2. Tomcat剖析(二):一个简单的Servlet服务器 3. Tomcat剖析(三):连接器 ...
- 自己模拟的一个简单的web服务器
首先我为大家推荐一本书:How Tomcat Works.这本书讲的很详细的,虽然实际开发中我们并不会自己去写一个tomcat,但是对于了解Tomcat是如何工作的还是很有必要的. Servlet容器 ...
- 自己动手模拟开发一个简单的Web服务器
开篇:每当我们将开发好的ASP.NET网站部署到IIS服务器中,在浏览器正常浏览页面时,可曾想过Web服务器是怎么工作的,其原理是什么?“纸上得来终觉浅,绝知此事要躬行”,于是我们自己模拟一个简单的W ...
- 一个简单的web服务器
写在前面 新的一年了,新的开始,打算重新看一遍asp.net本质论这本书,再重新认识一下,查漏补缺,认认真真的过一遍. 一个简单的web服务器 首先需要引入命名空间: System.Net,关于网络编 ...
- [置顶] 在Ubuntu下实现一个简单的Web服务器
要求: 实现一个简单的Web服务器,当服务器启动时要读取配置文件的路径.如果浏览器请求的文件是可执行的则称为CGI程序,服务器并不是将这个文件发给浏览器,而是在服务器端执行这个程序,将它的标准输出发给 ...
- 利用 nodeJS 搭建一个简单的Web服务器(转)
下面的代码演示如何利用 nodeJS 搭建一个简单的Web服务器: 1. 文件 WebServer.js: //-------------------------------------------- ...
- 《深度解析Tomcat》 第一章 一个简单的Web服务器
本章介绍Java Web服务器是如何运行的.从中可以知道Tomcat是如何工作的. 基于Java的Web服务器会使用java.net.Socket类和java.net.ServerSocket类这两个 ...
- 如何用PHP/MySQL为 iOS App 写一个简单的web服务器(译) PART1
原文:http://www.raywenderlich.com/2941/how-to-write-a-simple-phpmysql-web-service-for-an-ios-app 作为一个i ...
随机推荐
- 洛谷P2051 中国象棋
题目描述 这次小可可想解决的难题和中国象棋有关,在一个N行M列的棋盘上,让你放若干个炮(可以是0个),使得没有一个炮可以攻击到另一个炮,请问有多少种放置方法.大家肯定很清楚,在中国象棋中炮的行走方式是 ...
- Flutter SDK path为空导致工程打开后不显示iOS模拟器的问题
说明下问题场景,面向git编程时下载了个开源的Flutter项目 Mac系统下AndroidStudio打开工程后,发现顶部不展示iPhone模拟器 根据ide浅黄色提示提示,判断是FlutterSD ...
- phpcms url路由规则、多站点、PC手机切换
解决一个分站点pc手机共存的问题 首先需要有PC手机两套模板.通过修改url路由规则,在同一目录下生成PC手机两套静态网站,PC使用默认url路由规则,手机端使用文件名追加“_m”的路由规则. 然后通 ...
- MaxCompute 费用暴涨之新增SQL分区裁剪失败
现象:因业务需求新增了SQL任务,这SQL扫描的表为分区表,且SQL条件里表只指定了一个分区,按指定的分区来看数据量并不大,但是SQL的费用非常高.费用比预想的结果相差几倍甚至10倍以上. 若只知道总 ...
- 2019-8-31-cmd-如何跨驱动器移动文件夹
title author date CreateTime categories cmd 如何跨驱动器移动文件夹 lindexi 2019-08-31 16:55:58 +0800 2019-02-27 ...
- Python 变量赋值
- @atcoder - AGC034E@ Complete Compress
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个 N 个点的树,编号为 1, 2, ..., N.第 i ...
- @codeforces - 590E@ Birthday
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定 n 个互不相同的只包含 'a', 'b' 的字符串. 请选 ...
- Android教程 -05 Android6.0权限的管理
视频为本篇博客知识的讲解,建议采用超清模式观看, 欢迎点击订阅我的优酷 上篇文章我们讲解了通过隐式意图拨打电话,在AndroidManifest.xml文件中添加了权限 <uses-permis ...
- 【转载】Windows平台分布式架构实践 - 负载均衡
概述 最近.NET的世界开始闹腾了,微软官方终于加入到了对.NET跨平台的支持,并且在不久的将来,我们在VS里面写的代码可能就可以通过Mono直接在Linux和Mac上运行.那么大家(开发者和企业)为 ...