手动实现tomcat服务器的流程:
分析具体的实现步骤:
1,浏览器和后端服务如何实现通信,首先传输的数据要遵循http协议,通过tcp也就是我们常说的套接字编程来实现,具体的底层数据传输肯定就是我们的输入输出流来实现了。
2,我们再来看后台服务器的实现逻辑,首先我们要定义两个对象,一个request,一个response分别用来存放请求的参数以及返回的参数。
3,创建一个ServerSocket,等待浏览器的连接和数据传输,当通过输入流读取到数据,放入到request对象。
4,浏览器的请求类型一般分为get和post两种,所以我们需要一个mpper映射类来根据浏览器的访问路径来分发具体处理的类或者方法。
5,处理之后获取处理的结果,并放到response对象,通过输出流返回给浏览器。
下面是具体的代码实现:
1,reques类
package com.liuyi; import java.io.InputStream; public class MyRequest { //请求方法 GET/POST private String requestMethod; //请求地址 private String requestUrl; public MyRequest(InputStream inputStream) throws Exception{ //缓冲区域 byte[] buffer = new byte[1024]; //读取数据的长度 int len = 0; //定义请求的变量 String str = null; if((len = inputStream.read(buffer))>0){ str = new String(buffer,0,len); } // GET / HTTP/1.1 String data = str.split(" ")[0]; String[] params = data.split(" "); this.requestMethod = params[0]; this.requestUrl = params[1]; } public String getRequestMethod() { return requestMethod; } public void setRequestMethod(String requestMethod) { this.requestMethod = requestMethod; } public String getRequestUrl() { return requestUrl; } public void setRequestUrl(String requestUrl) { this.requestUrl = requestUrl; } }
2,response类
package com.liuyi; import java.io.OutputStream; public class MyResponse { private OutputStream outputStream; public MyResponse(OutputStream outputStream) { this.outputStream = outputStream; } public void write(String str) throws Exception{ StringBuilder builder = new StringBuilder(); builder.append("HTTP/1.1 200 OK ") .append("Content-Type:text/html ") .append(" ") .append("<html>") .append("<body>") .append("<h1>"+str+"</h1>") .append("</body>") .append("</html>"); this.outputStream.write(builder.toString().getBytes()); this.outputStream.flush(); this.outputStream.close(); } }
3,Mapping类,定义请求路径和请求处理类的关系
package com.liuyi; import java.util.HashMap; public class MyMapping { public static HashMap<String,String> mapping = new HashMap<String,String>(); static {
//这里请改成自己servlet实现类的完全限定名 mapping.put("/mytomcat","com.liuyi.MyServlet"); } public HashMap<String,String> getMapping(){ return mapping; } }
4,定义HpptServlet抽象类,实现get和post的分发(根据不同的请求方式调用不同的方法进行处理)
package com.mashibing; public abstract class MyHttpServlet { //定义常量 public static final String METHOD_GET = "GET"; public static final String METHOD_POST = "POST"; public abstract void doGet(MyRequest request,MyResponse response) throws Exception; public abstract void doPost(MyRequest request,MyResponse response) throws Exception; /** * 根据请求方式来判断调用哪种处理方法 * @param request * @param response */ public void service(MyRequest request,MyResponse response) throws Exception{ if(METHOD_GET.equals(request.getRequestMethod())){ doGet(request,response); }else if(METHOD_POST.equals(request.getRequestMethod())){ doPost(request,response); } } }
5,定义自己的servlet
package com.liuyi; public class MyServlet extends MyHttpServlet{ @Override public void doGet(MyRequest request, MyResponse response) throws Exception { response.write("mytomcat get"); } @Override public void doPost(MyRequest request, MyResponse response) throws Exception { response.write("post tomcat"); } }
6,定义服务端的接受程序,接受socket请求
package com.liuyi; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class MyServer { /** * 定义服务端的接受程序,接受socket请求 * @param port */ public static void startServer(int port) throws Exception{ //定义服务端套接字 ServerSocket serverSocket = new ServerSocket(port); //定义客户端套接字 Socket socket = null; while (true){ socket = serverSocket.accept(); //获取输入流和输出流 InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream(); //定义请求对象 MyRequest request = new MyRequest(inputStream); //定义响应对象 MyResponse response = new MyResponse(outputStream); String clazz = new MyMapping().getMapping().get(request.getRequestUrl()); if(clazz!=null){ Class<MyServlet> myServletClass = (Class<MyServlet>)Class.forName(clazz); //根据myServletClass创建对象 MyServlet myServlet = myServletClass.newInstance(); myServlet.service(request,response); } } } //运行启动 public static void main(String[] args) { try { startServer(10086); } catch (Exception e) { e.printStackTrace(); } } }
总结:
本案例只是实现了简单的tomcat和servlet,仅仅只是为了让我们学习servlet和tomcat没有那么多的疑惑,学起来会更容易。实际工作中当然也不会这样去写,
但是如果你认值把这个代码敲一遍,并理解为什么这样写,那么对你学习java web肯定会有很大的帮助。