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表单中指定请求路径即可。

相关内容

热门资讯

美版三星s8省电技巧-美版三星... 大家好,我是你们的手机电量小能手,今天来聊聊咱们的美版三星S8怎么省电,让它的电量像小强一样坚强,不...
安卓系统是什么意思-安卓系统:... 嘿,大家好!今天我要聊聊那个在咱们手机里默默工作的小家伙——安卓系统。你们知道吗?每次我打开手机,看...
分区后d盘不见了-电脑硬盘分区... 哎哟喂,今天真是倒霉透顶了!我就想着给电脑来个大扫除,顺手就给硬盘分了个区。谁知道,一觉醒来,我的D...
shopnc模板下载-Shop... 嘿,亲爱的网站搭建小伙伴们!今天我要带你们进入一个全新的世界——ShopNC模板下载的世界!这不仅仅...
linux命令在线模拟器-超级... 嘿,亲爱的代码爱好者们,今天我要给你们带来一个超级酷炫的玩意儿——Linux命令在线模拟器!想象一下...
帝国cms下载模板-帝国 CM... 哎呀,说到这个帝国CMS下载模板,真是让我心情复杂啊!你知道吗,每当我想要给我的网站换个新装,我就开...
身份证住宿登记查询攻略:如何避... 哎呀呀,说起这个身份证住宿登记查询,真是让人头疼啊!每次出门在外,最怕的就是找不到身份证,或者忘记登...
android手机文件传输-告... 嘿,大家好!今天咱们聊聊Android手机文件传输那些事儿。你知道吗?每次我想把手机里的照片、视频或...
w8重装系统-电脑卡顿不用怕,... 哎呀,说到这个重装系统,我简直要泪流满面了!你知道吗,我的电脑最近简直就像个老态龙钟的老头,动不动就...
银行监控报警系统培训:保安的超... 哎呀,说到这个银行监控报警系统培训,我可是满脸兴奋啊!你知道吗,这不仅仅是一堆冷冰冰的机器和程序,这...
互盾安卓恢复大师手机版下载-手... 哎呀,天哪,我的手机里那些珍贵的照片、视频和信息,竟然一夜之间全都不见了!这可怎么办啊?我的心都快碎...
qt 实现qq-用 Qt 打造... 嘿,各位编程爱好者们,今天我要给大家讲一个关于Qt和QQ的故事,这可不是普通的编程故事,这是我在代码...
linux 设备驱动-Linu... 哎呀,说起这Linux设备驱动啊,真是让我又爱又恨!爱它什么呢?爱它那股子开放和自由的劲儿,就像是一...
tabbar icon 下载-... 嘿,亲爱的屏幕控们!今天咱们不聊那些枯燥的技术参数,不谈那些让人头疼的编程代码,咱们就来聊聊那些能让...
怀孕以后老是感冒咳嗽怎么办?-... 哎呀,说到怀孕后老是感冒咳嗽,我这心里就急得像热锅上的蚂蚁!明明是喜事一桩,怎么就老是被这些小病小痛...
河南身份证号码大全集泄露问题令... 哎呀,说到这个“河南身份证号码大全集”,真是让人又爱又恨啊!你知道吗,这东西在网上流传得像风一样快,...
展讯sc9832处理器-展讯 ... 哎呀,说到这个展讯SC9832处理器,我就忍不住要激动一番!这小家伙,别看它个头不大,心里可是装着大...
资阳大众网乐至烧烤节-资阳乐至... 嘿,朋友们!想象一下,炎炎夏日,一群人围着篝火,手里拿着烤串,脸上挂着满足的笑容,这就是我们资阳的乐...
宝宝吃完奶就打嗝怎么回事-宝宝... 哎呀,每次看到我家小宝贝吃完奶后就开始打嗝,我的心都揪起来了!这小家伙,吃饱了还不安生,一连串的嗝声...
ecshop手机版模板修改-E... 哎呀,说到这个ECSHOP手机版模板修改,我这心里头可真是五味杂陈啊!作为一个天天和代码打交道的前端...