Java全栈web网页技术:8.Servlet

Posted new nm个对象

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java全栈web网页技术:8.Servlet相关的知识,希望对你有一定的参考价值。

Servlet组件

第1章 我们为什么需要Servlet?

  • 已注册为例,前端提交的数据不能直接传到数据库中,需要先传到Java中,然后再通过jdbc技术传入数据库中。而Java程序要获取前端的数据或者发送数据给前端页面可以使用servlet技术。
  • servlet:可以理解为有url特性的Java代码

1.1 Web应用基本运行模式

  • 生活中的例子

  • Web应用运行模式

1.2 Web服务器中Servlet作用举例

  • 举例一:插入数据

  • 举例二:查询数据

通过网页驱动服务器端的Java程序。在网页上显示Java程序返回的数据。

第2章 什么是Servlet?

如果把Web应用比作一个餐厅,Servlet就是餐厅中的服务员——负责接待顾客、上菜、结账。

  • 从广义上来讲,Servlet规范是Sun公司制定的一套技术标准,包含与Web应用相关的一系列接口,是Web应用实现方式的宏观解决方案。而具体的Servlet容器负责提供标准的实现。
  • 从狭义上来讲,Servlet指的是javax.servlet.Servlet接口及其子接口,也可以指实现了Servlet接口的实现类。
  • Servlet(Server Applet)作为服务器端的一个组件,它的本意是“服务器端的小程序”。
    • Servlet的实例对象由Servlet容器负责创建;
    • Servlet的方法由容器在特定情况下调用;
    • Servlet容器会在Web应用卸载时销毁Servlet对象的实例。

第3章 如何使用Servlet?

3.1 操作步骤

  • 复习:使用一个接口的传统方式:

    • 创建一个类实现接口
    • new 实现类的对象
    • 调用类的方法等
  • 使用Servlet接口的方式:

    ① 搭建Web开发环境

    ② 创建动态Web工程
    按照前面的方法,将动态工程创建好后,还需要引入Servletjar包:
    第一步: RUN》Edit Configurations》

    第二步:在当前项目的iml文件中引入tomcat

    第三步:重启idea

    ③ 创建javax.servlet.Servlet接口的实现类:com.atguigu.servlet.MyFirstServlet

    ④ 在service(ServletRequest, ServletResponse)方法中编写如下代码,输出响应信息:

@Override
	public void service(ServletRequest req, ServletResponse res)
			throws ServletException, IOException 
		//1.编写输出语句,证明当前方法被调用
		System.out.println("Servlet worked...");
	

​ ⑤ 在web.xml配置文件中注册MyFirstServlet

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <!-- 这是Servlet的别名,一个名字对应一个Servlet。相当于变量名 -->
        <servlet-name>MyFirstServlet</servlet-name>
        <!-- Servlet的全类名,服务器会根据全类名找到这个Servlet -->
        <servlet-class>com.atguigu.servlet.MyFirstServlet</servlet-class>
    </servlet>

    <!-- 建立Servlet的请求映射信息 -->
    <servlet-mapping>
        <!-- Servlet的别名,说明这个Servlet将会响应下面url-pattern的请求 -->
        <servlet-name>MyFirstServlet</servlet-name>
        <!-- Servlet响应的请求路径。如果访问这个路径,这个Servlet就会响应 -->
        <url-pattern>/MyFirstServlet</url-pattern>
    </servlet-mapping>
</web-app>

说明:

  • <url-pattern>:这个url-pattern可以配置多个,这时表示的就是访问这些url都会触发这个Servlet进行响应,运行浏览器,访问刚才配置的url路径,Servlet的service方法就会被调用。

  • <url-pattern>中的文本内容必须以 / 或 *. 开始书写路径。相当于将资源映射到项目根目录下形成虚拟的资源文件。

  • <servlet-mapping>中的<url-pattern>可以声明多个,可以通过任意一个都可以访问。但是开发中一般只会配置一个。

  • <servlet-mapping>中的servlet-name必须与<servlet>中的servlet-name一致

  • 解析流程:

​ ⑥ 在web目录下创建index.html

​ ⑦ 在index.html中加入超链接 <a href=“MyFirstServlet”>To Servlet

⑧ 在idea中启动tomcat服务

​ ⑨ 点击超链接测试Servlet

3.2 运行分析(执行原理)

  • index.html

  • web.xml

  • 如果配置文件一旦修改,需要重启服务器来重新部署web项目。

3.3 Servlet作用总结

  • 接收请求 【解析请求报文中的数据:请求参数】

  • 处理请求 【DAO和数据库交互】

  • 完成响应 【设置响应报文】

第4章 Servlet生命周期(重要)

4.1 Servlet生命周期概述

  • 应用程序中的对象不仅在空间上有层次结构的关系,在时间上也会因为处于程序运行过程中的不同阶段而表现出不同状态和不同行为——这就是对象的生命周期。
  • 简单的叙述生命周期,就是对象在容器中从开始创建到销毁的过程。

4.2 Servlet容器

Servlet对象是Servlet容器创建的,生命周期方法都是由容器调用的。这一点和我们之前所编写的代码有很大不同。在今后的学习中我们会看到,越来越多的对象交给容器或框架来创建,越来越多的方法由容器或框架来调用,开发人员要尽可能多的将精力放在业务逻辑的实现上。

4.3 Servlet生命周期的主要过程

① Servlet对象的创建:构造器

  • 默认情况下,Servlet容器第一次收到HTTP请求时创建对应Servlet对象。
  • 容器之所以能做到这一点是由于我们在注册Servlet时提供了全类名,容器使用反射技术创建了Servlet的对象。
  • 执行时机:第一次接收请求时执行
  • 执行次数:在整个生命周期中,只执行一次。【Servlet单例】

② Servlet对象初始化:init()

  • Servlet容器**创建Servlet对象之后,会调用init(ServletConfig config)**方法。
  • 作用:是在Servlet对象创建后,执行一些初始化操作。例如,读取一些资源文件、配置文件,或建立某种连接(比如:数据库连接)
  • init()方法只在创建对象时执行一次,以后再接到请求时,就不执行了
  • 在javax.servlet.Servlet接口中,public void init(ServletConfig config)方法要求容器将ServletConfig的实例对象传入,这也是我们获取ServletConfig的实例对象的根本方法。
  • 执行时机:第一次接收请求时,再执行完构造器之后,执行。
  • 执行次数:在整个生命周期中,只执行一次

③ 处理请求:service()

  • 在javax.servlet.Servlet接口中,定义了**service(ServletRequest req, ServletResponse res)**方法处理HTTP请求。
  • 在每次接到请求后都会执行。
  • 上一节提到的Servlet的作用,主要在此方法中体现。
  • 同时要求容器将ServletRequest对象和ServletResponse对象传入。
  • 执行时机:每次接收请求时都会执行
  • 执行次数:在整个生命周期中,会执行多次

④ Servlet对象销毁:destroy()

  • 服务器重启、服务器停止执行或Web应用卸载时会销毁Servlet对象,会调用public void destroy()方法。
  • 此方法用于销毁之前执行一些诸如释放缓存、关闭连接、保存内存数据持久化等操作。
  • 执行时机:在关闭服务器时执行
  • 执行次数:在整个生命周期中,只执行一次。

面试讲解:

  • 当Servlet第一次接收请求时,Servlet容器【web容器|web服务器】会调用构造器创建Servlet对象。之后执行init()方法,进行初始化操作。最后执行service()方法,处理请求,做出响应。
  • 之后再接收请求,只会执行service()方法。
  • 当关闭或重启服务器时,执行destroy()方法,销毁Servlet对象

案例

4.4 Servlet请求过程

  • 第一次请求
    • 调用构造器,创建对象
    • 执行init()方法
    • 执行service()方法
  • 后面请求
    • 执行service()方法
  • 对象销毁前
    • 执行destroy()方法
public class MyFirstServlet implements Servlet 
    public MyFirstServlet() 
        System.out.println("调用构造器");
    

    @Override
    public void init(ServletConfig servletConfig) throws ServletException 
        System.out.println("调用init");
    

    @Override
    public ServletConfig getServletConfig() 
        return null;
    

    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException 
        //1.编写输出语句,证明当前方法被调用
        System.out.println("调用service");
    

    @Override
    public String getServletInfo() 
        return null;
    

    @Override
    public void destroy() 
        System.out.println("调用destroy");
    

页面第一次请求相关url,测试一下:

通过页面再次请求url,测试一下:

最后关闭tomcat服务器,测试一下:

4.5 通过配置文件修改Servlet的生命周期

我们在web.xml配置文件中,可以修改Servlet对象的生命周期:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
    <servlet>
        <!-- 这是Servlet的别名,一个名字对应一个Servlet。相当于变量名 -->
        <servlet-name>MyFirstServlet</servlet-name>
        <!-- Servlet的全类名,服务器会根据全类名找到这个Servlet -->
        <servlet-class>com.demo1.MyFirstServlet</servlet-class>
        <!--表示在启动服务时创建Servlet对象,即启动服务时就调用构造方法和init()方法-->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <!-- 建立Servlet的请求映射信息 -->
    <servlet-mapping>
        <!-- Servlet的别名,说明这个Servlet将会响应下面url-pattern的请求 -->
        <servlet-name>MyFirstServlet</servlet-name>
        <!-- Servlet响应的请求路径。如果访问这个路径,这个Servlet就会响应 -->
        <url-pattern>/MyFirstServlet</url-pattern>
    </servlet-mapping>
</web-app>
  • <load-on-startup>标签:表示在启动服务时创建Servlet对象,即启动服务时就调用构造方法和init()方法
  • 标签中的值要是正整数,最新为1。用来设置Servlet被创建的优先级【主要是当有多个Servlet需要创建时,用来区分创建的优先级】。数值越小优先级越高。

第5章 Servlet的两个重要接口

官方API中声明如下:

5.1 ServletConfig接口

  • ServletConfig接口封装了Servlet配置信息,这一点从接口的名称上就能够看出来。

  • 每一个Servlet都有一个唯一对应的ServletConfig对象,代表当前Servlet的配置信息。

  • 对象由Servlet容器创建,并传入生命周期方法init(ServletConfig config)中。可以直接获取使用。

  • 代表当前Web应用的ServletContext对象也封装到了ServletConfig对象中,使ServletConfig对象成为了获取ServletContext对象的一座桥梁。

  • ServletConfig对象的主要功能

    • 获取Servlet名称:getServletName()

    • 获取全局上下文ServletContext对象:getServletContext()

    • 获取Servlet初始化参数:getInitParameter(String) / getInitParameterNames()。

      • 使用如下:前提是要在web.xml中配置了初始化参数

      通过String info = config.getInitParameter("url");的方式获取value值
      

练习:

  • 在web.xml文件中,配置初始化参数。
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
        <servlet>
            <!-- 这是Servlet的别名,一个名字对应一个Servlet。相当于变量名 -->
            <servlet-name>MyFirstServlet</servlet-name>
            <!-- Servlet的全类名,服务器会根据全类名找到这个Servlet -->
            <servlet-class>com.demo1.MyFirstServlet</servlet-class>
            <!--创建初始化参数-->
            <init-param>
                <param-name>url</param-name>
                <param-value>jdbc:mysql://localhost:3306/databasename</param-value>
            </init-param>
            <!--表示在启动服务时创建Servlet对象,即启动服务时就调用构造方法和init()方法-->
            <load-on-startup>1</load-on-startup>
        </servlet>
    
        <!-- 建立Servlet的请求映射信息 -->
        <servlet-mapping>
            <!-- Servlet的别名,说明这个Servlet将会响应下面url-pattern的请求 -->
            <servlet-name>MyFirstServlet</servlet-name>
            <!-- Servlet响应的请求路径。如果访问这个路径,这个Servlet就会响应 -->
            <url-pattern>/MyFirstServlet</url-pattern>
        </servlet-mapping>
    </web-app>
    
  • 编写Servlet实现类
    package com.demo1;
    
    import javax.servlet.*;
    import java.io.IOException;
    
    public class MyFirstServlet implements Servlet 
        private ServletConfig servletConfig;
        public MyFirstServlet() 
            System.out.println("调用构造器");
        
    
        @Override
        public void init(ServletConfig servletConfig) throws ServletException 
            this.servletConfig = servletConfig;
        
    
        @Override
        public ServletConfig getServletConfig() 
            return null;
        
    
        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException 
            // 1.获取Servlet名字
            String servletName = this.servletConfig.getServletName();
            System.out.println(servletName);
            // 2.获取ServletContext对象
            ServletContext servletContext = this.servletConfig.getServletContext();
            System.out.println(servletContext);
            // 3.获取初始化参数
            String url = this.servletConfig.getInitParameter("url");
            System.out.println(url);
        
    
        @Override
        public String getServletInfo() 
            return null;
        
    
        @Override
        public void destroy() 
            System.out.println("调用destroy");
        
    
    
  • 测试一下:

5.2 ServletContext接口

  • Web容器在启动时,它会为每个Web应用程序都创建一个唯一对应的ServletContext对象,意思是Servlet上下文,代表当前Web应用。

  • 由于一个Web应用程序中的所有Servlet都共享同一个ServletContext对象,所以ServletContext对象也被称为 application 对象(Web应用程序对象)。

  • 对象由Servlet容器在项目启动时创建,通过ServletConfig对象的getServletContext()方法获取。在项目卸载时销毁。

  • ServletContext对象的主要功能

    ① 获取项目的上下文路径(带/的项目名): getContextPath()

    @Override
    public void init(ServletConfig config) throws ServletException 
    	ServletContext application = config.getServletContext();
    	System.out.println("全局上下文对象:"+application);
    	String path = application.getContextPath();
    	System.out.println("全局上下文路径:"+path);// /06_Web_Servlet
    
    

    ② 获取虚拟路径所映射的本地真实路径:getRealPath(String path)

    • 虚拟路径:浏览器访问Web应用中资源时所使用的路径。

    • 本地路径:资源在文件系统中的实际保存路径。

    • 作用:将用户上传的文件通过流写入到服务器硬盘中。

      @Override
      public void init(ServletConfig config) throws ServletException 
      	//1.获取ServletContext对象
      	ServletContext context = config.getServletContext();
      	//2.获取index.html的本地路径
      	//index.html的虚拟路径是“/index.html”,其中“/”表示当前Web应用的根目录,
      	//即WebContent目录
      	String realPath = context.getRealPath("/index.html");
      	//realPath=D:\\DevWorkSpace\\MyWorkSpace\\.metadata\\.plugins\\
      	//org.eclipse.wst.server.core\\tmp0\\wtpwebapps\\MyServlet\\index.html
      	System.out.println("realPath="+realPath);
      
      
      

    ③ 获取WEB应用程序的全局初始化参数(基本不用)

    • 该初始化参数是全局的,所有Servlet对象都可以使用

    • 设置Web应用初始化参数的方式是在web.xml的根标签下加入如下代码

      <web-app>
      	<!-- Web应用初始化参数 -->
      	<context-param>
      		<param-name>ParamName</param-name>
      		<param-value>ParamValue</param-value>
      	</context-param>
      </web-app>
      
    • 获取Web应用初始化参数

      @Override
      public void init(ServletConfig config) throws ServletException 
      	//1.获取ServletContext对象
      	ServletContext application = config.getServletContext();
      	//2.获取Web应用初始化参数
      	String paramValue = application.getInitParameter("ParamName");
      	System.out.println("全局初始化参数paramValue="+paramValue);
      
      

    ④ 作为域对象共享数据

    • 作为最大的域对象在整个项目的不同web资源内共享数据。

其中,

  • setAttribute(key,value):以后可以在任意位置取出并使用
  • getAttribute(key):取出设置的value值

第6章 Servlet技术体系

6.1 Servlet接口

6.2 Servlet接口的常用实现类

  • 为什么要扩展Servlet接口?

    • 实现Servlet接口的实现类中方法冗余【主要需要service()即可】
    • 不会提示在web.xml中注册servlet
  • 实现类体系

    • GenericServlet实现Servlet接口
    • HttpServlet继承GenericServlet
  • 创建Servlet的最终方式

    • 继承HttpServlet

6.2.1 GenericServlet抽象类

  • GenericServlet对Servlet功能进行了封装和完善,重写了init(ServletConfig config)方法,用来获取ServletConfig对象。此时如果GenericServlet的子类(通常是自定义Servlet)又重写了init(ServletConfig config)方法有可能导致ServletConfig对象获取不到,所以子类不应该重写带参数的这个init()方法。
  • 如果想要进行初始化操作,可以重写GenericServlet提供的无参的init()方法,这样就不会影响ServletConfig对象的获取。
  • 将service(ServletRequest req,ServletResponse res)保留为抽象方法,让使用者仅关心业务实现即可。

6.2.2 HttpServlet抽象类

  • 专门用来处理Http请求的Servlet。

  • 对GenericServlet进行进一步的封装和扩展,在service(ServletRequest req, ServletResponse res)方法中,将ServletRequest和ServletResponse转换为HttpServletRequest和HttpServletResponse,根据不同HTTP请求类型调用专门的方法进行处理。

  • 今后在实际使用中继承HttpServlet抽象类创建自己的Servlet实现类即可。重写doGet(HttpServletRequest req, HttpServletResponse resp)和doPost(HttpServletRequest req, HttpServletResponse resp)方法实现请求处理,不再需要重写service(ServletRequest req, ServletResponse res)方法了。

  • 又因为我们业务中get,post的处理方式又都是一样的,所以我们只需要写一种方法即可,使用另外一种方法调用我们写好的doXXX方法。web.xml配置与之前相同。

    //处理浏览器的get请求
    doGet(HttpServletRequest request, HttpServletResponse response)
    	//业务代码
    
    //处理浏览器的post请求
    doPost(HttpServletRequest request, HttpServletResponse response)
        doGet(request, response);
    
    

6.2.3 HttpServlet源码分析

导入源码


源码分析
  • HttpServlet继承了GenricServlet类,而GenricServlet类实现了Servlet接口

  • GenricServlet类的主要作用:

    • 提供了获取ServletConfig和ServletContext对象的公共方法
      	@Override
          public ServletConfig getServletConfig() 
              return config;
          
          
          @Override
          public ServletContext getServletContext() 
              return getServletConfig().getServletContext();
          
      
    • 将service()方法抽象化
      @Override
          public abstract void service(ServletRequest req, ServletResponse res)
                  throws ServletException, IOException;
      
  • HttpServlet类的作用: