可以看到 server 已经正常启动,我们在网页上输入 127.0.0.1:9901, 可以看到已经能够正常返回了,是不是很简单呀。
2、使用 Tomcat 处理HTTP请求
从上面我们可以看到编写HTTP服务器其实是非常简单的,只需要先编写基于多线程的TCP服务,然后在一个TCP连接中读取HTTP请求,发送HTTP响应就可以了。
但是,要编写一个完善的HTTP服务器,还要考虑更多东西例如:
我们一直都在强调不要重复造轮子,Java发展了这么久处理TCP连接,解析HTTP协议这些底层工作早已有了现成的API。JavaEE提供的Servlet API,我们可以使用Servlet API编写自己的Servlet来处理HTTP请求,
接下来我们看一个简单的例子
import java.nio.charset.StandardCharsets;
import java.io.*;
import java.util.*;
import java.net.*;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
// WebServlet注解表示这是一个Servlet,并映射到地址/:
@WebServlet(urlPatterns = "/")
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
// 设置响应类型:
resp.setContentType("text/html");
// 获取输出流:
PrintWriter pw = resp.getWriter();
String name = req.getParameter("name");
// 写入响应:
if (null == name) {
pw.write("Hello, world!
");
} else {
pw.write("Hello, " + name + "!
");
}
// 最后不要忘记flush强制输出:
pw.flush();
}
}
其中 Servlet API是一个jar包,我们需要通过Maven来引入它,才能正常编译。编写pom.xml文件如下
4.0.0
com.lzf.learnjava
web-servlet-hello1
war
1.0-SNAPSHOT
UTF-8
UTF-8
8
8
8
javax.servlet
javax.servlet-api
4.0.0
provided
hello
具体代码结构目录如下
Mavean 打包出来的是war包, 需要运行的话得先启动Web服务器,而Web服务我们最常用的就是Tomcat。首先我们到官网下载Tomcat服务器,解压后
Tomcat目录:
bin:存放启动和关闭tomcat脚本 conf:存放不同的配置文件(server.xml和web.xml) doc:存放Tomcat文档 lib:存放Tomcat运行需要的库文件(JARS) logs:存放Tomcat执行时的LOG文件 webapps:Tomcat的主要Web发布目录(包括应用程序示例) work:存放jsp编译后产生的class文件
把hello.war复制到Tomcat的webapps目录下,Tomcat 默认监听的8080的端口请求的url在此服务器上找不到,可以通过修改 conf/server.xml -> Connector 里的 port 属性来改变监听端口。然后切换到bin目录,执行startup.sh或startup.bat启动Tomcat服务器
网页上输入:9903/hello/?name=Qc ,成功访问!
接下来我们来分析Tomcat 是如何处理一个HTTP请求的过程
首先我们先了解Tomcat 的体系架构
参考上面的图解释下:
1.Server组件
即服务器,每个tomcat程序启动后,就是一个server。
2、Service组件
一个Server可以包含多个Service,Service这是一种抽象的服务,它把连接器和处理引擎结合在一起。
3、Connector组件:
一个Service可以有多个Connector,Connector组件用于处理连接和并发。一般说来常见于server.xml
中的连接器类型通常有4种:
1) HTTP连接器 2) SSL连接器 3) AJP 1.3连接器 4) proxy连接器
4、Engine组件:
Engine是Servlet处理器的一个实例,即servlet引擎,其defaultHost属性是用来来为其定义一个接收所
有发往非明确定义虚拟主机的请求的host组件。如前面示例中定义的:
5、Host组件:
位于Engine容器中,用于接收请求并进行相应处理的主机或虚拟主机.
bbbtc.test
6、Context组件:
Context在某些意义上类似于apache中的路径别名,一个Context定义用于标识tomcat实例中的一个Web应用程序
了解了架构之后我们看请求过程
1、用户打开浏览器输入地址,请求被发送到本机端口9903请求的url在此服务器上找不到,被在那里监听的Coyote HTTP/1.1 Connector获得。
2、Connector把该请求交给它所在的Service的Engine来处理,并等待Engine的回应。
3、Engine获得请求localhost:9903/hello/?name=Qc,匹配所有的虚拟主机Host。
4、Engine匹配到名为localhost的Host(即使匹配不到也把请求交给该Host处理,因为该Host被定义为该Engine的默认主机)名为localhost的Host获得请求/hello/?name=Qc,匹配它所拥有的所有的Context。 Host匹配到路径为/hello 的Context(如果匹配不到就把该请求交给路径名为""的Context去处理)。
5、在它的mapping table中寻找出对应的Servlet 处理数据。
6、构造HttpServletRequest对象和HttpServletResponse对象,作为参数调用JspServlet的doGet()或doPost().执行业务逻辑、数据存储等程序。
7、Context把执行完之后的HttpServletResponse对象返回给Host。
版权声明
本文仅代表作者观点。
本文系作者授权发表,未经许可,不得转载。
发表评论