Tomcat本质上是一款开源轻量级Web应用服务器,是一款优秀的Servlet容器实现。
核心2点,Web服务器、Servlet容器。
阿里中间件团队:http://jm.taobao.org/about/
很多公司都手写或者重写Tomcat.比如aliTomcat : https://help.aliyun.com/document_detail/90754.html
网络通讯,客户端和服务端的关系,java中建立Socket通讯,注意一般Socket是基于TCP的协议。
//1、绑定端口 ---JDK 为我们提供的网络操作的API
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("服务器启动成功!");
while(!serverSocket.isClosed()){//在等待请求
//2、有请求过来了 ,使用一个socket: 代表着一个客户端--服务端的连接
Socket socket = serverSocket.accept();
//3、使用一个线程来处理请求
executorService.execute(()->{
try{
InputStream inputStream = socket.getInputStream();
System.out.println("收到请求:");
BufferedReader reader = new BufferedReader( new InputStreamReader(inputStream,"utf-8"));
//字符串
String msg =null;
StringBuilder requestInfo = new StringBuilder();
while ( (msg=reader.readLine()) !=null ){
if(msg.length()==0) break;
requestInfo.append(msg).append("\r\n");
}
System.out.println(requestInfo);
//要对请求的头进行解析,获取请求的第一行
String firstline =requestInfo.toString().split("\r\n")[0];
System.out.println(firstline);
浏览器之间通讯必须要符合HTTP协议,响应信息加入HTTP格式的响应
//要对请求的头进行解析,获取请求的第一行
String firstline =requestInfo.toString().split("\r\n")[0];
System.out.println(firstline);
//防止浏览器发空过的请求过来
if(firstline.length()<1){
return;
}
String servletPath = firstline.split(" ")[1];
//Servet映射
Map servletMapping= (Map)webAppMap.get("servlet-mapping");
//Servlet实例
Map servletInstances= (Map )webAppMap.get("servlet");
//是否有正确的url对应的Servlet
if(servletMapping.containsKey(servletPath)){
String servletName = servletMapping.get(servletPath);
HttpServlet httpServlet = (HttpServlet)servletInstances.get(servletName);
HttpServletRequest httpServletRequest =createRequest();
HttpServletResponse httpServletResponse = createResponse();
httpServlet.service(httpServletRequest,httpServletResponse);
OutputStream outputStream = socket.getOutputStream();
byte[] response ="请求成功!".getBytes();
outputStream.write("HTTP/1.1 200 OK \r\n".getBytes());
outputStream.write("Content-Type:text/html;charset=utf-8 \r\n".getBytes());
outputStream.write( ("Content-Length:"+response.length+"\r\n").getBytes());
outputStream.write("\r\n".getBytes());
outputStream.write(response);
outputStream.flush();
System.out.println("----END");
}else{
//要与浏览器进行“互动” ,HTTP 协议
OutputStream outputStream = socket.getOutputStream();
byte[] response ="对不起,没有对应的Servlet请求信息!".getBytes();
outputStream.write("HTTP/1.1 200 OK \r\n".getBytes());
outputStream.write("Content-Type:text/html;charset=utf-8 \r\n".getBytes());
outputStream.write( ("Content-Length:"+response.length+"\r\n").getBytes());
outputStream.write("\r\n".getBytes());
outputStream.write(response);
outputStream.flush();
System.out.println("----END");
}
}catch (IOException e){
类加载
public static void main(String[] args) throws Exception{
//0、加载项目(类加载)、容器、HashMap
Map webAppMap = ProjectLoader.load();
public class ProjectLoader {
public static Map load() throws Exception{
//定义一个Map,存储项目信息
Map webapp = new HashMap<>();
Map servletInstances = new HashMap<>(); //servlet
Map servletMapping = new HashMap<>(); //servlet-mapping
//项目路径
String webappPath ="D:\\work_public\\servletdemo\\out\\artifacts\\servletdemo_war_exploded\\WEB-INF";
//JDK提供类加载器 URL
URL classFile = new URL("file:"+webappPath+"\\classes\\");
URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{classFile});
//解析xml文件
//1.获取解析器
SAXReader reader = new SAXReader();
//2.获取文档对象(xml)
Document document = reader.read(new File(webappPath+"\\web.xml"));
//3.获取根元素
Element root = document.getRootElement();
//4.获取根元素中下的子元素
List childElements = root.elements();
//5.遍历子元素
for (Element element:childElements) {
//6.判断元素名称为servlet的元素
if ("servlet".equals(element.getName())) {
//获取servlet-name元素
Element servletName = element.element("servlet-name");
//获取servlet-class元素
Element servletClass = element.element("servlet-class");
String strServletName = servletName.getText();
String strServletClass = servletClass.getText();
System.out.println("servlet:"+strServletName+"="+strServletClass);
//1.加载到JVM
Class> classzz= urlClassLoader.loadClass(strServletClass);
//2 创建对象实例(反射) -servlet;
Servlet servlet = (Servlet)classzz.newInstance();
//web.xml的servlet实例化放入hashmap
servletInstances.put(strServletName, servlet);
}
//7.判断元素名称为servlet-mapping的元素
if ("servlet-mapping".equals(element.getName())) {
//获取servlet-name元素
Element servletName = element.element("servlet-name");
//获取url-pattern元素
Element urlPattern = element.element("url-pattern");
String strServletName = servletName.getText();
String strUrlPattern = urlPattern.getText();
//web.xml的servlet的Mapping放入hashmap
System.out.println("servlet-mapping:"+strUrlPattern+"="+strServletName);
servletMapping.put(strUrlPattern,strServletName);
}
}
webapp.put("servlet",servletInstances);
webapp.put("servlet-mapping",servletMapping);
return webapp;
}
}
解析请求地址,找到对应的Servlet
//要对请求的头进行解析,获取请求的第一行
String firstline =requestInfo.toString().split("\r\n")[0];
System.out.println(firstline);
//防止浏览器发空过的请求过来
if(firstline.length()<1){
return;
}
String servletPath = firstline.split(" ")[1];
//Servet映射
Map servletMapping= (Map)webAppMap.get("servlet-mapping");
//Servlet实例
Map servletInstances= (Map )webAppMap.get("servlet");
//是否有正确的url对应的Servlet
if(servletMapping.containsKey(servletPath)){
String servletName = servletMapping.get(servletPath);
HttpServlet httpServlet = (HttpServlet)servletInstances.get(servletName);
HttpServletRequest httpServletRequest =createRequest();
HttpServletResponse httpServletResponse = createResponse();
httpServlet.service(httpServletRequest,httpServletResponse);
OutputStream outputStream = socket.getOutputStream();
byte[] response ="请求成功!".getBytes();
outputStream.write("HTTP/1.1 200 OK \r\n".getBytes());
outputStream.write("Content-Type:text/html;charset=utf-8 \r\n".getBytes());
outputStream.write( ("Content-Length:"+response.length+"\r\n").getBytes());
outputStream.write("\r\n".getBytes());
outputStream.write(response);
outputStream.flush();
System.out.println("----END");
构建简单的参数
HttpServletRequest httpServletRequest =createRequest();
HttpServletResponse httpServletResponse = createResponse();