为了账号安全,请及时绑定邮箱和手机立即绑定

JavaWeb基础(五)-Servlet详解

标签:
Java

这篇文章, 我主要分享JavaWeb动态网页开发.要谈JavaWeb动态网页开发.我们就要来了解Servlet, 所以我会按如下进行分享

  • Servlet的规范

  • Servlet的请求流程

  • Servlet初始化参数

  • Servlet继承体系的设计原因

  • Servlet请求和响应
    主要围绕Servlet的原理Servlet的应用两条主线来分享.
    Servlet的原理: 包含Servlet的规范Servlet的基本请求流程Servlet继承体系的设计原因
    Servlet的应用: 包含Servlet初始化参数Servlet请求和响应

1.什么是Servlet规范

Servlet是一套规范, 所谓的规范就是做了约束.

  • 是一个规范.Servlet是一个规范,所谓的规范就是Servlet约束了一些东西, 主要约束了容器、约束了项目目录结构约束了我们的代码.

  • 是一个组件. Servlet也可以看成是一个组件, 因为一个遵循Servlet规范的程序可以跑在实现Servlet规范的容器中。

webp

Servlet的规范

2.如何编写一个最简单的Servlet的步骤

  • 创建一个HelloServlet类继承自HttpServlet.。

  • 复写其service方法, 在其中编写业务逻辑处理请求。

  • 配置web.xml. 增加xml中的servlet对象和servlet-mapping对象.其中servlet对象用来关联我们的类,并给这个类一个别名。servlet-mapping对象用来映射servlet和和访问的资源名。这样才来告诉tomcat容器, 一旦请求来了, 该根据资源名去找哪个servlet做处理。

3.如何研究Servlet对象的生命周期

Servlet对象生命周期依赖于容器, 因为Servlet规范已经约定了Servlet对象必须放在实现Servlet规范的容器中运行, 换区话说Servlet对象从出生到死亡都由容器调度。所以容器负责Servlet的创建、初始化、运行、释放.

要了解Servlet具体的生命周期, 我们先介绍以下上个方法.这三个方法是Servlet的生命周期方法.

生命周期方法

  • init(ServletConfig); 负责初始化Servlet.

  • service(ServletRequest, ServletResponse); 负责处理请求.

  • destory(); 负责释放Servlet.

观察Servlet的生命周期

我们可以创建一个HelloServlet如下, 并且给它提供一个无参构造方法, 分别在上面上个生命周期方法中做打印, 来研究其调用顺序.

创建HelloServlet, 继承自HttpServlet.复写生命周期方法

package com.sweetcs.web.servlet;import java.io.IOException;import javax.servlet.ServletConfig;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;public class HelloServlet extends HttpServlet{    
    public HelloServlet() {        // TODO Auto-generated constructor stub
        System.out.println("Servlet构造方法");
    }    
    @Override
    public void init(ServletConfig config) throws ServletException {        // TODO Auto-generated method stub
        super.init(config);
        
        System.out.println("Servlet init");
    }    
    
    @Override
    protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
        System.out.println("Servlet service");
    }    
    @Override
    public void destroy() {        // TODO Auto-generated method stub
        super.destroy();
        System.out.println("Servlet destroy");
    }   
}

web.xml中配置资源名的要交个哪个servlet处理

<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://java.sun.com/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                      http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
  version="3.0"
  metadata-complete="true">
  <display-name>Welcome to Tomcat</display-name>
  <description>
     Welcome to Tomcat  </description>


    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.sweetcs.web.servlet.HelloServlet</servlet-class>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
  </web-app>

第一次访问http://127.0.0.1:8080/hello打印输出

webp

第一次访问

第二、三次访问http://127.0.0.1:8080/hello打印输出

webp

第二、三次访问


通过上述观察可以发现,第一次访问是依次调用了构造方法init方法service方法.但是什么时候Servlet对象的destory方法才会调用呢?我们进行以下两种方式验证。

  • 第一种停止tomcat的运行, 点击带有叉号的猫

webp

点击带有叉号的猫

输出如下,说明调用了destory方法, Servlet被正确的释放掉.

webp

打印出destory

  • 第二种直接终止程序.

webp

点击小红点终止程序

输出如下, 说明Servlet对象的destory方法没有被容器调用, 也就是说Servlet没有被正确的释放掉.

webp

根据上述实验验证,我们可以得出以下结论

总结

  • Servlet的生命周期是先由容器创建Servlet对象, 所以会调用其构造方法.然后再调用init方法进行初始化, 最后调用service方法处理请求.

  • 由次可以见Servlet只在第一次访问时候创建.创建完后容器就调用了servlet的init方法.

  • Servlet对象在整个容器中只有一份,属于单例.因为多次的相同url的请求过来, 都没有再调用构造方法, 显然没有在创建新的Sevlet对象.

  • Servlet必须提供无参数构造器.由于Sevlet对象不是我们手动创建的, 而是交给容器负责。在这里我们使用的是tomcat容器.而tomcat容器是使用反射技术Class clazz = Class.forName();clazz.newInstance()创建Servlet对象.所以我们必须提供无参构造器.当然Java中如果你不提供构造器, 默认就会存在一个无参构造器。

  • 要正确的让Servlet得到释放, 必须得停止tomcat容器.如果是程序异常中断, Servlet并不能得到释放.

4.Servlet请求流程

我们了解了Servlet的规范、Servlet的生命周期、接着我们研究下我们从浏览器通过http协议请求相应的资源的时候。服务器端的Servlet从接受到请求的到响应的流程.

  • 1.当tomcat服务器接受到浏览器的请求时, 会进行URL的解析.将URL分解出ContextPathResourceName.即上下文路径资源名称.

  • 2.解析完成后, tomcat会去读取其conf/server.xml中的所有Context对象.(我把Context元素叫对象)

  • 3.然后根据ContextPath的值和Context对象path属性进行比较, 找到对应的Context对象。
    如果没有找到对应的Context对象就报404 Not Found.
    如果有找到对应的Context对象则进入第4步.(如下是一个Context元素<Context docBase='xxx' path='contextPath' />)

  • 4.读取Context对象的docBase属性值,即为项目的部署路径所在地址.tomcat会根据该地址取读取其下的WEB-INF/web.xml配置文件.

  • 5.解析web.xml中的所有Servlet-Mapping对象, 并用ResouceName和Servlet-Mapping对象的url-pattern比较.如果知道到匹配的进入第6步, 否者也是报404 Not Found.

  • 6.根据找到的Servlet-Mapping对象的servlet-name继续找到Servlet对象对应的全限定类名.

  • 7.尝试去 Servlet缓存池获取对应的Servlet对象.根据全限定类名取对应的Servlet对象.如果取到, 则直接调用其service方法(传入已经创建好的request和reponse对象)

  • 8.如果Servlet缓存池中没有对应的对象, 则使用反射技术, 加载解析出来的全限定类名.并调用其newInstance()方法创建Servlet对象.

  • 9.创建ServletConfig对象, 该对象即代表web.xml.调用Servlet对象的init方法.servlet.init(config)


  1. 调用Servlet对象的service方法处理请求, 相应数据. servlet.service(request, response)


  1. 如果有重复的请求进来, 则进入第7步.

注意

  • server.xml文件配置了contextPath.web.xml配置了资源名称.

  • server.xml文件让tomcat根据contextPath去找到对应的根目录地址.web.xml文件根据tomcat根据资源名称知道对应的Servlet类,再通过反射技术创建Sevlet对象.

5.Servlet初始化参数

了解完Servlet的请求流程, 我们也就明白了底层是如何创建Servlet对象, 同时知道了配置文件的作用。接着我们就顺着该流程的第一个步骤, 创建并初始化Servlet对象, 想来了解下Servlet的初始化参数.

5.1 init(config)

什么是初始化参数, 即Servlet在创建后, 我们可能会需要它附带一些属性, 并且我们用配置好的参数来初始化这些Servlet.这些参数都是配置在web.xml<Servlet元素>中.
如下我们给HelloServlet配置初始化参数, 并读取出来查看.

web.xml配置, 在servlet元素中添加init-param元素

    <servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.sweetcs.web.servlet.HelloServlet</servlet-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
    </servlet>

Java代码

public class HelloServlet extends HttpServlet{    
    private ServletConfig config;    
    public HelloServlet() {        // TODO Auto-generated constructor stub
        System.out.println("Servlet构造方法");
    }    
    @Override
    public void init(ServletConfig config) throws ServletException {        // TODO Auto-generated method stub
        super.init(config);        this.config = config;
        System.out.println("Servlet init");
    }    
    
    @Override
    protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException {
        System.out.println("Servlet service");
        
        String encoding = config.getInitParameter("encoding");
        System.out.println(encoding);
        
    }    
    @Override
    public void destroy() {        // TODO Auto-generated method stub
        super.destroy();
        System.out.println("Servlet destroy");
    }   
}

启动tomcat, 并浏览器输入http://127.0.0.1:8080/hello.打印如下,可以正确的将配置参数读取出来.

Servlet构造方法
Servlet init
Servlet service
UTF-8



作者:sixleaves
链接:https://www.jianshu.com/p/6d7fcf8120cc


点击查看更多内容
6人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消