服务器端
package httpProxyServer;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
public class HttpServer1 {
private static Map<String,Servlet> servletCache = new HashMap<String,Servlet>(); // 存放Servlet实例的缓存
public static void main(String[] args) {
// test,我们先用helloWorld测试一下
int port;// 定义服务器需要绑定的本地端口号
ServerSocket serverSocket;// 定义服务器套接口对象
// 不得不吐槽这异常抛的真不正规
try {
port = Integer.getInteger(args[1]);// 将第二个命令行参数转化为整数
} catch (Exception e) {
System.out.println("port = 8880 (默认)");
port = 8880;
}
try {
serverSocket = new ServerSocket(port);
System.out.println("服务器正在监听端口:" + serverSocket.getLocalPort());
while (true) {
try {
final Socket socket = serverSocket.accept();
System.out.println("建立了与客户的新的TCP连接,该客户的地址为:" + socket.getInetAddress() + ":" + socket.getPort());
service(socket);
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void service(Socket socket) throws Exception {
// 读取http请求信息
InputStream socketIn = socket.getInputStream();// 创建输入流通道
Thread.sleep(500);
int size = socketIn.available();// 获取输入流中缓存的大小
byte[] buffer = new byte[size];// 根据缓存大小在缓存外面建立缓存buffer
socketIn.read(buffer);// 读取缓存信息到buffer中
String request = new String(buffer);// 将缓存buffer中的字节放到字符串中
System.out.println(request);// 输出字符串
// 解析http请求信息
String firstLineOfRequest = request.substring(0, request.indexOf("\n\r"));
String[] parts = firstLineOfRequest.split(" ");
String uri = parts[1];
if (uri.indexOf("servlet") != -1) {
// 获取servlet的名字
String servletName = null;
if(uri.indexOf("?") != -1)
servletName = uri.substring(uri.indexOf("servlet/") + 8,uri.indexOf("?"));
else
servletName = uri.substring(uri.indexOf("servlet/") + 8,uri.length());
//尝试从servlet缓存获取servlet对象
Servlet servlet = (Servlet)servletCache.get(servletName);
//如果servlet缓存中不存在servlet对象,就创建它,并将它放到servlet缓存中
if (servlet == null) {
//这边由于Servlet是抽象接口,必须由子类实现,所以子类必须都要强转为父类
servlet = (Servlet)Class.forName("servlet." + servletName).newInstance();//这边先简单理解为创建一个对象,动态加载类,和new Servlet()的具体区别请参考反射原理
servlet.init();
servletCache.put(servletName, servlet);
}
//调用Servlet的service()方法
servlet.service(buffer,socket.getOutputStream());
Thread.sleep(1000);
socket.close();
return;//这边有个小细节,如果能找到动态加载的时候,就不需要再执行下面的静态加载方法,直接返回就好
}
//....由于演示的是动态加载,为了降低理解难度,静态加载就省略
}
}
package httpProxyServer;
import java.io.OutputStream;
//这是一个接口类,类中的所有方法都必须在子类中实现
public interface Servlet {
public void init() throws Exception;
public void service(byte[] buffer, OutputStream outputStream) throws Exception;
}
package servlet;
import java.io.OutputStream;
import java.io.StreamCorruptedException;
import httpProxyServer.Servlet;
public class HelloServlet implements Servlet {
@Override
public void init() throws Exception {
System.out.println("这边是servlet的初始化!");
}
@Override
public void service(byte[] buffer, OutputStream outputStream) throws Exception {
String request = new String(buffer);
//获取http请求的第一行
String firstLineOfReqest = request.substring(0,request.indexOf("\r\n"));
//解析http请求的第一行
String[] parts = firstLineOfReqest.split(" ");
String method = parts[0];
String uri = parts[1];
String username = null;
//如果请求方式为get
if(method.equalsIgnoreCase("get") && uri.indexOf("username=") != -1){
String parameters = uri.substring(uri.indexOf("?"),uri.length());
parts = parameters.split("&");
parts = parts[0].split("=");
username = parts[1];
}
//如果请求方式为post
if (method.equalsIgnoreCase("post")) {
int locate = request.indexOf("\r\n\r\n");
//获得响应正文
String content = request.substring(locate+4,request.length());
if(content.indexOf("username") != -1){
parts = content.split("&");
parts = parts[0].split("=");
username = parts[1];
}
}
//创建并发送http响应
outputStream.write("HTTP/1.1 200 OK\r\n".getBytes());//响应首部
outputStream.write("Content-type: text/html\r\n\r\n".getBytes());//响应头
outputStream.write("<html><head><title>HelloWorld</title></head><body>".getBytes());
outputStream.write(new String("<h1>Hello:"+username+"</h1></body></html>").getBytes());
}
}
客户端
package httpProxyServer;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class HttpClient1 {
public static void main(String[] args) {
//相比较于静态客户端,这边uri变了,servlet是给服务器去判断是不是需要通过servlet类动态加载资源,/后面是要求处理业务的具体的servlet子类
String uri = "servlet/HelloServlet";
if(args.length != 0) uri=args[0];//这边需要区别c语言下的参数,这边的第一个参数是不包括命令行自身的。
doGet("localhost",8880,uri);
}
private static void doGet(String host, int port, String uri) {
Socket socket = null;
try {
socket = new Socket(host,port);
} catch (Exception e) {
e.printStackTrace();
}
try {
//创建http请求
StringBuffer sb = new StringBuffer("GET " + uri + " HTTP/1.1\r\n");
sb.append("Accept: */*\r\n");
sb.append("Accept-Encoding: gzip,deflate\r\n");
sb.append("Accept-Language: zh-cn\r\n");
sb.append("User-Agent: HTTPClient\r\n");
sb.append("Connection: Keep-Alive\r\n\r\n");
//发送http请求
OutputStream socketOut = socket.getOutputStream();
socketOut.write(sb.toString().getBytes());
Thread.sleep(2000);
//接收响应结果
InputStream socketIn = socket.getInputStream();
int size = socketIn.available();
byte[] buffer = new byte[size];
socketIn.read(buffer);
System.out.println(new String(buffer));
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}