day8 模板方法设计模式 HttpServlet源码分析
创始人
2024-06-01 11:45:34
0

模板方法设计模式

  • 什么是设计模式?
    • 某个问题的固定的解决方案。(可以被重复使用。)
  • 你知道哪些设计模式?
    • GoF设计模式:
      • 通常我们所说的23种设计模式。(Gang of Four:4人组提出的设计模式)
      • 单例模式
      • 工厂模式
      • 代理模式
      • 门面模式
      • 责任链设计模式
      • 观察者模式
      • 模板方法设计模式
    • JavaEE设计模式:
      • DAO
      • DTO
      • VO
      • PO
      • pojo
  • 什么是模板方法设计模式?
    • 在模板类的模板方法当中定义核心算法骨架,具体的实现步骤可以延迟到子类当中完成。
  • 模板类通常是一个抽象类,模板类当中的模板方法定义核心算法,这个方法通常是final的(但也可以不是final的)
  • 模板类当中的抽象方法就是不确定实现的方法,这个不确定怎么实现的事儿交给子类去做。

HttpServlet源码分析

  • HttpServlet类是专门为HTTP协议准备的。比GenericServlet更加适合HTTP协议下的开发。
  • HttpServlet在哪个包下?
    • jakarta.servlet.http.HttpServlet
  • 到目前为止我们接触了servlet规范中哪些接口?
    • jakarta.servlet.Servlet 核心接口(接口)
    • jakarta.servlet.ServletConfig Servlet配置信息接口(接口)
    • jakarta.servlet.ServletContext Servlet上下文接口(接口)
    • jakarta.servlet.ServletRequest Servlet请求接口(接口)
    • jakarta.servlet.ServletResponse Servlet响应接口(接口)
    • jakarta.servlet.ServletException Servlet异常(类)
    • jakarta.servlet.GenericServlet 标准通用的Servlet类(抽象类)
  • http包下都有哪些类和接口呢?jakarta.servlet.http.*;
    • jakarta.servlet.http.HttpServlet (HTTP协议专用的Servlet类,抽象类)
    • jakarta.servlet.http.HttpServletRequest (HTTP协议专用的请求对象)
    • jakarta.servlet.http.HttpServletResponse (HTTP协议专用的响应对象)
  • HttpServletRequest对象中封装了什么信息?
    • HttpServletRequest,简称request对象。
    • HttpServletRequest中封装了请求协议的全部内容。
    • Tomcat服务器(WEB服务器)将“请求协议”中的数据全部解析出来,然后将这些数据全部封装到request对象当中了。
    • 也就是说,我们只要面向HttpServletRequest,就可以获取请求协议中的数据。
  • HttpServletResponse对象是专门用来响应HTTP协议到浏览器的。
  • 回忆Servlet生命周期?
    • 用户第一次请求
      • Tomcat服务器通过反射机制,调用无参数构造方法。创建Servlet对象。(web.xml文件中配置的Servlet类对应的对象。)
      • Tomcat服务器调用Servlet对象的init方法完成初始化。
      • Tomcat服务器调用Servlet对象的service方法处理请求。
    • 用户第二次请求
      • Tomcat服务器调用Servlet对象的service方法处理请求。
    • 用户第三次请求
      • Tomcat服务器调用Servlet对象的service方法处理请求。
      • Tomcat服务器调用Servlet对象的service方法处理请求。
    • 服务器关闭
      • Tomcat服务器调用Servlet对象的destroy方法,做销毁之前的准备工作。
      • Tomcat服务器销毁Servlet对象。
  • HttpServlet源码分析:
public class HelloServlet extends HttpServlet {// 用户第一次请求,创建HelloServlet对象的时候,会执行这个无参数构造方法。public HelloServlet() {}//override 重写 doGet方法//override 重写 doPost方法
}public abstract class GenericServlet implements Servlet, ServletConfig,java.io.Serializable {// 用户第一次请求的时候,HelloServlet对象第一次被创建之后,这个init方法会执行。public void init(ServletConfig config) throws ServletException {this.config = config;this.init();}// 用户第一次请求的时候,带有参数的init(ServletConfig config)执行之后,会执行这个没有参数的init()public void init() throws ServletException {// NOOP by default}
}// HttpServlet模板类。
public abstract class HttpServlet extends GenericServlet {// 用户发送第一次请求的时候这个service会执行// 用户发送第N次请求的时候,这个service方法还是会执行。// 用户只要发送一次请求,这个service方法就会执行一次。@Overridepublic void service(ServletRequest req, ServletResponse res)throws ServletException, IOException {HttpServletRequest  request;HttpServletResponse response;try {// 将ServletRequest和ServletResponse向下转型为带有Http的HttpServletRequest和HttpServletResponserequest = (HttpServletRequest) req;response = (HttpServletResponse) res;} catch (ClassCastException e) {throw new ServletException(lStrings.getString("http.non_http"));}// 调用重载的service方法。service(request, response);}// 这个service方法的两个参数都是带有Http的。// 这个service是一个模板方法。// 在该方法中定义核心算法骨架,具体的实现步骤延迟到子类中去完成。protected void service(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {// 获取请求方式// 这个请求方式最终可能是:""// 注意:request.getMethod()方法获取的是请求方式,可能是七种之一:// GET POST PUT DELETE HEAD OPTIONS TRACEString method = req.getMethod();// 如果请求方式是GET请求,则执行doGet方法。if (method.equals(METHOD_GET)) {long lastModified = getLastModified(req);if (lastModified == -1) {// servlet doesn't support if-modified-since, no reason// to go through further expensive logicdoGet(req, resp);} else {long ifModifiedSince;try {ifModifiedSince = req.getDateHeader(HEADER_IFMODSINCE);} catch (IllegalArgumentException iae) {// Invalid date header - proceed as if none was setifModifiedSince = -1;}if (ifModifiedSince < (lastModified / 1000 * 1000)) {// If the servlet mod time is later, call doGet()// Round down to the nearest second for a proper compare// A ifModifiedSince of -1 will always be lessmaybeSetLastModified(resp, lastModified);doGet(req, resp);} else {resp.setStatus(HttpServletResponse.SC_NOT_MODIFIED);}}} else if (method.equals(METHOD_HEAD)) {long lastModified = getLastModified(req);maybeSetLastModified(resp, lastModified);doHead(req, resp);} else if (method.equals(METHOD_POST)) {// 如果请求方式是POST请求,则执行doPost方法。doPost(req, resp);} else if (method.equals(METHOD_PUT)) {doPut(req, resp);} else if (method.equals(METHOD_DELETE)) {doDelete(req, resp);} else if (method.equals(METHOD_OPTIONS)) {doOptions(req,resp);} else if (method.equals(METHOD_TRACE)) {doTrace(req,resp);} else {//// Note that this means NO servlet supports whatever// method was requested, anywhere on this server.//String errMsg = lStrings.getString("http.method_not_implemented");Object[] errArgs = new Object[1];errArgs[0] = method;errMsg = MessageFormat.format(errMsg, errArgs);resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, errMsg);}}protected void doGet(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException{// 报405错误String msg = lStrings.getString("http.method_get_not_supported");sendMethodNotAllowed(req, resp, msg);}protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {// 报405错误String msg = lStrings.getString("http.method_post_not_supported");sendMethodNotAllowed(req, resp, msg);}}/*
通过以上源代码分析:假设前端发送的请求是get请求,后端程序员重写的方法是doPost假设前端发送的请求是post请求,后端程序员重写的方法是doGet会发生什么呢?发生405这样的一个错误。405表示前端的错误,发送的请求方式不对。和服务器不一致。不是服务器需要的请求方式。通过以上源代码可以知道:只要HttpServlet类中的doGet方法或doPost方法执行了,必然405.怎么避免405的错误呢?后端重写了doGet方法,前端一定要发get请求。后端重写了doPost方法,前端一定要发post请求。这样可以避免405错误。这种前端到底需要发什么样的请求,其实应该后端说了算。后端让发什么方式,前端就得发什么方式。有的人,你会看到为了避免405错误,在Servlet类当中,将doGet和doPost方法都进行了重写。
这样,确实可以避免405的发生,但是不建议,405错误还是有用的。该报错的时候就应该让他报错。
如果你要是同时重写了doGet和doPost,那还不如你直接重写service方法好了。这样代码还能
少写一点。
*/
  • 我们编写的HelloServlet直接继承HttpServlet,直接重写HttpServlet类中的service()方法行吗?

    • 可以,只不过你享受不到405错误。享受不到HTTP协议专属的东西。
  • 到今天我们终于得到了最终的一个Servlet类的开发步骤:

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

相关内容

热门资讯

火影安卓系统和ios系统互通吗... 你有没有想过,火影安卓系统和iOS系统之间是不是也能来个亲密接触呢?想象你可以在手机上随时随地,不管...
抽卡系统漫画app安卓,安卓用... 你有没有发现,最近手机上的一款漫画APP突然火了起来?没错,就是那个让人又爱又恨的抽卡系统!今天,就...
向葵视频安卓系统下载,轻松享受... 你有没有发现,最近手机上多了一个特别有趣的小玩意儿——向葵视频!这款视频软件可是火得一塌糊涂,不仅界...
安卓能登ios系统吗 你有没有想过,安卓手机能不能登录iOS系统呢?这个问题听起来是不是有点像是在问“猫能不能变成狗”一样...
荣耀如何玩好安卓系统,尽享流畅... 你有没有想过,为什么荣耀手机那么受欢迎呢?不仅仅是因为它的外观时尚,性能强大,更重要的是,它的安卓系...
安卓系统如何安装飞机,安卓系统... 你有没有想过,在安卓系统上安装飞机游戏,那感觉简直就像是真的驾驶了一架飞机在天空中翱翔!没错,今天就...
安卓系统大屏怎么恢复 手机屏幕突然变得模糊不清,是不是觉得自己的安卓大屏手机有点儿“老眼昏花”了呢?别急,今天就来教你怎么...
如何关闭安卓系统运行,轻松关闭... 手机用久了,是不是感觉安卓系统里的后台程序越来越多,运行速度越来越慢?别急,今天就来教你怎么关闭安卓...
安卓改苹果系统数据清理,系统数... 你是不是也和我一样,手机里堆满了各种应用,照片,视频,还有那些不知道什么时候开始占据空间的文件?别急...
锤子系统比安卓好吗,超越安卓的... 你有没有想过,手机系统到底哪家强?安卓和锤子系统,这两大巨头,哪个才是你的菜呢?今天,就让我来给你好...
安卓atv9.0系统,系统革新... 你有没有发现,最近安卓电视盒子界又掀起了一股热潮?没错,就是那款备受瞩目的安卓ATV9.0系统!今天...
安卓和苹果怎么转系统,安卓与苹... 你有没有想过,手机里的操作系统就像是个小世界,有时候你可能会想换个环境,体验一下不同的风景。没错,今...
苹果和安卓系统转换软件,苹果与... 你有没有想过,手机里的苹果和安卓系统,就像是两个截然不同的世界,各自有着独特的魅力和规则。但你知道吗...
找回安卓系统的软件,恢复系统至... 手机里的安卓系统是不是突然变得有点儿陌生了呢?是不是觉得那些曾经熟悉的软件都消失得无影无踪?别急,今...
安卓系统互相转移数据,轻松实现... 你有没有想过,当你从一台安卓手机换到另一台的时候,那些珍贵的照片、联系人、音乐和游戏怎么才能无缝转移...
安卓系统换几个桌面好用,让你的... 你有没有发现,手机桌面换换心情也是一种生活小情趣呢?尤其是安卓系统,桌面应用丰富,可玩性极高。今天,...
三星系统升级安卓系统 你知道吗?最近三星手机界可是热闹非凡呢!三星系统升级安卓系统,这可是个大新闻哦!想象你的三星手机瞬间...
安卓系统手绘软件推荐,安卓系统... 你有没有想过,用手机也能画出美美的画作呢?没错,现在就有这么神奇的安卓系统手绘软件,让你的创意随时随...
怎么升级htc安卓系统版本,版... 亲爱的手机控们,你是否也像我一样,对手机系统升级充满了期待和好奇呢?尤其是那些拥有HTC安卓手机的小...
三星系统最好的安卓系统 你有没有想过,为什么三星的安卓系统总是那么受欢迎呢?是不是每次看到三星手机,都会被那流畅的操作和丰富...