设为首页 收藏本站
查看: 655|回复: 0

[经验分享] 浅析Tomcat原理(一个简单的web应用服务器)

[复制链接]

尚未签到

发表于 2017-2-6 06:10:03 | 显示全部楼层 |阅读模式
  Tomcat是一个jsp和servlet的容器,缺少了这个容器,web程序就不能得以实现。
  学过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涉及到的知识远远不止这些,多用户访问还涉及到多线程编程,性能调优涉及到线程池等等。。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-337937-1-1.html 上篇帖子: 配置了derby数据库后启动tomcat 服务报错 下篇帖子: Debug Tomcat时发生java.library.path错误的解决方法
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表