这是小小本周的第六篇,本篇小小将会介绍一个很古老很古老很古老的为什么系列之不能重写service方法。

小小最近看到一年一度的考研,心生感慨,不过,作为一个专科,没法参与今年的考研,但是没关系,小小明年都能参加考研了,争取早日考研,早日上岸。

故事的开头

从前有做山,山上有做庙,庙里有个老和尚,老和尚说,在很久很久以前是这样的。孩子啊,以后你要写servlet,绝对绝对绝对不能重写service方法,孩子对孩子的孩子说道,绝对不能重写service方法,孙子睁大眼睛问道,巴巴为什么要这样?“听爷爷的绝对没错”

今日话题:为什么不能重写Service方法

一个具体的例子

小小正在看osc,看见一篇大作,只见小小左手一个动作,右手一个动作,熟练的打开chrome开发者工具,猛然间看到了如下的结果。这个时候,聪明的你,一定发现了,除了第一个名为12-77118的请求返回状态为200,其他都为304,那么200和304有什么区别?一切都从代码中来。编写一个index.html如下

<html>
<body>
<h3>I'm a test page . </h3>
<h3>I'm a test page . </h3>
<h3>I'm a test page . </h3>
<h3>I'm a test page . </h3>
<h3>I'm a test page . </h3>
<h3>I'm a test page . </h3>
<h3>I'm a test page . </h3>
</body>
</html>

访问这个页面第一次访问第二次访问这次请求的头信息中,多了一条if-modified-since,而且返回的响应中,状态变成了304,这是什么原因?对于静态页面来说。

  1. 当浏览器第一次发起请求,server会在响应中告诉浏览器这个资源最后修改的时间。

  2. 浏览器也很聪明,当你再次请求这个资源时候,浏览器会询问server这个资源自从上次告诉我的最后修改时间以来有没有被修改过。

  3. 如果资源没有被修改,server返回304状态码,并不会再次把资源发送给浏览器,浏览器会使用本地的缓存文件。所有的静态资源如果没有发生变化,通常不会传递多次,不管什么浏览器都是这样的,这叫http缓存协商。这是约定优于配置的体现。

一个更加复杂的例子

在这个例子中,我们请求一个控制器,然后转向一个视图。web.xml中的servlet配置如下

<web-app><servlet><servlet-name>me</servlet-name><servlet-class>com.me.web.MeServlet</servlet-class></servlet><servlet-mapping><servlet-name>me</servlet-name><url-pattern>/test</url-pattern></servlet-mapping>
</web-app>

MeServlet

public class MeServlet extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException {/*** 1. 处理具体的业务:* -- 处理请求参数* -- 检查缓存* -- 处理具体数据* -- 更新缓存*/doBizLogic(req, res);/*** 2. 根据处理的结果转向具体的视图:* -- 这里假设就是 index.html*/getServletContext().getRequestDispatcher("/index.html").include(req, res);}public void doBizLogic(HttpServletRequest request, HttpServletResponse response) {System.out.println("do biz.");}
}

再次不断地刷新可以发现,无论什么时候,每次相应的状态都是200,index.html的内容都能被完整的记录下来发送给浏览器,这为什么不能进行缓存协商呢,原因是因为缓存协商基于http请求和响应头中的Modified信息的,如果没有这个信息,是无法进行缓存协商的,对于动态内容来说,server无法帮我们决定内容是不是有改变的,也无法决定修改时间。继续修改

public class MeServlet extends HttpServlet {@Overrideprotected long getLastModified(HttpServletRequest req) {/*** 这里你要自己决定动态内容的最后修改时间,例如你可以返回* -- 数据缓存最后更新的时间* -- 简单起见,我们假设最后的修改时间是 1000*/return 1000;}@Overrideprotected void service(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException {/*** 1. 处理具体的业务:* -- 处理请求参数* -- 检查缓存* -- 处理具体数据* -- 更新缓存*/doBizLogic(req, res);/*** 2. 根据处理的结果转向具体的视图:* -- 这里假设就是 index.html*/getServletContext().getRequestDispatcher("/index.html").include(req, res);}public void doBizLogic(HttpServletRequest request, HttpServletResponse response) {System.out.println("do biz.");}
}

你会看到getLastModified这个方法是重写的,说明HttpServlet中已经有了这个方法,我们使用这个方法来告诉server在这个动态资源中,最后内容变化的时间是多少。最理想的情况是server会自己回调这个方法,那就太省心啦。

我们先访问的看看:发现依然每次都是200,server没有告诉浏览器最后的修改时间,缓存协商机制无法工作。

先别沮丧,忘了我们要解释什么问题吗——为什么不要重写service方法。也许你已经猜到了,如果你看看service方法的实现,现在你已经明白了,service方法自己实现了缓存协商的机制,如果我们重写它,反而将这中良好的机制给去掉了。我们再修改一下,这次我们重写doGet,在doGet中完成完全相同的逻辑:

public class MeServlet extends HttpServlet {@Overrideprotected long getLastModified(HttpServletRequest req) {/*** 这里你要自己决定动态内容的最后修改时间,例如你可以返回* -- 数据缓存最后更新的时间* -- 简单起见,我们假设最后的修改时间是 1000*/return 1000;}@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse res)throws ServletException, IOException {/*** 1. 处理具体的业务:* -- 处理请求参数* -- 检查缓存* -- 处理具体数据* -- 更新缓存*/doBizLogic(req, res);/*** 2. 根据处理的结果转向具体的视图:* -- 这里假设就是 index.html*/getServletContext().getRequestDispatcher("/index.html").include(req, res);}public void doBizLogic(HttpServletRequest request, HttpServletResponse response) {System.out.println("do biz.");}
}

再次访问

此时已经可以看到缓存已经出来啦。

作者

小小,一个双鱼座的文艺作者,来自于二线城市,生活在一线城市,在大城市的孤独与漂泊只有我自己一个人知道。我是小小,就是文中的老和尚,我们下期再见。

小明菜市场

推荐阅读

● 细说 | "失效"的private修饰符

● 知道 | 同学,你都了解关系型数据库,确定不了解一下这种数据库吗?

● 基础 | 零散的MySql基础记不住,看这一篇就够啦

● 面试 | 你说你熟悉MySql,那你就来谈谈InnoDB如何解决幻读的?

● 传记 | 我的大学三年-不以物喜,不以己悲

给我个好看再走好吗?

这是小小本周的第六篇,本篇小小将会介绍一个很古老很古老很古老的为什么系列之不能重写service方法。...相关推荐

  1. 都2021年了,不会还有人连深度学习还不了解吧(六)-- Padding篇

    导读 本篇文章主要介绍CNN中常见的填充方式Padding,Padding在CNN中用的很多,是CNN必不可少的组成部分,使用Padding的目的主要是为了调整输出的大小,是必须搞清楚的知识点.如果你 ...

  2. 自研机器人协调控制系统(2)——六足舞蹈篇

    自研机器人协调控制系统(2)--六足舞蹈篇 前言 系统 关于本文 一. 后4足站定舞蹈部分 1. 螳螂拳 1) 蓄势 2) 出拳 2. 太极 1) 云手 2) 收势 二. 6足舞蹈部分 1. 平移 2 ...

  3. [Python从零到壹] 三十六.图像处理基础篇之图像算术与逻辑运算详解

    欢迎大家来到"Python从零到壹",在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界.所有文章都将结合案例.代码和作者的经验讲 ...

  4. 仿百度壁纸客户端(六)——完结篇之Gallery画廊实现壁纸预览已经项目细节优化

    仿百度壁纸客户端(六)--完结篇之Gallery画廊实现壁纸预览已经项目细节优化 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Fragment 仿百度 ...

  5. 仿百度壁纸client(六)——完结篇之Gallery画廊实现壁纸预览已经项目细节优化...

    仿百度壁纸client(六)--完结篇之Gallery画廊实现壁纸预览已经项目细节优化 百度壁纸系列 仿百度壁纸client(一)--主框架搭建,自己定义Tab + ViewPager + Fragm ...

  6. 仿百度壁纸客户端(六)——完结篇之Gallery画廊实现壁纸预览已经项目细节优化...

    仿百度壁纸客户端(六)--完结篇之Gallery画廊实现壁纸预览已经项目细节优化 百度壁纸系列 仿百度壁纸客户端(一)--主框架搭建,自定义Tab + ViewPager + Fragment 仿百度 ...

  7. html5春节拜年,春节拜年日记六则6篇

    春节拜年日记六则6篇 春节拜年日记六则1 春节到了,万家团圆,家家户户都张灯结彩,喜气洋洋.我还穿上妈妈给我买的新衣服,穿上新鞋.妈妈说:"孩子快点吃,吃完了,我带你去外婆家拜年." ...

  8. C/C++基础讲解(八十六)之游戏篇(解救人质游戏)

    C/C++基础讲解(八十六)之游戏篇(解救人质游戏) 程序之美 前言 很多时候,特别是刚步入大学的学子们,对于刚刚开展的计算机课程基本上是一团迷雾,想要弄明白其中的奥秘,真的要花费一些功夫,我和大家一 ...

  9. GaN图腾柱无桥 Boost PFC(单相)六-终极细节篇

    最近一致在做关于PFC的项目,总的来说,PFC相交于三相pwm整流器简单,因为不涉及并网于能量回馈,易懂易理解,算法也比较少.前面的文章也是在调试PFC的时候所写,寻找相关文献,做相关实验以及仿真,都 ...

最新文章

  1. 文巾解题1588. 所有奇数长度子数组的和
  2. 环境监控告警系统之TIM即时消息推送部署(二)
  3. jquery中ajax参数说明
  4. Django从理论到实战(part26)--ORM模型
  5. Java中的功能性FizzBu​​zz Kata
  6. 【剑指offer】面试题24:反转链表(Java 实现)
  7. VMware converte报错记录
  8. C# Winform 窗体美化(七、Win7 Aero 毛玻璃效果)
  9. linux errno的作用域,关于比特科技c语言的学习博客(1)
  10. 在实验室服务器毫无阻拦的安装pip3
  11. 中国高校改名发展史:改了名,我们就是一流大学了
  12. C++11 using定义类型别名、模板别名
  13. 高等数学复盘 | 第七册上册第一章——第六章思维导图梳理(复习专用)
  14. 开源免费的pdf文档编辑器LibreOffice
  15. Arduino UNO步进电机控制
  16. 华为eNSP模拟器vlan 隔离技术的实现
  17. 多项式秦九韶算法c语言
  18. radmin配置说明
  19. 信阳发现多例蜱虫病病例
  20. 机械振动信号13个频域指标

热门文章

  1. [USACO08OPEN]寻宝之路Clear And Present Danger
  2. Selenium2+python自动化7-xpath定位
  3. C#类、接口、虚方法和抽象方法
  4. 在windows上搭建redis集群(主从复制)
  5. 01屏幕增强 sap_SAP (MM01 MM02 MM03)屏幕增强
  6. IndexTank全文检索引擎设计分析
  7. OpenJDK9 Hotspot :Zero 解释器 - BytecodeInterpreter
  8. C++ 0x: 内存模型
  9. 关于if 判断等于0 和‘0’的问题
  10. phash图像识别应用