HTTP服务端如何工作
在另一篇文章里我总结了HTTP的报文如何工作的,这些对于前端工作者已经足够了,只需要发送请求然后接收返回报文就可以了.但是当你发送HTTP报文到服务端时,服务端都进行了哪些操作呢?
就像前文中总结,HTTP本身是应用层协议,其在传输层TCP协议的上层,已经可以通过工具将二进制流转化为人的肉眼可以看懂的字符串,就如同阅读文章一样.
所以说HTTP报文本质上还是电报,是一张表格,有着固定的格式.通过实现约定好的格式我们可以区分出报文头,报文头中的字段,以及报文体.那么问题来了,我要去报文头中某个字段的时候怎么让计算机去取呢?
Servlet的诞生
聪明的少年们说,你不是说都是字符串么,我就分割字符串好了.其实原理也就是这么简单,但是HTTP请求这么频繁,每次都分割多累啊.
聪明的少年又说,那我就写个函数,通过函数来取就好了.但是如果下次我要取另外一个字段呢?你要准备多少个函数?
聪明的少年说,那我就封装成一个模型,带有参数和方法,将常用的变量赋值给参数,常用的方法用来取需要的字段.
经过以上三个步骤,就可以理解Servlet到底是什么了.Servlet就是对HTTP协议的封装,让其变成一个模型,方便开发者在服务端使用
Servlet的构成
Java中的Servlet的Class叫做HttpServlet,主要包含以下函数
//公开的方法用来接收HTTP的请求,并且转交给Protect的Service方法
public void service(ServletRequest req, ServletResponse res)
//分析请求,将ServletRequest对象转换成HttpServletRequest,同样处理Response
protected void service(HttpServletRequest req, HttpServletResponse resp)
//接受Service转发来的Get请求
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
//接受Service转发来的Post请求
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
按照基本定义一个Servlet就是一个接口(框架中Servlet可能会是转发器),其接收到的所有请求都会进入Public的Service函数,同时执行以下操作
- 自动分析HTTP报文将其封装成Request对象
- 新建一个Response对象备用
- 转发到Protect的Service函数
- 分析HTTP方法,然后转发到对应的Do方法(doGet例如)
- 处理完毕将结果写入Reponse
- 返回HTTP报文
服务端处理
由于Servlet的函数工作流程是确定的,所以我们可以通过重写其中任何一个方法,来在中间加入我们的逻辑代码,如我们处理所有的Get和Post请求,示例代码如下.
public class ServletManager extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String controlStr = request.getParameter("control");
response.sendRedirect("index.jsp");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
super.doGet(request, response);
}
}
Servlet映射
我们写好了一个Servlet,如何让它在网络上可以被访问到呢?这里就需要提到一个概念,连同Servlet在内的所有网络服务(例如网页),都可以打包成一个*.war文件放在服务器的webApp目录下,比如Tomcat或者Jetty.
当你的服务器启动后,就会自动加载这些*.war文件,也就是说你的服务已经发布了.接下来就是让别人通过URL地址访问你的时候可以获取HTTP返回.那么就需要Servlet映射.
web.xml映射
所有.war文件必须有个名为web.xml的配置文件,在配置文件中,让servlet-name与你的Class.java(servlet-class)文件对应,以及servlet-name与一个URL地址(url-pattern)对应.
<servlet>
<servlet-name>ServletManager</servlet-name>
<servlet-class>servlet.ServletManager</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletManager</servlet-name>
<url-pattern>/server</url-pattern>
</servlet-mapping>
通过以上方式就可以在你的服务器地址基础上加上war包的路径和servlet的url-pattern访问到这个Servlet进行HTTP的请求和处理.
注解映射
或者可以使用Servlet3.0,其本身为Java的注解
@WebServlet(name = "ServletManager", urlPatterns = "/server")
public class OrderServlet extends HttpServlet {}
将一个Class标记被Servlet,同web.xml配置的效果是一样的.