Tomcat服务器本质上就是一个 Server的程序,所以这里我们先写一个Server的程序和一个Socket程序,然后在对其进行改装
Server服务端的程序见下文所示
public class Server {
/*
Tomcat其实就是一个socket编程
下面的流程中 有两个流程,
第一个流程是 客户端请求浏览器的流程
第二个业务流程是 服务器给客户端返回数据的业务流程
两个业务类型不同,在这里可以抽取两个业务类 来分别抽取 两个不同的业务类
抽取HttpRequest 和 HttpResponse 两种业务
*/
public static void main(String[] args) {
//发送信息的电报机
ServerSocket serverSocket = null;
Socket client = null;
try{
serverSocket = new ServerSocket( 8888 );
System.out.println("服务器初始化完毕,初始化的端口是 8888");
//这里在不断的接收客户端请求
while(true){
//服务端接收客户端的Socket连接过来
client = serverSocket.accept();
//对客户端端里面的请求信息进行处理
InputStream in = client.getInputStream();
//定义一个读取缓冲流,主要是在InputStream流当中读取这些字节
byte[] buff = new byte[1024];
int len = in.read(buff);
if(len>0){
String msg = new String(buff,0,len);
System.out.println("客户端请求信息!"+"============"+msg+"============");
OutputStream os = client.getOutputStream();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//构建一个响应头信息 200 OK
StringBuffer sb = new StringBuffer();
//响应头信息
sb.append("HTTP/1.1 200 OK\n");
sb.append("Content-Type: text/html;charset=UTF-8\n");
sb.append("cahce-control:max-age-0");
sb.append("Upgrade-Insecure-Requests: 1");
sb.append("User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36");
sb.append("Accept-Encoding:gzip, deflate, br");
sb.append("Accept-Language:zh-CN,zh;q=0.9");
sb.append("\r\n");
//响应正文
String html = "欢迎各位同学 当前时间:" +
"" +
format.format(new Date()) +
"
服务器回复: 大家今天有收货吗 " +
"
服务器回复:大家今天有收获吗" +
"";
//把响应头和正文都连接在了一起
sb.append(html);
//响应业务,
os.write(sb.toString().getBytes());
os.flush();
os.close();
}
}
}catch(Exception e){
}
}
public class Client {
public static void main(String[] args) {
try {
Socket s = new Socket("127.0.0.1",8888);
//构建IO
InputStream is = s.getInputStream();
OutputStream os = s.getOutputStream();
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(os));
//向服务器端发送一条消息
bw.write("测试客户端和服务器通信,服务器接收到消息返回到客户端\n");
bw.flush();
//读取服务器返回的消息
/*
BufferedReader br = new BufferedReader(new InputStreamReader(is) );
String line = br.readLine();
System.out.println( line );
*/
StringBuffer sb = new StringBuffer();
int len = 0;
byte[] buff = new byte[1024];
while( (len = is.read(buff) )!=-1 ){
sb.append( new String(buff,0,len) );
}
System.out.println( sb.toString() );
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
启动服务端然后便可以看到客户端与服务器端互相通信已经畅通
然后考虑到tomcat中在实现其功能的时候需要将其业务拆分,拆分成 处理请求的一部分和返回响应的一部分,所以这里对代码进行改进,新建一个Server2.java,项目的目录结构如下图所示:
Server2.java代码
package com.zwz;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
public class Server2 {
static SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static void main(String[] args) {
try {
ServerSocket ss = new ServerSocket(8888);
System.out.println("启动服务器....8888端口");
while(true){
Socket s = ss.accept();
System.out.println("客户端:"+s.getInetAddress().getLocalHost()+"已连接到服务器");
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
HttpRequest request = new HttpRequest( s.getInputStream() );
String requesturi = request.getUri();
System.out.println("请求路径是:"+requesturi);
HttpResponse response = new HttpResponse(s.getOutputStream());
//if(isStatic(requesturi)){
response.writeFile(requesturi);
//}
s.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//静态资源的重复获取需要通过过滤
public static boolean isStatic( String uri ){
boolean isStatic = false;
String []suffixs = {"html","css","js","jpg","png","gif","bmp"};
for( String suffix : suffixs){
if(uri.endsWith("."+suffix)){
isStatic = true;
break;
}
}
return isStatic;
}
}
HttpReuqest.java代码:
package com.zwz;
import java.io.IOException;
import java.io.InputStream;
public class HttpRequest {
private String uri;
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
public HttpRequest(InputStream in) throws IOException{
resolverRequest(in);
}
private void resolverRequest(InputStream in) throws IOException {
//1.读取 客户端请求过来的数据,解析出来uri
byte[] buff = new byte[1024];
int len = in.read(buff);
if( len>0 ){
String msg = new String(buff,0,len);
System.out.println("客户端请求信息");
System.out.println("客户端请求过来的数据是:" + msg );
this.uri = msg.substring( 4,msg.indexOf("HTTP/1.1") );
}else{
System.out.println("bad request!");
}
}
public static void main(String[] args) {
}
}
HttpResponse.java代码
package com.zwz;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
public class HttpResponse {
private OutputStream out = null;
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
public HttpResponse(OutputStream out) {
super();
this.out = out;
}
//这个方法的作用是把请求的地址传递进来,服务器这个时候向客户端回写响应的文件数据等
public void writeFile( String path ) throws IOException{
String basepath = new File("").getCanonicalPath();
FileInputStream fis = new FileInputStream( basepath +"/"+ path);
byte[] buff = new byte[1024];
int len = 0;
StringBuffer sb = new StringBuffer();
//拼凑响应头信息
sb.append("HTTP/1.1 200 OK\n");
//sb.append("Content-Type: text/html;charset=UTF-8\n");
sb.append("\r\n");
//响应业务,
out.write(sb.toString().getBytes());
while((len=fis.read(buff))!=-1){
out.write(buff,0,len);
}
fis.close();
out.flush();
out.close();
}
}
这个时候运行 server2.java这个文件
在浏览器地址蓝输入 localhost:8888/test/demo.html,显示页面如下
ok,到这里大功告成,已经手写实现了一个简单的tomcat 服务