在web开发的基础部分,我们看到编写一个HTTP服务器其实是非常简单的,只需要先编写基于TCP/IP协议的服务,然后再一个TCP连接中读取HTTP请求,发送HTTP相应。
编写一个完善的HTTP服务器,以HTTP/1.1为例:
(1) 识别正确和错误的HTTP请求
(2) 识别正确和错误的HTTP头····
(3) 复用TCP链接
(4) 复用线程
(5) IO异常处理
由于这些基础工作会消耗完我们大量的时间,并且经过长期测试才能稳定运行,每次编写这些这些千行底层代码,就无法做到高校而稳定的开发,所以JAVAEE平台上,处理TCP连接,解析HTTP协议这些底层工作,都交给现成的Web服务器,我们只需要让我们自己的应用程序跑在Web服务器上,JAVA提供了Servlet API,我们使用Servlet API编写。
- // WebServlet注解表示这是一个Servlet,并映射到地址 hello.do
- @WebServlet(urlPatterns = "/hello.do")
- public class HelloServlet extends HttpServlet {
- protected void doGet(HttpServletRequest req, HttpServletResponse resp)
- throws ServletException, IOException {
- // 设置响应类型:
- resp.setContentType("text/html");
- // 获取输出流:
- PrintWriter pw = resp.getWriter();
- // 写入响应:
- pw.write("
Hello, world!
"); - // 最后不要忘记flush强制输出:
- pw.flush();
- }
- }
一个servlet总是继承自HttpServlet,然后覆写doGet()方法或者doPost()方法。这俩个方法创建时分别传入了俩个对象,分别是request(请求)和response(响应)。我们在使用Servlet API时,并不直接与底层TCP交互,也不需要解析HTTP协议。我们只需要设置正确的响应类型,然后获取PrintWrite,写入相应即可。
这样的项目最终会打包成一个.war文件,运行这个文件,需要支持的Servlet API容器(web服务器)。
(1)Tomcat:由Apache开发的开源免费的服务器
(2)Jetty:由Eclipse开发的开源免费的服务器
(3)GlassFish:一个开源的全功能的JAVAEE服务器
在通过一个URL路径发起一个对Servlet的请求,其本质实在调用执行Servlet实例的doXXX()方法。该Servlet实例的创建和使用的过程,被称为Servlert的生命周期。
Servlet的生命周期包括:
根据Servlet请求的路径(例如home.do),查找该Servlet的实例。如果实例不存在,则通过调用构造方法,完成Servlet实例的创建。
通过该Servlet的实例,调用init()方法,执行初始化的逻辑。
通过该Servlet的实例,调用service()方法,如果子类没有重写该方法,则调用HttpServlet父类的service()方法,在父类的该方法中进行请求方式的判断,如果是GET()请求,则doGet()方法,如果是POST请求,则调用doPost()方法。
如果子类重写该方法,则调用子类重写后的方法。
如果子类未重写该方法,则调用父类的doXXX()方法,在父类的方法实现中,返回一个 405的错误显示。
服务器关闭或重启时,会销毁所有的Servlet实例,会调用Servlet实例的destroy()方法。