如何深入浅出地学习Tomcat中的Servlet技术?

2026-04-11 09:501阅读0评论SEO教程
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1674个文字,预计阅读时间需要7分钟。

如何深入浅出地学习Tomcat中的Servlet技术?

介绍Servlet的生命周期、运行机制、适配器和模板方法设计模式,以及Servlet的映射问题,如HttpServletRequest在请求过程中遇到的POST问题...

一、Servlet简介Servlet类是Java Web技术中的重要组成部分,它使得Java程序能够处理HTTP请求。Servlet类的最终开发步骤如下:

第一步:编写Servlet类javapublic class MyServlet extends HttpServlet { // 编写业务逻辑代码}

介绍了Servlet的生命周期、运行机制,适配器和模板方法设计模式以及Servlet的映射问题,HttpServletRequest在请求过程中post遇到的问题... 一、Servlet简介

Servlet类最终开发步骤:

如何深入浅出地学习Tomcat中的Servlet技术?

  • 第一步:编写一个Servlet类,直接继承HttpServlet
  • 第二步:重写doGet方法或者doPost方法,重写哪个我说的算!
  • 第三步:将Servlet类配置到web.xml文件当中
  • 第四步:准备前端的页面(form表单),指定请求路径即可

  • Servlet是一个接口,在它的下面有GenericServlet
    和HttpServlet两个实现类

我们来了解一下GenericServlet:

  • 其中的GenericServlet实现了很多方法,只保留了一个抽象方法,就是我们经常用的service方法。

  • 这或许就是为了更简洁一点吧,我们每次不需要在像实现Servlet接口一样,将全部的抽象方法都实现。
  • 根据他的类图可知,HttpServlet继承了GenericServlet这个类,那么它为什么要继承GenericServlet呢?

我们来了解一下HttpServlet:

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); long lastModified; if (method.equals("GET")) { lastModified = this.getLastModified(req); if (lastModified == -1L) { this.doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader("If-Modified-Since"); } catch (IllegalArgumentException var9) { ifModifiedSince = -1L; } if (ifModifiedSince < lastModified / 1000L * 1000L) { this.maybeSetLastModified(resp, lastModified); this.doGet(req, resp); } else { resp.setStatus(304); } } } else if (method.equals("HEAD")) { lastModified = this.getLastModified(req); this.maybeSetLastModified(resp, lastModified); this.doHead(req, resp); } else if (method.equals("POST")) { this.doPost(req, resp); } else if (method.equals("PUT")) { this.doPut(req, resp); } else if (method.equals("DELETE")) { this.doDelete(req, resp); } else if (method.equals("OPTIONS")) { this.doOptions(req, resp); } else if (method.equals("TRACE")) { this.doTrace(req, resp); } else { String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[]{method}; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(501, errMsg); } }

  • 这段是HttpServlet中实现的Service方法的源码,我们可以清楚的了解到,Tomcat已经把这个Service写好了,我们只需要去实现doGet()doPost()等等这些请求的方法就可以了。
  • 因为这个Service会自己判断,我们进行访问的是什么请求,然后自动找到相应的方法进行处理。
二、两种设计模式 2.1适配器模式

适配器:适配器就是一种适配中间件,它存在于不匹配的二者之间,用于连接二者,将不匹配变得匹配,简单点理解就是平常所见的转接头,转换器之类的存在。

public interface MyInterface { void m1(); void m2(); void m3(); void m4(); void m5(); void test(); //但是这个接口中我们常用的方法只有test(),我们在实现此接口的时候,还需要实现其他方法,很累赘。 //所以我们就需要一个适配器! }

public abstract class Test implements MyInterface{ public void m1() { } public void m2() { } public void m3() { } public void m4() { } public void m5() { } //这是一个适配器 //在创建一个接口的实现类,我们将常用的方法设置为抽象的方法 //这样我们只需要继承该类,然后实现方法即可 public abstract void test(); }

  • 这样做的优点就是下次我们只需要去继承Test类,实现我们经常使用的test()方法就可以了。
  • 使我们的减少了冗余的代码量
  • 同时你也会发现这个就和GenericServlet去继承Servlet这个接口是一样的
  • 这就是适配器设计模式,其实很简单,也有利于我们更加理解抽象类的作用和接口的使用

public class Realize extends Test{ public void test() { //这样我们就不需要再去实现接口中的 其他方法了 } } 2.2 模板设计方法模式

模板方法模式:是一种行为设计模式, 它在超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。

  • 模板方法模式建议将算法分解为一系列步骤, 然后将这些步骤改写为方法, 最后在 “模板方法” 中依次调用这些方法。 步骤可以是 抽象的, 也可以有一些默认的实现。 为了能够使用算法, 客户端需要自行提供子类并实现所有的抽象步骤。 如有必要还需重写一些步骤 (但这一步中不包括模板方法自身)。

  • 认真的去阅读上面这段话:你就会发现他说将 算法进行分解,最后在模板中依次调用:

    • 此时的你是否想起我们刚开篇介绍的HttpServlet???
    • HttpServlet继承了 GenericServlet类,而GenericServlet类又实现了Servlet接口;HttpServlet里面的Service()方法你是否还记得?

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); long lastModified; if (method.equals("GET")) { lastModified = this.getLastModified(req); if (lastModified == -1L) { this.doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader("If-Modified-Since"); } catch (IllegalArgumentException var9) { ifModifiedSince = -1L; } if (ifModifiedSince < lastModified / 1000L * 1000L) { this.maybeSetLastModified(resp, lastModified); this.doGet(req, resp); } else { resp.setStatus(304); } } } else if (method.equals("HEAD")) { lastModified = this.getLastModified(req); this.maybeSetLastModified(resp, lastModified); this.doHead(req, resp); } else if (method.equals("POST")) { this.doPost(req, resp); } else if (method.equals("PUT")) { this.doPut(req, resp); } else if (method.equals("DELETE")) { this.doDelete(req, resp); } else if (method.equals("OPTIONS")) { this.doOptions(req, resp); } else if (method.equals("TRACE")) { this.doTrace(req, resp); } else { String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[]{method}; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(501, errMsg); } }

  • 一大堆的ifelse ifelse 这不就是所谓的将算法分块提炼了出来吗?然后我们只需要去刻画doGet()doPost()等方法,程序的主框架是不变的,只是其中的细节需要我们自己去实现。
  • 我个人目前觉得和适配器模式比较相似,但略有不同之处。
三、Servlet对象的声明周期 3.1 Servlet对象是由谁来维护的?
  • Servlet对象的创建、以及对象上方法的调用、对象的销毁这个过程,我们JavaWeb程序员是无权干预的。你可以仔细想想你什么时候new出来过一个Servlet对象。
  • Servlet对象的声明周期是由Tomcat服务器负责的
  • Tomcat服务器我们又可以称之为:WEB容器
  • WEB容器来管理Servlet对象的死活
3.2 Servlet认知强化
  • 你还真可以自己new一个Servlet对象,但是并不受我们Tomcat管理,所以你自己new出来的Servlet对象,死活和Tomcat没有关系。
  • Tomcat创建的Servlet对象,这些Servlet都会被放到一个集合当中(HashMap),只有放到HashMap集合的Servlet才能够被Tomcat容器管理。
  • Tomcat容器底层应该有一个HashMap这样的集合,在这个集合当中存储了Servlet对象和请求路径之间的关系,我想此时你更能够想到为什么我们总是在xml中如此定义?

  • 我们可以将Servlet对象称之为假单例模式,因为Servlet只有一个对象呀。

本文共计1674个文字,预计阅读时间需要7分钟。

如何深入浅出地学习Tomcat中的Servlet技术?

介绍Servlet的生命周期、运行机制、适配器和模板方法设计模式,以及Servlet的映射问题,如HttpServletRequest在请求过程中遇到的POST问题...

一、Servlet简介Servlet类是Java Web技术中的重要组成部分,它使得Java程序能够处理HTTP请求。Servlet类的最终开发步骤如下:

第一步:编写Servlet类javapublic class MyServlet extends HttpServlet { // 编写业务逻辑代码}

介绍了Servlet的生命周期、运行机制,适配器和模板方法设计模式以及Servlet的映射问题,HttpServletRequest在请求过程中post遇到的问题... 一、Servlet简介

Servlet类最终开发步骤:

如何深入浅出地学习Tomcat中的Servlet技术?

  • 第一步:编写一个Servlet类,直接继承HttpServlet
  • 第二步:重写doGet方法或者doPost方法,重写哪个我说的算!
  • 第三步:将Servlet类配置到web.xml文件当中
  • 第四步:准备前端的页面(form表单),指定请求路径即可

  • Servlet是一个接口,在它的下面有GenericServlet
    和HttpServlet两个实现类

我们来了解一下GenericServlet:

  • 其中的GenericServlet实现了很多方法,只保留了一个抽象方法,就是我们经常用的service方法。

  • 这或许就是为了更简洁一点吧,我们每次不需要在像实现Servlet接口一样,将全部的抽象方法都实现。
  • 根据他的类图可知,HttpServlet继承了GenericServlet这个类,那么它为什么要继承GenericServlet呢?

我们来了解一下HttpServlet:

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); long lastModified; if (method.equals("GET")) { lastModified = this.getLastModified(req); if (lastModified == -1L) { this.doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader("If-Modified-Since"); } catch (IllegalArgumentException var9) { ifModifiedSince = -1L; } if (ifModifiedSince < lastModified / 1000L * 1000L) { this.maybeSetLastModified(resp, lastModified); this.doGet(req, resp); } else { resp.setStatus(304); } } } else if (method.equals("HEAD")) { lastModified = this.getLastModified(req); this.maybeSetLastModified(resp, lastModified); this.doHead(req, resp); } else if (method.equals("POST")) { this.doPost(req, resp); } else if (method.equals("PUT")) { this.doPut(req, resp); } else if (method.equals("DELETE")) { this.doDelete(req, resp); } else if (method.equals("OPTIONS")) { this.doOptions(req, resp); } else if (method.equals("TRACE")) { this.doTrace(req, resp); } else { String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[]{method}; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(501, errMsg); } }

  • 这段是HttpServlet中实现的Service方法的源码,我们可以清楚的了解到,Tomcat已经把这个Service写好了,我们只需要去实现doGet()doPost()等等这些请求的方法就可以了。
  • 因为这个Service会自己判断,我们进行访问的是什么请求,然后自动找到相应的方法进行处理。
二、两种设计模式 2.1适配器模式

适配器:适配器就是一种适配中间件,它存在于不匹配的二者之间,用于连接二者,将不匹配变得匹配,简单点理解就是平常所见的转接头,转换器之类的存在。

public interface MyInterface { void m1(); void m2(); void m3(); void m4(); void m5(); void test(); //但是这个接口中我们常用的方法只有test(),我们在实现此接口的时候,还需要实现其他方法,很累赘。 //所以我们就需要一个适配器! }

public abstract class Test implements MyInterface{ public void m1() { } public void m2() { } public void m3() { } public void m4() { } public void m5() { } //这是一个适配器 //在创建一个接口的实现类,我们将常用的方法设置为抽象的方法 //这样我们只需要继承该类,然后实现方法即可 public abstract void test(); }

  • 这样做的优点就是下次我们只需要去继承Test类,实现我们经常使用的test()方法就可以了。
  • 使我们的减少了冗余的代码量
  • 同时你也会发现这个就和GenericServlet去继承Servlet这个接口是一样的
  • 这就是适配器设计模式,其实很简单,也有利于我们更加理解抽象类的作用和接口的使用

public class Realize extends Test{ public void test() { //这样我们就不需要再去实现接口中的 其他方法了 } } 2.2 模板设计方法模式

模板方法模式:是一种行为设计模式, 它在超类中定义了一个算法的框架, 允许子类在不修改结构的情况下重写算法的特定步骤。

  • 模板方法模式建议将算法分解为一系列步骤, 然后将这些步骤改写为方法, 最后在 “模板方法” 中依次调用这些方法。 步骤可以是 抽象的, 也可以有一些默认的实现。 为了能够使用算法, 客户端需要自行提供子类并实现所有的抽象步骤。 如有必要还需重写一些步骤 (但这一步中不包括模板方法自身)。

  • 认真的去阅读上面这段话:你就会发现他说将 算法进行分解,最后在模板中依次调用:

    • 此时的你是否想起我们刚开篇介绍的HttpServlet???
    • HttpServlet继承了 GenericServlet类,而GenericServlet类又实现了Servlet接口;HttpServlet里面的Service()方法你是否还记得?

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String method = req.getMethod(); long lastModified; if (method.equals("GET")) { lastModified = this.getLastModified(req); if (lastModified == -1L) { this.doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader("If-Modified-Since"); } catch (IllegalArgumentException var9) { ifModifiedSince = -1L; } if (ifModifiedSince < lastModified / 1000L * 1000L) { this.maybeSetLastModified(resp, lastModified); this.doGet(req, resp); } else { resp.setStatus(304); } } } else if (method.equals("HEAD")) { lastModified = this.getLastModified(req); this.maybeSetLastModified(resp, lastModified); this.doHead(req, resp); } else if (method.equals("POST")) { this.doPost(req, resp); } else if (method.equals("PUT")) { this.doPut(req, resp); } else if (method.equals("DELETE")) { this.doDelete(req, resp); } else if (method.equals("OPTIONS")) { this.doOptions(req, resp); } else if (method.equals("TRACE")) { this.doTrace(req, resp); } else { String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[]{method}; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(501, errMsg); } }

  • 一大堆的ifelse ifelse 这不就是所谓的将算法分块提炼了出来吗?然后我们只需要去刻画doGet()doPost()等方法,程序的主框架是不变的,只是其中的细节需要我们自己去实现。
  • 我个人目前觉得和适配器模式比较相似,但略有不同之处。
三、Servlet对象的声明周期 3.1 Servlet对象是由谁来维护的?
  • Servlet对象的创建、以及对象上方法的调用、对象的销毁这个过程,我们JavaWeb程序员是无权干预的。你可以仔细想想你什么时候new出来过一个Servlet对象。
  • Servlet对象的声明周期是由Tomcat服务器负责的
  • Tomcat服务器我们又可以称之为:WEB容器
  • WEB容器来管理Servlet对象的死活
3.2 Servlet认知强化
  • 你还真可以自己new一个Servlet对象,但是并不受我们Tomcat管理,所以你自己new出来的Servlet对象,死活和Tomcat没有关系。
  • Tomcat创建的Servlet对象,这些Servlet都会被放到一个集合当中(HashMap),只有放到HashMap集合的Servlet才能够被Tomcat容器管理。
  • Tomcat容器底层应该有一个HashMap这样的集合,在这个集合当中存储了Servlet对象和请求路径之间的关系,我想此时你更能够想到为什么我们总是在xml中如此定义?

  • 我们可以将Servlet对象称之为假单例模式,因为Servlet只有一个对象呀。