zoukankan      html  css  js  c++  java
  • 《Head First Servlets & JSP》-5-属性和监听

    Servlet初始化参数

    • 在DD文件(web.xml)中
      Servlet参数在/参数下:
    • 在Servlet代码中
    • 在Servlet初始化之前不能使用Servlet初始化参数
      一旦有了一个ServletConfig引用,就可以调用getInitParameter()方法,不过 不能从构造函数调用这个方法!因为容器只调用构造函数还未调用init()之前,它还不算一个完整的Servlet(薛定谔Servlet)。

    Servlet初始化参数只能赌一次——就是在容器初始化Servlet的时候

    容器建立一个Servlet时,会读DD,并为ServletConfig创建名/值对。容器不会再读初始化参数了,除非重新部署Servlet。

    Tomcat包括一个管理工具,可以部署、取消部署、重新部署整个Web应用而不必重启Tomcat。
    若初始化参数的值经常变化,最好让Servlet方法从一个文件或数据库得到值;不过这也意味着每次Servlet代码运行时都会有更多的开销,而不是只在初始化期间有开销。

    上下文初始化参数

    上下文初始化参数与Servlet初始化参数很类似,不过上下文参数对整个Web应用而不只是一个Servlet可用。
    意味只需在DD一个地方制定参数,所有Servlet和JSP都自动地能访问上下文参数。

    • 在DD文件中
      上下文参数在节点下:
    • 在Servlet代码中:

    上下文初始化参数和Servlet初始化参数对比


    • 每个Servlet一个ServletConfig;每个Web应用一个ServletContext

      如果应用是分布的,那么每个JVM有一个ServletContext

    ServletContextListerner监听器

    • 为什么
      若想Web应有的所有部分都能访问一个共享的数据连接,怎么办?
      首先,把DataSource查找名放在一个上下文初始化参数,没问题;
      其次,把这个String参数转化为一个具体的DataSource谁来做,servlet?不可以!
      因为,如何保证这个servlet最先运行?那么用这个新的事物——监听器。

    • 怎么做
      需要一个单独的对象,它可以:

    1. 上下文初始化时得到通知
      包括:
      从ServletContext得到上下文初始化参数;
      使用初始化参数查找名建立一个数据库连接;
      把数据库连接存储为一个属性,是的Web应用的各个部分都能访问;
    2. 上下文撤销时得到通知
      包括:
      关闭数据库连接;

    建立和使用一个上下文监听器

    以下要做的是把一个对象Dog放在ServletContext中:

    • 创建一个监听者类

      下面是一个DataSource的替代者:Dog
    • 在web.xml DD放一个元素
      根节点下:
    • 编写Servlet类

    8个监听者


    HttpSessionBindingListener

    普通HttpSessionAttributeListener类只想知道会话合适增加、删除或替换了某种类型的属性;
    HttpSessionBindingListener使得属性本身知道它何时增加到一个会话中,或者合适从会话中删除;

    什么是属性

    属性就是一个对象,设置(也称绑定)到另外3个servlet API对象中——ServletContext、HttpServletRequest或HttpSession。
    可以把它简单认为是一个映射实例对象中的名/值对(名是一个String,值是一个Object)。
    实际中,我们只关心属性所在的作用域,即谁能使用这个属性,以及属性能存活多久。
    属性不是参数

    名称 属性 参数
    设置方法 setAttribute(String name,Object value) 不能设置应用和servlet的参数,它们都在DD中设置
    返回类型 Object String
    获取方法 getAttribute(String name),注意必须强制类型转换,因为返回Object getInitParameter(String name)

    三个作用域

    • 上下文
      应用中每一部分都能访问该属性
    • 请求
      能访问特定HttpSession的部分才能访问
    • 会话
      能访问特定ServletRequest的部分才能访问

    上下文作用域的线程安全性

    • 上下文作用域不是线程安全的
      因为应用的每一部分都能访问上下文属性,若有多个servlet,即可能有多个线程,这些请求是并发处理的,每个请求在一个单独的线程中处理。
    • 同步上下文
      同步服务方法(如doGet)不能保护上下文属性。原因很简单,同步服务方法意味着servlet中一次只能运行一个线程,但是这并不能阻止其他servlet或JSP访问这个属性!正确的做法是对上下文加锁,而不是对servlet加锁
    • 怎么做

    会话属性的线程安全性

    • 会话属性不是线程安全的
      如用户可能打开一个新的浏览器窗口,容器把来自第二个窗口的请求看作是来自同一个会话。
    • 同步HttpSession
      因此,要会话属性线程安全,则必须像对同步上下文属性一样,要同步HttpSession!
    • 怎么做

    请求属性和局部变量——线程安全的!

    注意,实例变量不是线程安全的,因为多个用户请求一个servlet时,意味多个线程在运行该servlet代码,而且所有线程都能访问servlet的实例变量,因此实例变量不是线程安全的。

    请求属性和请求分派

    • 每次请求数据的处理
      MVC应用从一个servlet控制器开始,但最后以一个JSP视图结束。那么控制器与模型通信得到的视图建立响应所需要的数据放在哪?
      这些数据不应该放在上下文或会话属性中,因为它只针对这个请求,所以应该放在请求作用域中。
      那么,其他组件如何接管这个请求呢——RequestDispatcher。
    • 实现
    • 如何得到RequestDispatcher
      有两种方法得到RequestDispatcher:从请求得到,或者从上下文得到。
      无论哪一种,都必须告诉它要把请求转发给哪个Web组件,即告知接管请求的servlet或JSP。
      从ServletRequest得到RequestDispatcher:
      RequestDispatcher view=request.getRequestDispatcher("result.jsp");
      从ServletContext得到RequestDispatcher:
      RequestDispatcher view=getServletContext().getRequestDispatcher("/result.jsp");
      注意不能指定相对路径,即必须以斜线开头。
      在RequestDispatcher上调用forward():
      view.forward(request,response);
      RequestDispatcher提交了请求(forward())后,不能再转发请求,否则会有IlegalStateException.
      ,就是错误的例子。

    注意名词:

    • Servlet初始化参数
    • 上下文初始化参数
  • 相关阅读:
    php面向对象三大特性
    php面向对象的重写与重载
    一组成对的数字,找出不成对的数字
    如何创建dll以及使用
    常见运行时错误
    连续数的和
    绕圆圈取球
    第一章 概述
    错误2038
    一个简单的环境光shader
  • 原文地址:https://www.cnblogs.com/myitroad/p/6192521.html
Copyright © 2011-2022 走看看