浅析Tomcat原理(一个简单的web应用服务器)
2014-09-05 21:54
429 查看
Tomcat是一个jsp和servlet的容器,缺少了这个容器,web程序就不能得以实现。
学过Java的人都知道socket吧?tomcat其实就是一个ServerSocket服务器,一个普通的HTTP请求的过程是:
三次握手建立连接——浏览器发送请求——服务器响应
我们平时通过浏览器去访问资源的时候,需要在地址栏上输入url地址,其实你访问url地址就是你访问该服务器上的资源。为什么称作访问资源呢?我们称互联网上的各种各样的文件叫做资源,平时我们在建立一个网站的时候,需要建立那些html文件、图片文件等,都是资源,当我们请求资源的时候过程是这样子的:我们从浏览器中输入远程服务器上该资源的位置,也就是URI(统一资源定位符),当tomcat服务器接收到这个HTTP请求之后呢,就会解析报文里面的uri,得到这个Uri之后,服务器就会在webroot相应的目录下找到该资源,并且通过IO流去读取这个文件,然后把这个文件以流的形式返回给浏览器。当然,我们需要指定contentType来确定输出的是什么流,假如是普通的text/html,则返回的也就是基于浏览器解析的数据,让浏览器解析成为我们可以看到的页面。
下面我们来写一个简单的web服务器来说明:
先是一个HttpServer类:
Request:
此类有两个方法,parse()方法用来解析请求中的信息,此处使用字符串来存储请求报文数据,parseUri()方法则是在请求报文中解析出Uri来
Response:
此类只有一个方法sendResponse(),用来响应请求,返回数据,根据请求中的uri到webroot目录下寻找资源,如果找到,使用输出流写出该资源文件;否则,使用输出流写出页面找不到的页面。
下面的是常量类:
现在我们需要测试一下,首先在改项目下新建一个webroot文件夹来存放资源文件,然后在webroot目录下建立一个index.html文件,内容自定,然后执行HttpServer文件,在浏览器中输入http://localhost:8888/index.html,然后就可以访问啦。
这只是一个简单的web应用服务器,tomcat涉及到的知识远远不止这些,多用户访问还涉及到多线程编程,性能调优涉及到线程池等等。。
学过Java的人都知道socket吧?tomcat其实就是一个ServerSocket服务器,一个普通的HTTP请求的过程是:
三次握手建立连接——浏览器发送请求——服务器响应
我们平时通过浏览器去访问资源的时候,需要在地址栏上输入url地址,其实你访问url地址就是你访问该服务器上的资源。为什么称作访问资源呢?我们称互联网上的各种各样的文件叫做资源,平时我们在建立一个网站的时候,需要建立那些html文件、图片文件等,都是资源,当我们请求资源的时候过程是这样子的:我们从浏览器中输入远程服务器上该资源的位置,也就是URI(统一资源定位符),当tomcat服务器接收到这个HTTP请求之后呢,就会解析报文里面的uri,得到这个Uri之后,服务器就会在webroot相应的目录下找到该资源,并且通过IO流去读取这个文件,然后把这个文件以流的形式返回给浏览器。当然,我们需要指定contentType来确定输出的是什么流,假如是普通的text/html,则返回的也就是基于浏览器解析的数据,让浏览器解析成为我们可以看到的页面。
下面我们来写一个简单的web服务器来说明:
先是一个HttpServer类:
package com.ccw.server; import java.io.File; 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.net.UnknownHostException; import com.ccw.request.Request; import com.ccw.response.Response; public class HttpServer { private static final String SHUTDOWN_COMMAND = "/SHUTDOWN"; private boolean isShutdown = false; private int portNum = 8888; public void start() { ServerSocket serverSocket = null; int port = portNum; try { serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1")); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); System.exit(1); } while (!isShutdown) { Socket socket = null; InputStream is = null; OutputStream os = null; try { //等待请求 System.out.println("=====等待请求======"); socket = serverSocket.accept(); System.out.println("=====建立请求======"); is = socket.getInputStream(); os = socket.getOutputStream(); Request request = new Request(is); //解析请求 request.parse(); Response response = new Response(os); response.setRequest(request); //响应 response.sendResponse(); System.out.println("======返回响应信息======="); socket.close(); System.out.println("======连接关闭======="); isShutdown = request.getUri().equals(SHUTDOWN_COMMAND); } catch (Exception e) { e.printStackTrace(); continue; } } } public static void main(String[] args) { HttpServer server = new HttpServer(); server.start(); System.out.println("==========启动成功========="); } }接下来分别是Request类和Response类:
Request:
此类有两个方法,parse()方法用来解析请求中的信息,此处使用字符串来存储请求报文数据,parseUri()方法则是在请求报文中解析出Uri来
package com.ccw.request; import java.io.IOException; import java.io.InputStream; public class Request { //用来读取请求中的数据 private InputStream is; private String uri; public Request(InputStream is) { this.is=is; } /** * 解析请求 */ public void parse() { //以字符串的形式存储request报文 StringBuffer request=new StringBuffer(2048); int i; byte[] buffer=new byte[2048]; try { i=is.read(buffer); } catch (IOException e) { e.printStackTrace(); i=-1; } for(int j=0;j<i;j++){ request.append((char)buffer[j]); } System.out.println(request.toString()); uri=parseUri(request.toString()); } /** * 解析uri * @param requestStr * @return */ private String parseUri(String requestStr) { int index1,index2; index1=requestStr.indexOf(' '); if(index1!=-1){ index2=requestStr.indexOf(' ', index1+1); if(index2>index1){ return requestStr.substring(index1,index2); } } return null; } public String getUri() { return this.uri; } }
Response:
此类只有一个方法sendResponse(),用来响应请求,返回数据,根据请求中的uri到webroot目录下寻找资源,如果找到,使用输出流写出该资源文件;否则,使用输出流写出页面找不到的页面。
package com.ccw.response; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import com.ccw.request.Request; import com.ccw.server.Constants; public class Response { //一次读取的长度 private static final int BUFFER_SIZE=1024; Request request; //用来写数据返回到页面 OutputStream os; public Response(OutputStream os) { this.os=os; } public void setRequest(Request request) { this.request=request; } /** * 响应请求 */ public void sendResponse() { byte[] bytes=new byte[BUFFER_SIZE]; FileInputStream fis=null; try { //在webroot目录下寻找所请求的资源 File file=new File(Constants.WEB_ROOT, request.getUri().trim()); System.out.println(Constants.WEB_ROOT+request.getUri().trim()); //如果资源存在,则返回数据 if(file.exists()){ fis=new FileInputStream(file); int ch=fis.read(bytes,0,BUFFER_SIZE); while(ch!=-1){ os.write(bytes, 0, BUFFER_SIZE); ch=fis.read(bytes, 0, BUFFER_SIZE); } //否则返回404错误 }else{ String errorMsg="HTTP/1.1 404 File Not Found\r\n"+ "Content-Type:text/html\r\n"+"Content-Length:23\r\n"+ "\r\n<h1>File Not Found</h1>"; os.write(errorMsg.getBytes()); } } catch (Exception e) { System.out.println(e.toString()); e.printStackTrace(); }finally{ if(fis!=null){ try { fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
下面的是常量类:
package com.ccw.server; import java.io.File; public class Constants { public static final String WEB_ROOT = System.getProperty("user.dir") + File.separator + "webroot";; }写完了这几个类之后,一个简单的web应用服务器就完成了啦
现在我们需要测试一下,首先在改项目下新建一个webroot文件夹来存放资源文件,然后在webroot目录下建立一个index.html文件,内容自定,然后执行HttpServer文件,在浏览器中输入http://localhost:8888/index.html,然后就可以访问啦。
这只是一个简单的web应用服务器,tomcat涉及到的知识远远不止这些,多用户访问还涉及到多线程编程,性能调优涉及到线程池等等。。
相关文章推荐
- 浅析Spring原理,手写一个简单的Spring
- tomcat原理解析(一):一个简单的实现
- Skinned Mesh 原理解析和一个最简单的实现示例
- Skinned Mesh原理解析和一个最简单的实现示例
- jBPM4.2 安装到tomcat 和 mysql上的步骤。并且创建一个最简单的应用
- 一个简单的AOP原理
- 学习Java的第一步是安装好JDK,写一个Hello World, 其实JDK的学习没有那么简单,关于JDK有两个问题是很容易一直困扰Java程序员的地方:一个是CLASSPATH的问题,其实从原理上来说,是要搞清楚JRE的ClassLoader是如何加
- 一个剖析AJAX原理的简单范例
- Skinned Mesh原理解析和一个最简单的实现示例(转)
- [How Tomcat Works]第2章 一个简单的Servlet容器
- 用JSP+Servlet+JavaBean模式实现一个简单的登录网页设计(JSP+Tomcat+MySQL)
- 一个简单的Servlet框架(帮助理解Servlet原理)
- 一个简单的tomcat部署方案
- tomcat配置及使用(环境变量设置及测试,一个简单的web应用实例)
- 【转】解压缩版tomcat配置及使用(环境变量设置及测试,一个简单的web应用实例)
- 一个简单的示例讲解游戏游戏编程原理。附示例源码
- EJB原理之(六)--范例--一个简单的事务容器
- 一个自写的共享内存简单的例子,学习原理之用
- [置顶] Skinned Mesh原理解析和一个最简单的实现示例
- 一个简单的示例讲解游戏游戏编程原理。附示例源码(转)