【Servlet】Servlet的一般开发流程和执行过程

Servlet 是 Server Applet 的简称,译为“服务器端小程序”。

Servlet的定义:

  1. Servlet 运行在服务端的Java小程序;
  2. sun公司提供一套规范(接口),用来处理客户端请求、响应给浏览器的动态资源;
  3. servlet的实质就是java代码,通过java的API动态的向客户端输出内容;

Servlet的开发步骤

实现步骤:

  1. 创建类继承HttpServlet类;
  2. 重写doGet和doPost方法;
  3. 在web.xml中进行servlet的配置;
  4. 部署到Tomcat服务器;
  5. 在浏览器中输入URL,进行访问;

第一个Servlet程序实现,参照前一篇文章:Hello,Servlet

**Servlet运行的过程解析: **

tomcat服务器启动时,首先加载webapps中的每个Web项目的web.xml配置文件。
webapps文件夹里就是一个对外开放的资源库。

用户在浏览器输入:http://localhost:8080/KrojectDynamicWeb/HelloServlet后,

  1. http://:表明http协议
  2. localhost:到本地的hosts文件中查找是否存在该域名对应的IP地址,查找到是127.0.0.1
  3. 8080:根据端口找到运行中的Tomcat服务器
  4. KrojectDynamicWeb:在tomcat的webapps目录下找到KrojectDynamicWeb文件夹
  5. HelloServlet:资源名称,在KrojectDynamicWeb中的web.xml中查找,是否有匹配url-pattern的内容
  6. 如果找到匹配的url-pattern,则使用当前的servlet-name的名称到web.xml文件中查询是否有相同名称的servlet配置
  7. 如果找到,则取出对象的servlet配置信息中的servlet-class内容:net.hackyle.HelloServlet,即一个Java类
  8. 通过反射,构造HelloServlet对象,调用该对象里面的方法
  9. 执行方法,Tomcat服务器给浏览器做出响应,显示在浏览器的页面上

就是这样,你就看到了页面上你编写的内容。

Servlet接口

Servlet接口是已经过时了的开发接口,它的开发步骤是:

  1. 创建类实现Servlet接口
  2. 覆盖尚未实现的方法,如service方法
  3. 在web.xml进行servlet的配置

在实际开发中,我们不会直接去实现Servlet接口,因为那样需要覆盖的方法太多,我们一般创建类继承HttpServlet。但是它以及其里面的方法任然有学习的价值,因为HttpServlet是Servlet接口的实现

SUN公司定义了两个默认实现类,分别为:GenericServlet、HttpServlet。

  1. HttpServlet类:能够处理HTTP请求的servlet,它在原有Servlet 接口上添加了一些与HTTP协议处理方法,它比Servlet接口的功能更为强大。

  2. 因此开发人员在编写Servlet时,通常应继承这个类,而避免直接去实现Servlet接口

  3. HttpServlet在实现Servlet接口时,覆写了service方法,该方法体内的代码会自动判断用户的请求方式;

  4. 如为GET请求,则调用HttpServlet的doGet方法

  5. 如为Post请求,则调用doPost方法

  6. 因此,开发人员在编写Servlet时,通常只需要覆写doGet或 doPost方法,而不要去覆写service方法

接口方法

1)init(ServletConfig config)

  • 何时执行:servlet对象创建的时候执行,由服务器创建对象并调用init方法。
    ServletConfig :代表的是该servlet对象的配置信息

2)service(ServletRequest request,ServletResponse response)

  • 何时执行:每次请求都会执行
    ServletRequest :代表请求,认为ServletRequest 内部封装的是http请求的信息
    ServletResponse :代表响应 认为要封装的是响应的信息

3)destroy()

  • 何时执行:servlet销毁的时候执行

Servlet的生命周期

Servlet程序的生命周期由tomcat服务器控制。

1)Servlet何时创建:默认第一次访问servlet时创建该对象
2)Servlet何时销毁:服务器关闭servlet就销毁了
3)每次访问必然执行的方法:service(ServletRequest req, ServletResponse res)方法

Servlet四个生命周期方法

  1. 构造方法:创建servlet对象的时候调用。默认情况下,第一次访问servlet的时候创建servlet对象只调用1次。证明servlet对象在tomcat是单实例的。
  2. init方法创建完servlet对象的时候调用。只调用1次。
  3. service方法: 每次发出请求时调用。调用n次
  4. destroy方法销毁servlet对象的时候调用。停止服务器或者重新部署web应用时销毁servlet对象。只调用1次。

证明Servlet生命周期方法调用次数

import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

public class HelloServlet extends HttpServlet {
	 // 1.构造方法
	public HelloServlet(){
		System.out.println("1.servlet对象被创建了。");
	}

	 // 2.init方法
	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("2.init方法被调用");
	}
	
	 // 3.service方法
	@Override
	public void service(ServletRequest req, ServletResponse res)
			throws ServletException, IOException {
		System.out.println("3.service方法被调用");
	}
	
	 // 4.destroy方法
	@Override
	public void destroy() {
		System.out.println("4.servlet对象销毁了");
	}
}

在这里插入图片描述

web.xml

功能:

  • Web项目一启动,服务器就读取web.xml这个文件;
  • 因为这个文件告诉了Tomcat该从那个类开始执行,如何去执行;

HelloServlet的web.xml配置详情:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>KrojectDynamicWeb</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
    <description></description>
    <display-name>HelloServlet</display-name>
    <servlet-name>HelloServlet</servlet-name>
    <servlet-class>hello.HelloServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>HelloServlet</servlet-name>
    <url-pattern>/HelloServlet</url-pattern>
  </servlet-mapping>
</web-app>

servlet标签

<servlet>元素用于注册Servlet,它包含有两个主要的子元素:<servlet-name><servlet-class>,分别用于设置Servlet的注册名称和Servlet的完整类名
一个<servlet-mapping>元素用于映射一个已注册的Servlet的一个对外访问路径,它包含有两个子元素:<servlet-name><url-pattern>,分别用于指定Servlet 的注册名称和Servlet的对外访问路径
在这里插入图片描述

url-pattern的映射

访问Web项目的URL中,最后一个组成成分(“http://localhost:8080/KrojectDynamicWeb/HelloServlet”),将会在项目工程中的web.xml中查找是否有匹配的url-pattern的内容,匹配成功才能正常运行URL;

例如URL: http://localhost:8080/Kroject/first;映射路径是指把”/first”在web.xml中的url-pattern中寻找是否有一样的;
在这里插入图片描述
在这里插入图片描述

在执行URL最后部分与url-pattern的匹配过程中,有两种匹配类型:
A. 精确匹配
浏览器输入:url-pattern
http://localhost:8080/day10/first: /first
http://localhost:8080/day10/itcast/demo1: /itcast/demo1

B. 模糊匹配
浏览器输入 ===> url-pattern
http://localhost:8080/day10/任意路径 ===> /*
http://localhost:8080/day10/itcast/任意路径 ===> /itcast/*
http://localhost:8080/day10/任意路径.后缀名 ===> *.后缀名
http://localhost:8080/day10/任意路径.do ===> *.do
http://localhost:8080/day10/任意路径.action ===> *.action

注意事项:

  1. 在url-pattern中有两种固定的格式:一种格式是“*.扩展名”;另一种格式是以正斜杠(/)开头并以*结尾。
  2. url-pattern要么以 / 开头,要么以*开头。
  3. 不能同时使用两种模糊匹配,例如 /itcast/*.do是非法路径
  4. 当有输入的URL有多个servlet同时被匹配的情况下:
    a) 精确匹配优先。(长的最像优先被匹配)
    b) 以后缀名结尾。(*.后缀名)的模糊url-pattern优先级最低!!!

缺省路径

Tomcat的安装“config”目录下的web.xml文件指定了缺省路径(即当我们输入的一个URL,在webapps目录下并没有找到,于是就把缺省路径下的一个HTML资源返回。)
在这里插入图片描述
在这里插入图片描述

Tomcat安装目录下的config/web.xml

servlet的缺省路径(/)是在tomcat服务器内置的一个路径。该路径对应的是一个DefaultServlet(缺省Servlet)。这个缺省的Servlet的作用是用于解析web应用的静态资源文件。

匹配问题例题
问题: URL输入http://localhost:8080/day10/index.html 如何读取文件????
解答:
1)到当前day10应用下的web.xml文件查找是否有匹配的url-pattern。
2)如果没有匹配的url-pattern,则交给tomcat的内置的DefaultServlet处理
3)DefaultServlet程序到day10应用的根目录下查找是存在一个名称为index.html的静态文件。
4)如果找到该文件,则读取该文件内容,返回给浏览器。
5)如果找不到该文件,则返回404错误页面。

结论:先找动态资源,再找静态资源。尽量不要在web.xml文件下配置伪静态文件。

Tomcat服务器运行Servlet的过程

  1. 当服务器接收到URL后;

  2. 经过URL与web.xml中的url-pattern进行映射匹配后;

  3. 找到了servlet-class的内容,得到了本次URL需要调用的类的全名:net.hackyle.HelloServlet;

  4. 通过反射构造该类对象,即构造HelloServlet类的对象;

  • 得到字节码对象:Class class = class.forName("net.hackyle.HelloServlet ");
  • 调用无参数的构造方法来构造对象:Object obj = class.newInstance(); (注意:此时servlet的构造方法被调用)
  1. 创建ServletConfig对象,通过反射调用init方法
  • 得到方法对象:Method m = class.getDeclareMethod(“init”,ServletConfig.class);
  • 调用方法:m.inmoke(obj,config); (注意:此时servlet的init方法被调用)
  1. 创建request,response对象,通过反射调用service方法
  • 得到方法对象:Methodm m=class.getDeclareMethod(“service”,HttpServletRequest.class,HttpServletResponse.class);
  • 调用方法:m.invoke(obj,request,response); (注意:servlet的service方法被调用)
  1. 当tomcat服务器停止或web应用重新部署,通过反射调用destroy方法
  • 得到方法对象:Method m = clazz.getDeclareMethod(“destroy”,null);
  • 调用方法:m.invoke(obj,null); (注意:servlet的destroy方法被调用)

再次请求相同URL

① Web服务器首先检查是否已经装载并创建了该Servlet的实例对象。如果是,则直接执行第④步,否则,执行第②步。
② 装载并创建该Servlet的一个实例对象。
③ 调用Servlet实例对象的init()方法。
④ 创建一个用于封装HTTP请求消息的HttpServletRequest对象和 一个代表HTTP响应消息的HttpServletResponse对象,然后调用 Servlet的service()方法并将请求和响应对象作为参数传递进去。
⑤ WEB应用程序被停止或重新启动之前,Servlet引擎将卸载 Servlet,并在卸载之前调用Servlet的destroy()方法。

自动加载机制

出现背景:

  1. 默认情况下,第一次访问servlet的时候创建servlet对象。
  2. 如果servlet的构造方法或init方法中执行了比较多的逻辑代码,那么导致用户第一次访问sevrlet的时候比较慢。

解决方案:

  1. 改变servlet创建对象的时机;
  2. 提前到加载web应用的时候!!! 即在servlet的web.xml配置信息中,加上一个即可!!
  3. 在中的整数值越大,创建优先级越低!!
  4. 可以为多个类创建快速启动;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章