在上一篇文章中,我们已经可以通过程序来对web.xml中的配置项进行读取了,现在,我们通过我们自己定义的MyHttpRequest得到访问的URI,然后通过map里面的映射关系,实现游览器对Servlet的访问。
思路分析
我们创建一个MyServletThread类,这个类实现了Runnable接口,这个类里面有一个Socket,这个socket在类创建时必须传入一个Socket,我们通过这个socket就可以得到InputStream和OutputStream,通过这2个流我们就能够创建MyHttpRequest对象和MyHttpResponse对象,其中MyHttpRequest对象可以获取到访问的URI,通过URI和我们在上一篇文章中的map就能够实现对MyServlet的定位。
我们的思路差不多就是这个样子,废话就不说了,直接开始撸代码。
代码实现
首先创建类,实现Runnable接口。
public class MyServletThread implements Runnable{
}
定义Socket成员属性,并在构造器中对Socket进行赋值
//定义一个socket对象
private Socket socket = null;
//在初始化对象时传入socket
public MyServletThread(Socket socket) {
this.socket = socket;
}
实现run方法
@Override
public void run() {
}
我们具体的逻辑就在run方法中进行编写,按照上面的图,我们首先获取到InputStream和OutputStream,并且通过这2个流创建MyHttpRequest和MyHttpResponse
//获取输入流,并且通过输入流创建MyHttpRequest对象
MyHttpRequest request = new MyHttpRequestImpl(socket.getInputStream());
//获取输出流,并且通过输出流创建MyHttpResponse对象
MyHttpResponse response = new MyHttpResponseImpl(socket.getOutputStream());
我们通过MyHttpRequest得到访问的URI
//得到访问的URI
String uri = request.getUri() == null ? "": request.getUri();
下面,我们就通过URI来进行一系列的判断,判断游览器访问的MyServlet是否存在,是不是第一次访问MyServlet等
//判断是否已经创建过MyServlet实例
if(MyServletHandler.PATTERN_CLASS.containsKey(uri)){
//如果已经创建过了,直接调用该MyServlet的service方法
MyServlet myServlet = MyServletHandler.PATTERN_CLASS.get(uri);
myServlet.service(request,response);
}else if (MyServletHandler.PATTERN_NAME.containsKey(uri)){
//如果是第一次访问,我们就创建MyServlet实例,并且将该实例存入map中
String name = MyServletHandler.PATTERN_NAME.get(uri);
String classPath = MyServletHandler.NAME_CLASS.get(name);
MyServlet myServlet = (MyServlet) Class.forName(classPath).newInstance();
MyServletHandler.PATTERN_CLASS.put(uri,myServlet);
//第一次访问是调用init方法和service方法
myServlet.init();
myServlet.service(request,response);
}else {
//如果MyServlet不存在,我们直接返回404 NOT FOUND
response.setStatus(404);
response.write("404 NOT FOUND");
}
完整代码如下
import com.clucky.myTomcat.MyServletHandler;
import com.clucky.myTomcat.myHttp.MyHttpRequest;
import com.clucky.myTomcat.myHttp.MyHttpRequestImpl;
import com.clucky.myTomcat.myHttp.MyHttpResponse;
import com.clucky.myTomcat.myHttp.MyHttpResponseImpl;
import com.clucky.myTomcat.myServlet.MyServlet;
import java.net.Socket;
public class MyServletThread implements Runnable{
//定义一个socket对象
private Socket socket = null;
//在初始化对象时传入socket
public MyServletThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
//获取输入流,并且通过输入流创建MyHttpRequest对象
MyHttpRequest request = new MyHttpRequestImpl(socket.getInputStream());
//获取输出流,并且通过输出流创建MyHttpResponse对象
MyHttpResponse response = new MyHttpResponseImpl(socket.getOutputStream());
//得到访问的URI
String uri = request.getUri() == null ? "": request.getUri();
//判断是否已经创建过MyServlet实例
if(MyServletHandler.PATTERN_CLASS.containsKey(uri)){
//如果已经创建过了,直接调用该MyServlet的service方法
MyServlet myServlet = MyServletHandler.PATTERN_CLASS.get(uri);
myServlet.service(request,response);
}else if (MyServletHandler.PATTERN_NAME.containsKey(uri)){
//如果是第一次访问,我们就创建MyServlet实例,并且将该实例存入map中
String name = MyServletHandler.PATTERN_NAME.get(uri);
String classPath = MyServletHandler.NAME_CLASS.get(name);
MyServlet myServlet = (MyServlet) Class.forName(classPath).newInstance();
MyServletHandler.PATTERN_CLASS.put(uri,myServlet);
//第一次访问是调用init方法和service方法
myServlet.init();
myServlet.service(request,response);
}else {
//如果MyServlet不存在,我们直接返回404 NOT FOUND
response.setStatus(404);
response.write("404 NOT FOUND");
}
//关闭流
socket.close();
} catch (Exception e) {
System.out.println("创建servlet发生异常...");
}
}
}
现在,我们的每一个Servlet都编写好了,我们来创建我们的第3个版本的tomcat。创建一个类,这个类的名字就是MyTomcat03,这个类就是我们的主类,对8080端口进行监听,并负责创建MyServletThread线程对象,开启线程。
代码很简单,下面就直接给出了。
import com.clucky.myTomcat.thread.MyServletThread;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class MyTomcat03{
public void startUp(){
MyServletHandler.init();
try {
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("服务器在8080端口监听");
while (!serverSocket.isClosed()){
Socket socket = serverSocket.accept();
System.out.println("创建了一个线程");
MyServletThread myServletHandler = new MyServletThread(socket);
new Thread(myServletHandler).start();
}
} catch (IOException e) {
System.out.println("启动服务器异常");
}
}
public static void main(String[] args) {
new MyTomcat03().startUp();
}
}
运行MyTomcat进行测试
我们启动MyTomcat03这个类,游览器访问http://localhost:8080/dog ,显示如下
我们再访问http://localhost:8080/cat,显示如下
我们可能忘记了MyDogServlet和MyCatServlet的内容,这2个MyServlet的内容如下
我们发现游览器显示的和我们再doGet中写的一样,说明我们就已经实现了游览器访问MyServlet。