附加:【Servlet】和【Spring MVC】的关系;【Servlet】体系简述;

说明:

(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其实我们并不需要学太多的知识,只要学会安装和启动以及了解一下各个目录的含义就差不多了。

preview

Tomcat各个目录的含义:

preview

2.2 Servlet版“Hello world“

首先,我们需要认清一个JavaWeb的标准目录结构:

preview

随后,我们编写一个最简单的Servlet程序和配置web.xml来完成一次交互。

preview

preview

在写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,无非就是学几个对象,但这几个对象对我们后面的学习都非常重要,我之前画过一张思维导图概括了这几个对象,希望对大家有帮助:

  • 7
    点赞
  • 55
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring MVC 框架的工作执行流程如下: 1. 客户端发送请求到 DispatcherServlet。 2. DispatcherServlet 根据请求信息调用 HandlerMapping,解析出 HandlerExecutionChain 对象,其中包含 HandlerInterceptor 数组和 Controller 对象。 3. DispatcherServlet 根据 HandlerExecutionChain 中的 HandlerInterceptor 数组,按照顺序执行每个拦截器的 preHandle 方法,若有拦截器返回 false,则执行流程中止,返回错误信息。 4. DispatcherServlet 调用 Controller 的方法处理请求,返回 ModelAndView 对象。 5. DispatcherServlet 根据 ModelAndView 中的 ViewName,调用 ViewResolver 解析出 View 对象。 6. DispatcherServlet 调用 View 的 render 方法,将模型数据渲染到视图中。 7. DispatcherServlet 根据 HandlerExecutionChain 中的 HandlerInterceptor 数组,按照逆序执行每个拦截器的 postHandle 方法。 8. DispatcherServlet 返回响应给客户端。 下面是一个简单的 Spring MVC 示例: 1. 配置 DispatcherServlet 和 HandlerMapping: ```xml <servlet> <servlet-name>dispatcherServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/config/spring-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcherServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> ``` 2. 编写 Controller 类: ```java @Controller public class HelloController { @RequestMapping("/hello") public ModelAndView hello() { ModelAndView model = new ModelAndView("hello"); model.addObject("message", "Hello, world!"); return model; } } ``` 3. 编写 ViewResolver 类: ```xml <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix" value="/WEB-INF/views/" /> <property name="suffix" value=".jsp" /> </bean> ``` 4. 编写 JSP 视图: ```jsp <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Hello</title> </head> <body> <h1>${message}</h1> </body> </html> ``` 这样,当客户端发送请求到 /hello 路径时,Spring MVC 框架会调用 HelloController 的 hello 方法处理请求,并返回 ModelAndView 对象,其中包含视图名称和模型数据。DispatcherServlet 会根据视图名称通过 ViewResolver 解析出 View 对象,并调用其 render 方法将模型数据渲染到视图中,最终返回响应给客户端。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值