一、tomcat本质上是一个HTTP服务器,核心是servlet容器
二、原理
Connector是用来“连接”容器里边的请求的。Connector是为接收到每一个 HTTP 请求构造一个 request 和 response 对象。然后它把流程传递给容器。容器从连接器接收到 requset 和 response 对象,之后调用 servlet 的 service 方法用于响应。例如,在它调用 servlet 的 service 方法之前,它必须加载这个 servlet,验证用户(假如需要的话),更新用户会话等等。
三、服务器功能点
1. 需要有一个类去接收http请求;
2. 需要一个自定义Request类和Response类,把接收到的请求构造成这两个类;
3. 根据请求的格式来确定处理方式:返回静态资源 or 进入Servlet ?
4. 需要一个Servlet类执行业务逻辑
四、构造HttpServer类
public class HttpServer { private static final String SHUTDOWN_COMMAND = "/SHUTDOWN"; private static boolean shutdown = false; public static void main(String[] args) { HttpServer server = new HttpServer(); server.await(); } public static void await() { ServerSocket serverSocket = null; int port = 8080; try { serverSocket = new ServerSocket(port, 1, InetAddress.getByName("127.0.0.1")); } catch (IOException e) { e.printStackTrace(); System.exit(1); } while (!shutdown) { Socket socket = null; InputStream input = null; OutputStream output = null; try { socket = serverSocket.accept(); input = socket.getInputStream(); output = socket.getOutputStream(); // create Request object and parse Request request = new Request(input); request.parseUrl(); // create Response object Response response = new Response(output); response.setRequest(request); if (request.getUri().startsWith("/v2/")) { ServletProcessor processor = new ServletProcessor(); processor.process(request, response); } else { StaticResourceProcessor processor = new StaticResourceProcessor(); processor.process(request, response); } // Close the socket socket.close(); //check if the previous URI is a shutdown command shutdown = request.getUri().equals(SHUTDOWN_COMMAND); } catch (Exception e) { e.printStackTrace(); System.exit(1); } } } }
服务器启动入口放在了HttpServer里面。await()方法负责接收Socket连接,只有当用户输入了代表shutdown的URL时,服务器才会停止运行。Request类提供了解析请求的功能,根据请求的url,来决定是返回静态资源,或者进入对应的servlet类执行service逻辑。
ServerSocket这个类的用法。Socket 类代表一个客户端套接字,即任何时候你想连接到一个远程服务器应用的时候,你都会第一时间想到这个类。而ServerSocket 和 Socket 不同,服务器套接字的角色是等待来自客户端的连接请求。一旦服 务器套接字获得一个连接请求,它创建一个 Socket 实例来与客户端进行通信。 ServletSocket套接字的其中一个构造函数为
public ServerSocket(int port, int backLog, InetAddress bindingAddress);
port代表端口号,backLog代表这个套接字可支持的最大连接数量,bindingAddress代表服务器绑定的地址。一旦你有一个 ServerSocket 实例,你可以通过调用 ServerSocket 类的 accept 方法j。这个监听当前地址的当前端口上的请求,方法只会在有连接请求时才会返回,并且返回值是一个 Socket 类的实例。
五、request and response
servlet 的 service 方法从 servlet 容器中接收一个 javax.servlet.ServletRequest 实例 和一个 javax.servlet.ServletResponse 实例。这就是说对于每一个 HTTP 请求,servlet 容器 必须构造一个 ServletRequest 对象和一个 ServletResponse 对象并把它们传递给正在服务的 servlet 的 service 方法。
public class Request implements ServletRequest { private InputStream input; private String uri; public Request(InputStream input) { this.input = input; } public String getUri(){ return uri; } public void parseUrl() { StringBuffer request = new StringBuffer(2048); int i; byte[] buffer = new</