说明:
(1)为什么写本篇博客?:
● 在【Spring MVC拦截器1:拦截器入门一:拦截器(interceptor)简介;拦截器开发流程简介;演示了拦截器最基本的配置流程;】中:这是一个Spring MVC项目,然后在这个项目中我们引入了servlet-api.jar依赖;当时心里就像,Spring MVC就是用来替代Servlet的,为什么在一个Spring MVC项目中,还需要引入servlt-api.jar?
● 自然,在【Spring MVC拦截器1:拦截器入门一:拦截器(interceptor)简介;拦截器开发流程简介;演示了拦截器最基本的配置流程;】中已经给出了两个个理由:原因1:拦截器的HandlerInterceptor接口的三个方法需要【HttpServletRequest request, HttpServletResponse response】参数;
原因2:当IDE是IDEA,并且项目中用到servlet-api.jar的时候,我们大概率需要手动引入servlet依赖;
● 但是,还不明白的是:为什么一个在一个Spring MVC项目中,还需要引入servlt-api.jar?
● 为了解决这个疑问,就需要搞清楚【Spring MVC】和【Servlet】的关系;因而,就有了本篇博客;
(2)本篇博客参考的博客有:
● 【带着新人简单看看servlet到springmvc】,该文的作者是【java小新人】;然后,该作者很强,他有很多具有参考价值的博客;读者可以去瞅瞅。
● 知乎的一个问答:【servlet技术是否过时?】
(3)本篇博客可以帮助提升【对Spring MVC和Servlet的理解】,但深知知道这些还不够,需要继续学习、继续努力;
(4)本篇博客的给自己的提示:
● 不要只做,做调包侠,理解背后的原理十分重要:以后,有精力了,可以买几本专业的经典书籍,系统性的了解下;
● 透彻理解Servlet的实现和原理:十分必要;
● 在透彻理解Servlet后,可以自己实现一个简单版的Spring MVC;
以下内容,完全摘抄自 【带着新人简单看看servlet到springmvc】,该文的作者是【java小新人】;
这部分,对目前的自己来说主要有两点:
(1)第一:通过这个图,能帮助理解【Servlet】和【Spring MVC】的关系:【Spring MVC】还是需要【Servlet】的;
(2)帮助自己建立看源码的思路和方法;
带着新人简单看看servlet到springmvc
好久都没有写博客了,不是因为自己懒了,而是总感觉自己知道的只是太少了,每次想写博客的时候都不知道怎么下手,不过最近看到一篇博客说的是springmvc,给了我比较大的兴趣,感觉一下子对整个springmvc框架一下子清晰了,很多感觉模糊的东西一下子就清晰明了的。
我把那个老哥原博客网址贴出来:https://www.cnblogs.com/xdp-gacl/p/4101727.html
不过呢,如果只是将springmvc感觉不过瘾,于是顺带着说说servlet吧,以及为什么说springmvc本质上就是一个servlet,假如你能说明白这一点那么你的springmvc就掌握得很清楚了,后面我们根据那个老哥的博客,我们一起简单实现一下springmvc就差不多了。
1.简单看看servlet
1.1.servlet继承关系
先看看下面servlet的这个继承关系,有点印象即可(可以暂时忽略ServletConfig,这个接口就是让我们可以从web.xml文件中拿到标签中的参数,比如<servlet-name>,<init-param>等标签中的参数)
然后我们看一下最简单的servlet用法,概念和由来就不说了,说了我们也不懂,就知道能够通过浏览器访问servlet就够了。
1.2.servlet最简单的用法
新建一个myspringmvc项目,然后弄一下如下配置
可以了,就这么多,然后我们运行eclipse中集成的tomcat,在浏览器输入url就能访问了,很容易。
1.3.servlet生命周期
这个时候有个小问题,为什么我们发送一个get请求(在浏览器输入网址),就会直接跳转到get方法呢?这么智能的么,这么牛?
所以我们要站得高一点的角度看servlet的大概结构,如下图,最重要的就是这三个方法,还有另外两个方法暂时忽略:getServletConfig()是可以拿到web.xml中配置的<init-param>等标签的参数,还有getServletInfo()其实就是返回作者信息,版本信息等等,貌似还没用过。。。。。
最重要的就是那三个方法,一般别人都把这三个方法叫做servlet的生命周期。(注意service方法的两个参数,没有实现HTTP协议)
到了这里,假如就给你这样一个接口,让你自己写实现类,你感觉怎么样?反正我是很绝望的,不知道从哪里下手,这么多功能要实现,自己水平又比较菜,怎么编写一个完全的servlet实现类呢?
于是啊,一个抽象类就出来了GenericServlet,这个抽象类实现了Servlet接口,把几乎所有的方法都给你实现出来了,比如获取servlet上下文,获取initParameter等等常用的功能,就留下了那三个生命周期方法init(), service(),destroy()没有实现,这就需要我们自己去实现类,所以我们可以继承这个抽象类,实现这三个方法就ok了。
但是啊,我还是有点不会,因为我是用过浏览器发请求过来啊,你这个service方法要干嘛呢?主要逻辑是什么啊?而且每次都要实现这三个方法,好麻烦的啊,因为还要判断是get还是post方式提交,再调用get或者post方法,而且都是重复的东西,有点不会。
终于,出来了一个比较全面的抽象类HttpServlet,这个类继承了GenericServlet,还实现了http协议,其中做的最主要的是就是将那service()生命周期方法给实现了,并且在这里会根据浏览器提交过来数据的方式,给分发到各自的方法去实现,比如分发到doGet(),doPost()等,简单看一下源码
后面还有post,put,delete方法的判断,跟这里几乎一样,而且在本类中已经定义了doGet(),doPost()等方法,几乎没有怎么实现,所以啊,我们只需要继承HttpServlet类,根据我们的请求方式实现doGet(),doPost()等方法就可以了,分工明确,用起来也很舒服。
而且这里新手可能有点头晕,为什么会调用我们实现的doGet,doPost方法,而不是父类中的那些doXXX()方法呢?其实啊,这里又是一个基础知识,比如子类B继承父类A,重写父类方法aa(),那么实例化子类之后(这里就是多态的用法),调用aa()方法肯定是先在子类中找有没有aa()方法,有的话就调用子类的,没有的话就调用父类的!应该在java基础的时候这种问题贼多,坑了很多新人。
到这里Servlet的大概轮廓就清楚了,我们再来看看最上面的那个截图,是不是觉得懂了一点点了
2.简单看看springmvc初始化过程
还记得最开始学习springmvc的时候是自己看视频学习的,刚开始有很多的问题不懂,要自己慢慢理解,然后大量的查资料,记得比较清楚的一句话是说:springmvc中那个前端控制器其实就是一个servlet,springmvc的本质就是一个servlet!
反正我是牢记这个概念,哦哦,原来springmvc本质就是一个servlet啊,然后我就放着不管了,也不是怎么懂,反正我springmvc用的贼熟练。不就是那几个处理器吗?前端控制器,处理器映射器,处理器控制器,controller,视图解析器,我经常简单的这么一配置,就可以用了,然后和spring一整合,ok了!
2.1.springmvc和servlet的关系
首先问一个问题,为什么前端控制器是一个servlet啊?难道也是继承了HttpServlet吗?其中大概的流程是怎么样的呢?总感觉很模糊,似懂非懂。
那么我们就先来看一个前端控制器(DispatcherServlet)的继承结构(混个眼熟):
上图很明显,有三个新增的类,分别是HttpServletBean,FrameworkServlet,DispatcherServlet;这三个类我第一眼看过去反正我是不知道干嘛用的,就大概知道最后那个前端控制器,所以我们就慢慢的来看看前面两个类是干嘛用的啊?把前面两个弄清楚了,就差不多了。
2.2.随便看看HttpServletBean,FrameworkServlet
对于HttpServletBean,我们先回忆前面的servlet的内容,在HttpServlet总只是实现了service()方法并在其中做了方法分发,但是servlet生命周期可是有三个方法啊,还有init()和destroy(),于是我们在这里就会用到init方法了;
这里会重写GenericServlet的init方法(其实就是重写HttpServlet的父类GenericServlet的init方法)
由于这个initServletBean()方法是一个空方法,肯定是留给子类去实现的,然后我们去FrameworkServlet中还真的找到了这个initServletBean()方法。
这里就是一个比较重要的地方了,稍微截一下initServletBean()方法中的代码:
注意:大家知不知道springmvc+spring整合的时候,会有父子容器的概念!父容器就是ioc容器,启动toncat就会被web.xml中的那个监听器监听到,立马就会创建ioc容器,里面放的是service,dao,以及其他的各种bean;这里的子容器是springmvc的容器,里里面放着web层的所有组件,处理器映射器,处理器适配器,视图解析器,controller等;
还有我没有记错的话,由于父容器先创建,子容器后创建。所以父容器的引用会保存在子容器一份,所以可以通过子容器获取父容器的实例,然后再获取其中的bean;
在initWebApplicationContext()方法中,其实就是对spring 子容器的创建以及刷新,这里就随便提一下,不深入了!我们只看其中的刷新方法:
你点开刷新方法你会发现这又是一个空方法,等着子类去实现的!不知道大家到这里有没有看到一个很有趣的逻辑,就是很多时候,一个类中有些方法自己是不会去实现的,而是要留给子类去实现,哈哈哈!子类假如会说话,肯定会说:我真是日了狗哦!
2.3.继续随便看看DispatcherServlet
终于到这个类了,前面说了这么多,都快睡着了。。。
由上面可以知道,DispatcherServlet中肯定要实现那个刷新方法,于是我们就直接到这个刷新方法看看到底是什么鬼!
可以看到初始化了好多组件,注意一点:这里的context是子容器。
3.springmvc处理请求
前面springmvc初始化说了这么多,其实就是将子容器创建,然后初始化了那9个组件放进去就ok了,那么接下来就说说怎么处理一个请求吧!
还记得前面说处理请求,也就是我们在浏览器输入网址,一点回车,就会执行相应servlet的service()方法吧!
在HttpServlet中的service()方法中接收请求,根据请求方式(Get,Post等)分发到相应的doGet(),doPost()等方法,然后我们在FrameworkServlet中会发现,这个类将这些service和doGet(),doPost()等方法都重写了,是个狠类啊!
我们就来简单看看FrameworkServlet中的方法执行流程吧,不细看源码!
打开doGet方法,发现也是到processRequest()方法中
我们继续往processRequest()方法看:
我们接下来就是在DispatcherServlet中看看有没有doService()方法了;
看看最后的doDispatcher方法:
到这里,基本就差不多了,把整个结构都给梳理了一遍!肯定还有很多小伙伴对后半段有点迷糊,放心,我下一篇博客会一起来简单实现一下我们自己的springmvc框架。
以下内容参考自知乎的一个问答:【servlet技术是否过时?】
Servlet过时了吗?
以下内容,参考自【该知乎问答:servlet技术是否过时?】;该回答的作者是:【清浅池塘】。
以下内容,参考自【该知乎问答:servlet技术是否过时?】;该回答的作者是:【lalala】。
以下综述性的内容,同样参考自【该知乎问答:servlet技术是否过时?】;该回答的作者是:【Java3y】。
这个综述,主要内容是【Servlet综述】,这有助于帮助自己梳理思路,把以前学习过的内容给串起来;
前言
工作已经有一段时间了,如果让我重新学Servlet,我会怎么学呢?下面抛出两个常见的问题,我分开来解答
- 2020年了,还需要学Servlet吗?
- Servlet的学习路线(学习重点)
一、2020年了,还需要学Servlet吗?
老实说,Servlet放在现在肯定算是一个古老的技术了。现在你去任何的一家公司,应该都不是直接用Servlet来写项目的。现在的项目一般来说还是以
SpringMVC-Spring-Mybatis / SpringBoot
居多。面试也几乎不会问Servlet的知识(无论是校招还是社招)既然Servlet已经是一个这么古老的技术了,那我还需要学吗?这是一个非常常见的问题。我初学的时候也非常喜欢搜相关的问题:“
SWING/AWT
这种技术还需要学吗”。无论是我在知乎回答Java学习路线,还是读者问到的这个问题,我都会给予肯定的回答:“需要学Servlet,不要跳过Servlet去学框架”
我因为好好学了Servlet,在学Struts2(没错,我还学过Struts2)和SpringMVC的都非常容易上手,几天就基本会用了。
如果了解
Struts2或SpringMVC
的同学就会知道,其实他俩的底层都离不开Servlet。Struts2的核心用的是Filter(过滤器),而SpringMVC的核心用的就是Servlet。学过Servlet好处是什么:
- 打下坚实的基础,学习框架就得心应手了。
二、Servlet的学习路径
下面我来讲讲Servlet的重点有哪些,其实就是学习Servlet的路线。还是要重复一句话:“在学习一项技术之前,首先要知道为什么要学习它”
2.1 Tomcat
学Servlet之前,首先我们要学学
Tomcat
。Tomcat是一个Web服务器(同时也是Servlet容器),通过它我们可以很方便地接收和返回到请求(如果不用Tomcat,那我们需要自己写Socket来接收和返回请求)。Tomcat其实我们并不需要学太多的知识,只要学会安装和启动以及了解一下各个目录的含义就差不多了。
Tomcat各个目录的含义:
2.2 Servlet版“Hello world“
首先,我们需要认清一个JavaWeb的标准目录结构:
随后,我们编写一个最简单的Servlet程序和配置
web.xml
来完成一次交互。
在写Servlet的时候,我们顺便了解一下Servlet的继承体系和生命周期;
2.3 HTTP简单学一下
HTTP协议是客户端和服务器交互的一种通迅的格式。
例如:在浏览器点击一个链接,浏览器就为我打开这个链接的网页。
原理:当在浏览器中点击这个链接的时候,浏览器会向服务器发送一段文本,告诉服务器请求打开的是哪一个网页。服务器收到请求后,就返回一段文本给浏览器,浏览器会将该文本解析,然后显示出来。这段「文本」就是遵循HTTP协议规范的。
在初学的时候,我们只要记住一些常用的头信息(请求头和响应头)就足够了。
2.4 ServletConfig和ServerContext对象
ServletConfig:通过此对象可以读取
web.xml
中配置的初始化参数,不写硬编码,将配置写在配置文件中。ServletContext:这个对象是在Tomcat启动的时候就会创建,代表着当前整个应用。我们一般用来获取整个应用的配置信息(ServletConfig是单个的,而ServletContext是整个应用的),还可以用这个对象来读取资源文件。
这几个最基本的Servlet对象学完了以后,我们就可以关注一下Servlet的一些小细节了,比如说:
- Servlet是单例的
- 配置通配符的时候可以用各种的通配符
*.
和一个Servlet可以被多个配置映射- 访问任何资源其实都是在访问Servlet(即便是访问图片资源,Tomcat都有默认Servlet处理)
- ....
2.5request和response对象
Servlet的重点需要学习request和response对象。当我们学完HTTP的请求头和响应头以后,再看到这两个对象。我们就应该知道:request其实就是封装了HTTP的请求头,而response就是封装了HTTP响应头。
这两个对象是Servlet中最重要的,因为我们跟外接的交互都是通过request和response对象来进行的。
通过response对象,我们可以尝试写一些Demo,比如:
- 给浏览器输出一些简单的内容
- 实现文件下载的功能
- 实现页面自动刷新的功能
- 实现对数据的压缩
- 生成验证码图片
- 重定向跳转
- .....
通过request对象,我们也可以尝试做些Demo,比如:
- 得到浏览器的传递过来的各类信息(请求参数、请求头等)
- 实现防盗链
- 通过request对象来转发
- 解决请求参数中文乱码的问题
- ....
一句话总结:request对象主要用于接收请求各种的信息,response对象主要用户返回给请求各种的信息。围绕着请求、响应我们分别有request和response对象供我们操作。
2.6 Cookie和session会话机制
前面我们已经学到了Servlet的几个对象了,分别是Config(获取配置信息)、Context(代表整个Web应用)、Request(HTTP请求)、Response(HTTP响应)。
每个网站都会有登录注册的功能,那它是怎么实现的呢?上这上面的几个对象,好像都不是实现登录注册的。于是我们该来学学会话机制 Cookie和Session啦。
首先我们了解一下Cookie是存储在哪的,以及Cookie的基本API使用,包括:
- Cookie的有效期如何设置
- Cookie如何保存中文
- Cookie的不可跨域性是什么意思
- 使用Cookie来显示用户上次访问的时间
- 使用Cookie来显示上次浏览过的商品
Cookie的API使用基本会了以后,我们就可以学习Session了,学Session的时候我们需要解决:
- 有了Cookie,为什么需要Session(因为他俩都是会话机制)
- Session的API基本使用
- Session的生命周期和有效期
- Session的实现原理,如果禁用Cookie,还能使用Session吗
- 尝试完成Session的几个小Demo
- 使用Session完成购物的功能
- 使用Session完成简单的登录注册
- 使用Session完成防止表单重复提交
- 使用Session完成一次性校验码
完了以后,我们可以对比一下Cookie和Session的区别主要有哪些。
一句话总结:Cookie是检查用户身上的”通行证“来确认用户的身份,Session就是通过检查服务器上的”客户明细表“来确认用户的身份的。Session相当于在服务器中建立了一份“客户明细表”。
2.7 Servlet知识总结
其实纵观Servlet,无非就是学几个对象,但这几个对象对我们后面的学习都非常重要,我之前画过一张思维导图概括了这几个对象,希望对大家有帮助: