MVC模式与Servlet执行流程
Servlet生命周期
五个部分,从加载到卸载,如同人类的出生到死亡
- 加载:Servlet容器自动处理
- 初始化:init方法 该方法会在Servlet被加载并实例化后执行
- 服务:service抽象方法:具体实现是doGet(),doPost()方法
- 销毁:destroy(),Servlet被系统回收时执行
- 卸载:Servlet容器自动处理
init():
- 默认第一次访问Servlet时会被执行(只执行这一次,可以修改为Tomcat启动时自动执行:
- 2.5:web.xml中
<servlet>字段添加<load-on-startup>1(代表第1个Servlet).. - 3.0:@WebServlet(value = "/Servlet3",loadOnStartup = 1)
service():->doGet() doPost:调用几次,则执行几次
destroy():关闭tomcat服务时
Servlet API
由两个大类四个软件包组成::

即Servlet API可以适用于任何通信协议。但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器。
我们学习的Servlet,是位于javax.servlet.http包中的类和接口,是基础HTTP协议。
Servlet继承关系
ServletConfig:接口
ServletContext getServletContext():获取Servlet上下文对象 application
String getInitParameter(String name):在当前Servlet范围内,获取名为name的参数值(初始化参数)
a.ServletContext中的常见方法(application):
getContextPath():相对路径
getRealPath():绝对路径
setAttribute()、getAttribute()
---->
String getInitParameter(String name);在当前Web容器范围内,获取名为name的参数值(初始化参数)
初始化全局参数
<context-param>
<param-name>globalParam</param-name>
<param-value>global value...</param-value>
</context-param>
初始化Servlet参数
- Servlet2.5
<servlet>
<servlet-name>my</servlet-name>
<servlet-class>com.hacker.servlet.MyServlet</servlet-class>
<load-on-startup>2</load-on-startup>
<!--配置当前Servlet初始化参数 -->
<init-param>
<param-name>servletparamname</param-name>
<param-value>servletparamvalue...</param-value>
</init-param>
</servlet>
- Servlet3.0
@WebServlet(value = "/Servlet3",loadOnStartup = 1,initParams = {@WebInitParam(name="servletparamname30",value = "servletparamvalue30")})
注意:此注解只隶属于某一个具体的Servlet,因此无法为整个Web容器设置初始化参数(如果要通过3.0方式设置,仍需在web.xml中设置)
获取全局参数
ServletContext对象表示Servlet应用程序。每个Web应用程序都只有一个ServletContext对象。在将一个应用程序同时部署到多个容器的分布式环境中,每台Java虚拟机上的Web应用都会有一个ServletContext对象。
通过在ServletConfig中调用getServletContext方法,也可以获得ServletContext对象。
@Override
public void init() throws ServletException {
System.out.println("init...");
//获取整个Web容器的初始化参数
String str=super.getServletContext().getInitParameter("globalParam");
System.out.println("当前Web容器的初始化的参数为"+str);
}
获取当前Servlet参数
当Servlet容器初始化Servlet时,Servlet容器会给Servlet的init( )方式传入一个ServletConfig对象
其中几个方法如下:

@Override
public void init() throws ServletException {
System.out.println("init...");
//获取当前Servlet的初始化参数
String str=super.getInitParameter("servletparamname");
System.out.println("当前Servlet的初始化参数为"+str);
}
请求与响应
当我们在在请求Servlet容器具体的执行流程的细节是什么呢?一起来看一看
首先我们知道请求的过程最终传给了名为service的方法,那service方式到底是怎么执行的,我们先来简单的了解下
首先查看入口类继承的HTTPServlet类


点进去发现继承至GenericServlet,继续跟进

GenericServlet实现了一个Servlet接口

接口中定义了service方法,并且有两个参数ServletRequest和ServletResponse代表请求和响应,那么我们自定义的Servlet肯定不是实现的这个service方法,因为我们重写的service方法形参为HttpServletRequest和HttpServletResponse

现在就来找找到底是重写的那个service方法,首先来看GenericServlet类

在GenericServlet类中发现实现了service的抽象方法,传入参数为ServletRequest,明显也不是,继续跟进HTTPServlet类

在HTTPServlet类中发现两个service方法,很明显第二个service方法参数也是ServletRequest,所以第二个service方法为实现方法,下面来看看具体实现
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest)req;
response = (HttpServletResponse)res;
} catch (ClassCastException var6) {
throw new ServletException(lStrings.getString("http.non_http"));
}
this.service(request, response);
}
可以看到该实现方法将Servlet强转为了HttpServlet,

HttpServlet继承自Servlet,将父类变为了子类,把通用的响应,转换为了特需的HTTP响应,之所以能够这样强制的转换,是因为在调用Servlet的Service方法时,Servlet容器总会传入一个HttpServletRequest对象和HttpServletResponse对象,预备使用HTTP。因此,转换类型当然不会出错了。
PS:Java中父类想要转换为子类,父类的实例必须指向子类的应用,形如
public static void main(String[] args) {
//Car为父类,BigCar为子类
Car car=new BigCar();//这里car父类对象的引用为BigCar子类 父类是子类构造出来的实例
BigCar bc=(BigCar)car;//所以这里可以将父类对象car强转为子类对象BigCar
bc.setName("ssss");//这里就可以调用子类的方法
test(new BigCar());
}
public static void test(Car car) {
BigCar bigCar = (BigCar) car;
if (bigCar instanceof Car) {
System.out.println("1");
}
}
最后调用了当前类中的重载方法service
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince;
try {
ifModifiedSince = req.getDateHeader("If-Modified-Since");
} catch (IllegalArgumentException var9) {
ifModifiedSince = -1L;
}
if (ifModifiedSince < lastModified / 1000L * 1000L) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
在该方法中,将请求类型进行了划分,判定请求类型调用不同的方法,所以我们重写的service方法实际上是接收了所有类型的请求,那么可以针对不同请求重写相应的方法,来简化我们的操作。
一般装饰者就是在主体组件扩展到具体的实现类时,会引入一个中间层,把装饰者的公布部分引入进来,在引入具体的实现时,只需要实现自己特定的部分就行了。公共的就放在上面,中间层中。而GenericServlet类就可以看作是那个中间层,它在空实现Servlet类的方法后,子类在继承的时候就可以只重写需要的方法,不必重写Servlet类的所有方法了。
MVC案例
学了这么多,现在就来动手实现一个MVC简单登录案例
MVC模式与Servlet执行流程的更多相关文章
- Servlet执行流程和生命周期【慕课网搬】
Servlet执行流程(GET方式为例) 首先用户客户端浏览器发出Get方式(点击超链接方式)向浏览器发出请求. 服务器接收到客户端点击超链接,接收到GET请求之后,服务器到WEB.xml中<s ...
- 【JAVA】servlet执行流程
servlet执行流程 客户端发出http请求,web服务器将请求转发到servlet容器,servlet容器解析url并根据web.xml找到相对应的servlet,并将request.respon ...
- Servlet执行流程和生命周期
Servlet执行流程 Get方式请求HelloServlet ---> <a href="servlet/HelloServlet"> ↓ 服务器在配置文档中查 ...
- Spring 框架基础(06):Mvc架构模式简介,执行流程详解
本文源码:GitHub·点这里 || GitEE·点这里 一.SpringMvc框架简介 1.Mvc设计理念 MVC是一种软件设计典范,用一种业务逻辑.数据.界面显示分离的方法组织代码,将业务逻辑聚集 ...
- Spring MVC必须知道的执行流程
Spring MVC的执行流程 一.名词解释 1.前端控制器(DispatcherServlet) 接收请求,响应结果,相当于转发器,中央处理器 2.处理器映射器(HandlerMapping) 根据 ...
- Spring MVC 原理介绍(执行流程)
Spring MVC工作流程图 图一 图二 Spring工作流程描述 1. 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServle ...
- Servlet 执行流程 生命周期 ServletConfig 线程安全
Day34 servlet 三.如何使用Servlet 1.继承GenericServlet类(通用) (1)GenericServlet类有一个关键的设计,定义了一个私有的ServletConfig ...
- servlet执行流程
视频地址:http://www.imooc.com/video/5550 1-6 用户输入地址:localhost:8080/MyFirstServletDemo/index.jsp (My ...
- java web简易网上书店项目系列,使用MVC模式(servlet+jstl+dbutils),开篇
一. 针对很多java web初学者入门困难的问题,笔者利用一个小型web项目,一步一步的展示java web开发方法,每一个章节引入一些java web开发的重点知识,让同学们可以将java web ...
随机推荐
- 投票通过,PHP 8 确认引入 Union Types 2.0
关于是否要在 PHP 8 中引入 Union Types 的投票已于近日结束,投票结果显示有 61 名 PHP 开发组成员投了赞成票,5 名投了反对票. 还留意到鸟哥在投票中投了反对票~) 因此根据投 ...
- 20191017-7 alpha week 2/2 Scrum立会报告+燃尽图 06
此作业要求参见https://edu.cnblogs.com/campus/nenu/2019fall/homework/9803 一.小组情况 队名:扛把子 组长:迟俊文 组员:宋晓丽 梁梦瑶 韩昊 ...
- Gemini.Workflow 双子工作流高级教程:数据库设计及各表作用说明
整体数据库设计,可见这一篇:Gemini.Workflow 双子工作流高级教程:数据库-设计文档 这里对各数据表进行介绍: 工作流里的设计表并不多,核心只有以下8个: 下面按照流程的顺序来介绍一下表的 ...
- JVM系列一(Java内存区域和对象创建).
一.JVM 内存区域 堆 - Heap 线程共享,JVM中最大的一块内存,此内存的唯一目的就是存放对象实例,Java 堆是垃圾收集器管理的主要区域,因此很多时候也被称为"GC堆"( ...
- Selenium多层级的iframe中元素的定位
很多时候我们遇到多层级的iframe就会想各种方法去获取iframe中的元素,但其实很简单就可以做到的,就是一级一级获取就可以了,获取至你需要的那个层级即可,下面看下实际的案例:(转) <fra ...
- 附011.Kubernetes-DNS及搭建
一 Kubernetes DNS介绍 1.1 Kubernetes DNS发展 作为服务发现机制的基本功能,在集群内需要能够通过服务名对服务进行访问,因此需要一个集群范围内的DNS服务来完成从服务名到 ...
- 记一次MySQL数据库导入错误
昨天在转数据的时候,控制台报出了下面这个warning: Warning: Data truncated for column '控制距离' at row 1 字面上意思应该是:控制距离这一字段在第一 ...
- php 第1讲 html介绍 html运行原理①
1. html (hypertext mark-up language )是 超文本编辑语言,主要的用处是做网页,可以在网页上显示文字.图形.动画.视频... “标记“有时候也称之为“元素” 动态网页 ...
- js对象可扩展性和属性的四个特性(上)
# js对象可扩展性和属性的四个特性(上) 一.前言 再次花时间回顾一下基础,毕竟要想楼建的好,地基就要牢固,嘻嘻! 在开始之前需要具备对prototype.__proto__.constructor ...
- 转:URL,URLConnection,HttPURLConnection的使用
URLConnection与HttPURLConnection都是抽象类,无法直接实例化对象.其对象主要通过URL的openconnection方法获得. 值得注意的是:1.openConnectio ...