• cookie和session


    一、cookie机制和session机制的区别
    *************************************************************************************
    具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。
    同时我们也看到,由于才服务器端保持状态的方案在客户端也需要保存一个标识,所以session
    机制可能需要借助于cookie机制来达到保存标识的目的,但实际上还有其他选择
    *************************************************************************************

    二、会话cookie和持久cookie的区别
    *************************************************************************************
    如果不设置过期时间,则表示这个cookie生命周期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种生命期为浏览会话期的cookie被称为会话cookie。会话cookie一般不保存在硬盘上而是保存在内存里。
      如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie依然有效直到超过设定的过期时间。
      存储在硬盘上的cookie可以在不同的浏览器进程间共享,比如两个IE窗口。而对于保存在内存的cookie,不同的浏览器有不同的处理方式。
    *************************************************************************************

    三、如何利用实现自动登录
    *************************************************************************************
      当用户在某个网站注册后,就会收到一个惟一用户ID的cookie。客户后来重新连接时,这个
    用户ID会自动返回,服务器对它进行检查,确定它是否为注册用户且选择了自动登录,从而使用户务需给出明确的用户名和密码,就可以访问服务器上的资源。
    *************************************************************************************

    四、如何根据用户的爱好定制站点
    *************************************************************************************
      网站可以使用cookie记录用户的意愿。对于简单的设置,网站可以直接将页面的设置存储在cookie中完成定制。然而对于更复杂的定制,网站只需仅将一个惟一的标识符发送给用户,由服务器端的数据库存储每个标识符对应的页面设置。
    *************************************************************************************

    五、cookie的发送
    *************************************************************************************
    1.创建Cookie对象
    2.设置最大时效
    3.将Cookie放入到HTTP响应报头
    如果你创建了一个cookie,并将他发送到浏览器,默认情况下它是一个会话级别的cookie:存储在浏览器的内存中,用户退出浏览器之后被删除。如果你希望浏览器将该cookie存储在磁盘上,则
    需要使用maxAge,并给出一个以秒为单位的时间。将最大时效设为0则是命令浏览器删除该cookie。
    发送cookie需要使用HttpServletResponse的addCookie方法,将cookie插入到一个Set-Cookie HTTP请求报头中。由于这个方法并不修改任何之前指定的Set-Cookie报头,而是创建新的报头,因此我们将这个方法称为是addCookie,而非setCookie。同样要记住响应报头必须在任何文档内容发送到客户端之前设置。

    六、cookie的读取
    *************************************************************************************
    1.调用request.getCookie
    要获取有浏览器发送来的cookie,需要调用HttpServletRequest的getCookies方法,这个调用返回Cookie对象的数组,对应由HTTP请求中Cookie报头输入的值。
    2.对数组进行循环,调用每个cookie的getName方法,直到找到感兴趣的cookie为止
     cookie与你的主机(域)相关,而非你的servlet或JSP页面。因而,尽管你的servlet可能只发送了单个cookie,你也可能会得到许多不相关的cookie。
    例如:
      String cookieName = “userID”;
        Cookie cookies[] = request.getCookies();
        if (cookies!=null){
            for(int i=0;i<cookies.length;i++){
        Cookie cookie = cookies[I;
        if (cookieName.equals(cookie.getName())){
            doSomethingWith(cookie.getValue());
    }
    }
    }
    *************************************************************************************

    七、如何使用cookie检测初访者
    *************************************************************************************
    A.调用HttpServletRequest.getCookies()获取Cookie数组
    B.在循环中检索指定名字的cookie是否存在以及对应的值是否正确
    C.如果是则退出循环并设置区别标识
    D.根据区别标识判断用户是否为初访者从而进行不同的操作
    *************************************************************************************

    八、使用cookie检测初访者的常见错误
    *************************************************************************************
    不能仅仅因为cookie数组中不存在在特定的数据项就认为用户是个初访者。如果cookie数组为null,客户可能是一个初访者,也可能是由于用户将cookie删除或禁用造成的结果。
    但是,如果数组非null,也不过是显示客户曾经到过你的网站或域,并不能说明他们曾经访问过你的servlet。其它servlet、JSP页面以及非Java Web应用都可以设置cookie,依据路径的设置,其中的任何cookie都有可能返回给用户的浏览器。
    正确的做法是判断cookie数组是否为空且是否存在指定的Cookie对象且值正确。
    *************************************************************************************

    九、使用cookie属性的注意问题
    *************************************************************************************
      属性是从服务器发送到浏览器的报头的一部分;但它们不属于由浏览器返回给服务器的报头。 
      因此除了名称和值之外,cookie属性只适用于从服务器输出到客户端的cookie;服务器端来自于浏览器的cookie并没有设置这些属性。 
      因而不要期望通过request.getCookies得到的cookie中可以使用这个属性。这意味着,你不能仅仅通过设置cookie的最大时效,发出它,在随后的输入数组中查找适当的cookie,读取它的值,修改它并将它存回Cookie,从而实现不断改变的cookie值。
    *************************************************************************************

    十、如何使用cookie记录各个用户的访问计数
    *************************************************************************************
    1.获取cookie数组中专门用于统计用户访问次数的cookie的值
    2.将值转换成int型
    3.将值加1并用原来的名称重新创建一个Cookie对象
    4.重新设置最大时效
    5.将新的cookie输出
    *************************************************************************************

    十一、session在不同环境下的不同含义
    *************************************************************************************
    session,中文经常翻译为会话,其本来的含义是指有始有终的一系列动作/消息,比如打电话是从拿起电话拨号到挂断电话这中间的一系列过程可以称之为一个session。
    然而当session一词与网络协议相关联时,它又往往隐含了“面向连接”和/或“保持状态”这样两个含义。
      session在Web开发环境下的语义又有了新的扩展,它的含义是指一类用来在客户端与服务器端之间保持状态的解决方案。有时候Session也用来指这种解决方案的存储结构。
    *************************************************************************************

    十二、session的机制
    *************************************************************************************
      session机制是一种服务器端的机制,服务器使用一种类似于散列表的结构(也可能就是使用散列表)来保存信息。
    但程序需要为某个客户端的请求创建一个session的时候,服务器首先检查这个客户端的请求里是否包含了一个session标识-称为session id,如果已经包含一个session id则说明以前已经为此客户创建过session,服务器就按照session id把这个session检索出来使用(如果检索不到,可能会新建一个,这种情况可能出现在服务端已经删除了该用户对应的session对象,但用户人为地在请求的URL后面附加上一个JSESSION的参数)。
    如果客户请求不包含session id,则为此客户创建一个session并且生成一个与此session相关联的session id,这个session id将在本次响应中返回给客户端保存。
    *************************************************************************************

    十三、保存session id的几种方式
    *************************************************************************************
    A.保存session id的方式可以采用cookie,这样在交互过程中浏览器可以自动的按照规则把这个标识发送给服务器。
    B.由于cookie可以被人为的禁止,必须有其它的机制以便在cookie被禁止时仍然能够把session id传递回服务器,经常采用的一种技术叫做URL重写,就是把session id附加在URL路径的后面,附加的方式也有两种,一种是作为URL路径的附加信息,另一种是作为查询字符串附加在URL后面。网络在整个交互过程中始终保持状态,就必须在每个客户端可能请求的路径后面都包含这个session id。
    C.另一种技术叫做表单隐藏字段。就是服务器会自动修改表单,添加一个隐藏字段,以便在表单提交时能够把session id传递回服务器。
    *************************************************************************************

    十四、session什么时候被创建
    *************************************************************************************
    一个常见的错误是以为session在有客户端访问时就被创建,然而事实是直到某server端程序(如Servlet)调用HttpServletRequest.getSession(true)这样的语句时才会被创建。
    *************************************************************************************

    十五、session何时被删除
    *************************************************************************************
    session在下列情况下被删除:
    A.程序调用HttpSession.invalidate()
    B.距离上一次收到客户端发送的session id时间间隔超过了session的最大有效时间
    C.服务器进程被停止

    再次注意关闭浏览器只会使存储在客户端浏览器内存中的session cookie失效,不会使服务器端的session对象失效。
    *************************************************************************************

    十六、URL重写有什么缺点
    *************************************************************************************
       对所有的URL使用URL重写,包括超链接,form的action,和重定向的URL。每个引用你的站点的URL,以及那些返回给用户的URL(即使通过间接手段,比如服务器重定向中的Location字段)都要添加额外的信息。
       这意味着在你的站点上不能有任何静态的HTML页面(至少静态页面中不能有任何链接到站点动态页面的链接)。因此,每个页面都必须使用servlet或JSP动态生成。即使所有的页面都动态生成,如果用户离开了会话并通过书签或链接再次回来,会话的信息都会丢失,因为存储下来的链接含有错误的标识信息-该URL后面的SESSION ID已经过期了。  
    *************************************************************************************

    十七、使用隐藏的表单域有什么缺点
    *************************************************************************************
        仅当每个页面都是有表单提交而动态生成时,才能使用这种方法。单击常规的<A HREF..>超文本链接并不产生表单提交,因此隐藏的表单域不能支持通常的会话跟踪,只能用于一系列特定的操作中,比如在线商店的结账过程
    *************************************************************************************

    十八、会话跟踪的基本步骤
    *************************************************************************************
    1.访问与当前请求相关的会话对象
    2.查找与会话相关的信息
    3.存储会话信息
    4.废弃会话数据
    *************************************************************************************

    十九、getSession()/getSession(true)、getSession(false)的区别
    *************************************************************************************
    getSession()/getSession(true):当session存在时返回该session,否则新建一个session并返回该对象
    getSession(false):当session存在时返回该session,否则不会新建session,返回null
    *************************************************************************************

    二十、如何将信息于会话关联起来
    *************************************************************************************
      setAttribute会替换任何之前设定的值;如果想要在不提供任何代替的情况下移除某个值,则应使用removeAttribute。这个方法会触发所有实现了HttpSessionBindingListener接口的值的valueUnbound
    方法。
    *************************************************************************************

    二十一、会话属性的类型有什么限制吗
    *************************************************************************************
    通常会话属性的类型只要是Object就可以了。除了null或基本类型,如int,double,boolean。
    如果要使用基本类型的值作为属性,必须将其转换为相应的封装类对象
    *************************************************************************************

    二十二、如何废弃会话数据
    *************************************************************************************
    A.只移除自己编写的servlet创建的数据:
       调用removeAttribute(“key”)将指定键关联的值废弃
    B.删除整个会话(在当前Web应用中):
       调用invalidate,将整个会话废弃掉。这样做会丢失该用户的所有会话数据,而非仅仅由我们
    servlet或JSP页面创建的会话数据
    C.将用户从系统中注销并删除所有属于他(或她)的会话
       调用logOut,将客户从Web服务器中注销,同时废弃所有与该用户相关联的会话(每个Web应用至多一个)。这个操作有可能影响到服务器上多个不同的Web应用
    *************************************************************************************

    二十三、使用isNew来判断用户是否为新旧用户的错误做法
    *************************************************************************************
    public boolean isNew()方法如果会话尚未和客户程序(浏览器)发生任何联系,则这个方法返回true,这一般是因为会话是新建的,不是由输入的客户请求所引起的。
    但如果isNew返回false,只不过是说明他之前曾经访问该Web应用,并不代表他们曾访问过我们的servlet或JSP页面。
    因为session是与用户相关的,在用户之前访问的每一个页面都有可能创建了会话。因此isNew为false只能说用户之前访问过该Web应用,session可以是当前页面创建,也可能是由用户之前访问过的页面创建的。
    正确的做法是判断某个session中是否存在某个特定的key且其value是否正确
    *************************************************************************************

    二十四、Cookie的过期和Session的超时有什么区别
    *************************************************************************************
    会话的超时由服务器来维护,它不同于Cookie的失效日期。首先,会话一般基于驻留内存的cookie
    不是持续性的cookie,因而也就没有截至日期。即使截取到JSESSIONID cookie,并为它设定一个失效日期发送出去。浏览器会话和服务器会话也会截然不同。
    *************************************************************************************

    二十五、session cookie和session对象的生命周期是一样的吗
    *************************************************************************************
    当用户关闭了浏览器虽然session cookie已经消失,但session对象仍然保存在服务器端
    *************************************************************************************

    二十六、是否只要关闭浏览器,session就消失了
    *************************************************************************************
    程序一般都是在用户做log off的时候发个指令去删除session,然而浏览器从来不会主动在关闭之前通知服务器它将要被关闭,因此服务器根本不会有机会知道浏览器已经关闭。服务器会一直保留这个会话对象直到它处于非活动状态超过设定的间隔为止。
    之所以会有这种错误的认识,是因为大部分session机制都使用会话cookie来保存session id,而关闭浏览器后这个session id就消失了,再次连接到服务器时也就无法找到原来的session。
    如果服务器设置的cookie被保存到硬盘上,或者使用某种手段改写浏览器发出的HTTP请求报头,把原来的session id发送到服务器,则再次打开浏览器仍然能够找到原来的session。
    恰恰是由于关闭浏览器不会导致session被删除,迫使服务器为session设置了一个失效时间,当距离客户上一次使用session的时间超过了这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间。
      由此我们可以得出如下结论:
      关闭浏览器,只会是浏览器端内存里的session cookie消失,但不会使保存在服务器端的session对象消失,同样也不会使已经保存到硬盘上的持久化cookie消失。
    *************************************************************************************


    二十七、打开两个浏览器窗口访问应用程序会使用同一个session还是不同的session
    *************************************************************************************
    通常session cookie是不能跨窗口使用的,当你新开了一个浏览器窗口进入相同页面时,系统会赋予你一个新的session id,这样我们信息共享的目的就达不到了。
    此时我们可以先把session id保存在persistent cookie中(通过设置session的最大有效时间),然后在新窗口中读出来,就可以得到上一个窗口的session id了,这样通过session cookie和persistent cookie的结合我们就可以实现了跨窗口的会话跟踪。
    *************************************************************************************

    二十八、如何使用会话显示每个客户的访问次数
    *************************************************************************************
    由于客户的访问次数是一个整型的变量,但session的属性类型中不能使用int,double,boolean等基本类型的变量,所以我们要用到这些基本类型的封装类型对象作为session对象中属性的值
      但像Integer是一种不可修改(Immutable)的数据结构:构建后就不能更改。这意味着每个请求都必须创建新的Integer对象,之后使用setAttribute来代替之前存在的老的属性的值。例如:
    HttpSession session = request.getSession();
    SomeImmutalbeClass value = (SomeImmutableClass)session.getAttribute(“SomeIdentifier”);
    if (value= =null){
        value = new SomeImmutableClass(…); // 新创建一个不可更改对象
    }else{
        value = new SomeImmutableClass(calculatedFrom(value)); // 对value重新计算后创建新的对象
    }
    session.setAttribute(“someIdentifier”,value); // 使用新创建的对象覆盖原来的老的对象
    *************************************************************************************

    二十九、如何使用会话累计用户的数据
    *************************************************************************************
    使用可变的数据结构,比如数组、List、Map或含有可写字段的应用程序专有的数据结构。通过这种方式,除非首次分配对象,否则不需要调用setAttribute。例如

    HttpSession session = request.getSession();
    SomeMutableClass value = (SomeMutableClass)session.getAttribute(“someIdentifier”);
    if(value = = null){
        value = new SomeMutableClass(…);
        session.setAttribute(“someIdentifier”,value);
    }else{
        value.updateInternalAttribute(…);     // 如果已经存在该对象则更新其属性而不需重新设置属性
    }
    *************************************************************************************

    三十、不可更改对象和可更改对象在会话数据更新时的不同处理
    *************************************************************************************
    不可更改对象因为一旦创建之后就不能更改,所以每次要修改会话中属性的值的时候,都需要
    调用setAttribute(“someIdentifier”,newValue)来代替原有的属性的值,否则属性的值不会被更新
    可更改对象因为其自身一般提供了修改自身属性的方法,所以每次要修改会话中属性的值的时
    候,只要调用该可更改对象的相关修改自身属性的方法就可以了。这意味着我们就不需要调
    用setAttribute方法了

     JavaBean学习专题[分享]

    一、JavaBean的优点:
    *************************************************************************************
    A.不需要用到Java语法
    B.对象的共享更简单
    C.请求参数与对象属性之间可以方便地对应起来
    *************************************************************************************

    二、JavaBean的特点:
    *************************************************************************************
    A.bean类必须拥有一个零参数的(默认)构造函数:JSP元素创建bean时,会调用默认的构造函数。实际的应用中经常会由servlet创建bean,JSP页面只是从中查询数据。
    B.bean类不应该有公开的实例变量(字段):要成为JSP可以访问的bean,相应的类应该使用访问器方法(access method)取代对实例变量的直接访问。
    C.持续性的值应该通过getXxx和setXxx方法来访问:尽管我们可以使用JSP script或表达式访问类的任意方法,但是,访问bean的标准JSP只能使用那些遵循getXxx/setXxx或isXxx/setXxx命名约定的方法。
    *************************************************************************************

    三、JavaBean的构建:
    *************************************************************************************
    A.<jsp:useBean id = “name”class = “package.Class”/>
    这个语句表示:实例化由Class指定的类,并将实例化后的对象绑定到_jspService中的变量,变量的名字由id指定。
    B.一定要使用完全限定类名——包括包名的类名。不管你是否使用<%@ page import…%>引入包,都要满足这个要求。
    C.jsp:useBean动作规定:仅当不存在相同id和scope的bean时才实例化新的对象
    *************************************************************************************

    四、bean类的安装:
    *************************************************************************************
    A.单个bean类的正确位置是WEB-INF/classes/subdirectoryMatchingPackageName
    B.含有bean类的JAR文件应该放在WEB-INF/lib目录中
    *************************************************************************************

    五、jsp:useBean中beanName、type选项的使用:
    *************************************************************************************
    A.beanName:即可以指向类,也可以指定包含序列化bean对象的文件
    B.type:    当希望所要声明的变量的类型是实际bean类的超类,或是bean实现的接口。应该使用type属性来控制这种声明。此时type中声明的类型是class中指明的类型的父类或者接口,即用子类的构造方法初始化一个父类对象-多态。例如:
        <jsp:useBean id = “thread1” class = “mypackage.MyClass”
    type  = “java.lang.Runnable”>
    *************************************************************************************

    六、jsp:useBean的语法规则:
    *************************************************************************************
    A.属性名大小写敏感
    B.单引号和双引号都可以使用(但必须使用其中的一种)
    C.标签的结束标记为/>,不只是>
    *************************************************************************************

    七、JavaBean属性的设置:
    *************************************************************************************
    A.<jsp:setProperty name = “beanName”property = “beanProperty”value = “beanValue”/>
    B.jsp:setProperty的value属性允许给出的值为请求期间的表达式
    *************************************************************************************

    八、将单个属性与输入参数关联:
    *************************************************************************************
    A.可以不使用value属性,而是使用param指定一个输入参数,被指定的请求参数的值字段用作bean属性的值,由String到基本类型和封装类的类型转换都自动执行。

    B.如果请求中没有指定的参数,则不采用任何动作(系统并不传递null到相关联的属性),例如:
    <jsp:setProperty name = “bean1”property = “property1”param = “property1”>

    C.如果请求参数的名称和bean属性的名称相同,还可以更进一步地简化这段代码。这种情况下可以省略param
    *************************************************************************************

    九、将所有的属性与请求参数关联:
    *************************************************************************************
    A.JSP允许将所有的属性与同名的请求参数关联起来。我们所要做的只是以”*”作为property参数的值。例如:<jsp:setProperty name = “entry”property = “*”/>

    B.系统从请求参数开始查找匹配的bean属性,而非采用相反的方式。因此,对于没有请求参数与之匹配的属性,则不采用任何动作。这种行为意味着:表单bean不必一次填充完毕,相反,一次提交可以填写bean的部分属性,另一个表单填写其他属性。以此类推。但要使用这项功能,需要将bean在多个页面中共享。
    *************************************************************************************

    十、使用属性与请求参数自动关系方式的注意点:
    *************************************************************************************
    A.输入参数缺失时不采取任何动作:系统不会提供null作为属性的值。因此在设计bean时,一般
    要为其设置可以识别的默认值,以便可以确定某个属性是否修改过

    B.自动类型转换不能像手动类型转换那样那个防止不合法的值:在使用自动类型转换时,应该考虑使错误处理页面或显示使用try/catch块来处理异常数据

    C.bean属性的名称和请求参数大小写敏感:属性名和请求参数的名字必须精确匹配
    *************************************************************************************

    十一、共享bean
    *************************************************************************************
    使用scope时,系统首先检查指定的位置是否存在指定名称的bean。仅当系统找不倒现有的bean时,才会创建新的bean.scope属性有4个可选值:page、request、session、application
    *************************************************************************************

    十二、bean的scpoe = “page”:
    *************************************************************************************
    A.这个值表示:在处理当前请求期间,除了要将bean对象绑定到局部变量外,还应该将它放在PageContext对象中。

    B.将此对象存储在此表示,servlet可以通过调用预定义变量pageContext的getAttribute方法访问它.由于每个页面和每个请求都有不同的PageContext对象,

    C.所有scope = “page”表示不共享bean,也就是针对每个请求都创建新的bean
    *************************************************************************************

    十三、bean的scope = “request”:
    *************************************************************************************
    A.这个值表示:在处理当前请求期间,除了要将bean对象绑定到局部变量外,还应该将它放在
    HttpServletRequest对象中,从而可以通过getAttribute方法访问它。

    B.在使用jsp:include、jsp:forward、RequestDispatcher的include或forward方法时,两个JSP页面,或JSP页面和servlet将会共享请求对象。而scope = “page”的bean则无法共享请求对象
    *************************************************************************************

    十四、bean的scope = “session”:
    *************************************************************************************
    A.这个值表示:除了要将bean对象绑定到局部变量之外,还要将它存储到与当前请求相关联的HttpSession对象中,我们可以使用getAttribute获取存储在HttpSession中的对象

    B.bean存储在HttpSession对象中,若该会话不失效(如超时)则bean的属性可跨请求持续
    *************************************************************************************

    十五、bean的scope = “application”:
    *************************************************************************************
    A.这个值表示:除了要将bean对象绑定到局部变量之外,还要将它存储在ServletContext中,通过预定义application变量或通过调用getServletContext获得。

    B.ServletContext由Web应用中多个servlet和JSP页面共享。ServletContext中的值可以用getAttribute方法获得。
    *************************************************************************************

    十六、根据条件构建bean:
    *************************************************************************************
    A.根据条件构建bean:<jsp:useBean…>statements</jsp:useBean>

    B.jsp:useBean的起始标签和结束标签之间的语句只在创建新的bean时执行,如果使用已有的bean,则不执行。由于jsp:useBean调用默认(零参数)构造函数,因此,我们经常需要在bean创建之后修改它的属性。为了模拟构造函数,应该在bean首次创建时执行这些修改,而不应该在访问现存(或更新后)的bean时执行。

    C.多个页面都可以在jsp:useBean的起始标签和结束标签之间包含jsp:setProperty语句;只有被第一个访问的页面才会执行这些语句。

    Tomcat中数据源的配置和使用[分享]

    一、数据源简介:
    ************************************************************************************
    在Java语言中,DataSource对象就是一个代表数据源实体的对象。一个数据源就是一个用来存储数据的工具,它可以是复杂的大型企业级数据库,也可以是简单得只有行和列的文件。数据源可以位于在服务器端,也可以位于客服端。

    应用程序通过一个连接来访问数据源,那么一个DataSource对象就是用于提供连接数据源的工具。DataSource接口提供了两个方法用于建立和数据源的连接
    使用DataSource对象建立和数据库的连接比起使用DriverManager接口更加高效,虽然两者的使用范围都很相似,并且都提供了方法用于建立和数据库的连接,设置连接的最大超时时间,获取流、登录。
       
    但两者之间的区别更加明显。和DriverManager不同,一个DataSource对象能够识别和描述它所代表的数据源的属性,而且DataSource对象的工作和JNDI(Javatm Naming and Directory Interfaceti)具有密切的关系,DataSource的建立、发布、独立于应用程序的管理都依靠JNDI技术。
        
    在JDBC2.0或JDBC3.0中,所有的数据库驱动程序提供商必须提供一个实现了DataSource接口的类,要使用数据源必须首先在JNDI中注册该数据源对象。
    如果在JNDI中注册了数据源对象,将会比起使用DriverManager来具有两个方面的优势:
    首先程序不需要像使用DriverManager一样对加载的数据库驱动程序信息进行硬编码,程序员可以选择先在JNDI中注册这个数据源对象,然后在程序中使用一个逻辑名称来引用它,JNDI会自动根据你给出的名称找到与这个名称绑定的DataSource对象。然后就可以使用这个DataSource对象来建立和具体数据库的连接了。

    其次,使用实现了DataSource接口的类所具有的第二个优势体现在连接池和分布式事务上。连接池通过对连接的复用而不是新建一个物理连接来显著地提高程序的效率。从而适用于任务繁忙、负担繁重的企业级分布式事务。
    *************************************************************************************

    二、JNDI简介:
    *************************************************************************************
    JNDI是用于向Java程序提供目录和命名功能的API。它被设计成独立于特定的目录服务,所以各种各样的目录都可以通过相同的方式进行访问。

    可以简单地把JNDI理解为一种将对象和名字绑定的技术,对象工厂负责生产出对象,这些对象都和惟一的名字绑定。外部程序可以通过名字来获取对某个对象的引用。

    在Intranets(企业内部网)和Internates(互联网)中目录服务(Directory service)扮演了一个非常重要的角色,它能够在众多的用户、机器、网络、服务、应用程序中访问各种各样的信息。目录服务提供了一系列的命名措施,用人类可以理解的命名方式来刻画各种各样的实体之间的关系

    一个企业式计算环境(computing environment)通常是由若干代表不同部分的命名复合而成。比如在一个企业级环境中DNS(Domain Name System)通常被当成顶层的命名方案(top-level namein facility)区分不同的部门或组织。而这些部门或组织自己又可以使用诸如LADP或NDS的目录服务

    从用户的角度来看,这些都是由不同的命名方案构成的复合名称。URL就是一个很典型的例子,它由多个命名方案构成。使用目录服务的应用程序必须支持这种复合构成方式

    使用目录服务API的Java开发人员获得的好处不仅在于API独立于特定的目录或命名服务,而且可以通过多层的命名方案无缝访问(seamless acess)目录对象。实际上,任何的应用程序都可以将自身的对象和特定的命名绑定起来,这种功能可以使到任何的Java程序查找和获取任何类型的对象

    终端用户可以方便地使用逻辑名称从而轻易地在网络上查找和识别各种不同的对象,目录服务的开发人员可以使用API方便地在不同的客服端之间切换而不需要作任何更改
    *************************************************************************************


    三、数据源和连接池的关系:
    *************************************************************************************
    JDBC2.0提供了javax.sql.DataSource接口,它负责建立与数据库的连接,在应用程序访问数据库时不需要编写连接数据库的代码,可以直接从数据源获得数据库连接。
     
    在DataSource中事先建立了多个数据库连接,这些数据库连接保存在连接池(Connect Pool)中。Java程序访问数据库时,只需要从连接池中取出空闲状态的数据库连接;当程序访问数据库结束,再将数据库连接放回连接池。
    *************************************************************************************


    四、数据源和JNDI的关系:
    *************************************************************************************
    DataSource对象是由Tomcat提供的,因此不能在程序中采用创建一个实例的方式来生产DataSource对象,而需要采用Java的另一个技术JNDI,来获得DataSource对象的引用。

    Tomcat把DataSource作为一种可以配置的JNDI资源来处理。生成DataSource对象的工厂为org.apache.commons.dbcp.BasicDataSourceFactory。

    在javax.naming包中提供了Context接口,该接口提供了将对象和名字绑定,以及通过名字检索对象的方法。Context中的主要方法有:
    bind(String name,Object object):将对象与一个名字绑定
    lookup(String name):返回与指定的名字绑定的对象
    *************************************************************************************


    五、Tomcat中数据源的配置:
    *************************************************************************************
    数据源的配置涉及修改server.xml和web.xml,在server.xml中加入定义数据源的元素<Resource>,在web.xml加入<resource-ref>元素,声明该Web应用所引用的数据


    A.在server.xml中加入<Resource>元素:<Resource>元素用来定义JNDI Resource。
      
    属性    描述
    name    指定Resource的JNDI名字
    auth    指定管理Resource的Manager,它有两个可选值:Container、Application
    type    指定Resource所属的Java类名

    <Resource name = "jdbc/BookDb" 
    auth = "Container" 
            type = "javax.sql.DataSource" />

    B.在<Resource>元素中加入<ResourceParams>元素:<ResourceParams>元素用来指定各种参数值
      
    属性    描述
    factory    指定生成的DataResource的factory类名
    maxActive    指定数据库连接池中处于活动状态的最大连接数目,0表示不受限制
    maxIdle    指定数据库连接池中处于空闲状态的最大连接数目,0表示不受限制
    maxWait    指定连接池中连接处于空闲状态的最长时间,超过会抛出异常,-1表示无限
    username    指定连接数据库的用户名
    password    指定连接数据库的口令
    driverClassName    指定连接数据库的JDBC驱动程序
    url             指定连接数据库的URL

       <ResourceParams name = "jdbc/BookDb">

        <parameter>
           <name>factory</name>
           <value>org.apache.commons.dbcp.BasicDataSourceFactory</value>
        </parameter>

        <parameter>
           <name>maxActive</name>
           <value>100</value>
        </parameter>

        <parameter>
           <name>maxIdle</name>
           <value>30</value>
        </parameter>

        <parameter>
           <name>maxWait</name>
           <value>10000</value>
        </parameter>

        <parameter>
           <name>username</name>
           <value>user</value>
        </parameter>

        <parameter>
           <name>password</name>
           <value>1234</value>
        </parameter>  

        <parameter>
           <name>driverClassName</name>
           <value>com.mysql.jdbc.Driver</value>
        </parameter>

        <parameter>
           <name>url</name>
           <value>jdbc:mysql//localhost:3306/BookDb?autoReconnect=true</value>
        </parameter>  

    </ResourceParams>

    C.在web.xml中加入<resource-ref>元素:<resource-ref>元素表示在Web应用中引用JNDI资源
      
    属性                  描述
    description    对所引用的资源的说明
    res-ref-name    指定所引用资源的JNDI名字,与<Resource>元素中的name属性对应
    res-type             指定所引用资源的类名字,与<Resource>元素中的type属性对应
    res-auth             指定所引用资源的Manager,与<Resource>元素中的auth属性对应

    *************************************************************************************


    六、在Web应用中使用数据源:
    *************************************************************************************
    javax.naming.Context提供了查找JNDI Resource的接口,可以通过三个步骤来使用数据源对象:

    A.获得对数据源的引用:
        Context ctx = new InitalContext();
    DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/BookDb");

        B.获得数据库连接对象:
            Connection con = ds.getConnection();
      
        C.返回数据库连接到连接池:
            con.close();

    在连接池中使用close()方法和在非连接池中使用close()方法的区别是:前者仅仅是把数据库连接对象返回到数据库连接池中,是连接对象又恢复到空闲状态,而非关闭数据库连接,而后者将直接关闭和数据库的连接
    *************************************************************************************


    七、发布使用数据源的Web应用:
    *************************************************************************************
      如果直接同JDBC访问数据库,可以把JDBC驱动程序拷贝到Web应用的WEB-INF/lib目录或者Tomcat安装目录下的common/lib目录下。
      
      如果通过数据源访问数据库,由于数据源由Servlet容器创建并维护,所以必须把JDBC驱动程序拷贝到Tomcat安装目录下的common/lib目录下,确保Servlet容器能够访问驱动程序。

    Servlet过滤器[分享]

    一、Servlet过滤器的概念:
    ***************************************************************************************
    Servlet过滤器是在Java Servlet规范2.3中定义的,它能够对Servlet容器的请求和响应对象进行检查和修改。   

    Servlet过滤器本身并不产生请求和响应对象,它只能提供过滤作用。Servlet过期能够在Servlet被调用之前检查Request对象,修改Request Header和Request内容;在Servlet被调用之后检查Response对象,修改Response Header和Response内容。

    Servlet过期负责过滤的Web组件可以是Servlet、JSP或者HTML文件。 
    ***************************************************************************************


    二、Servlet过滤器的特点:
    ***************************************************************************************
    A.Servlet过滤器可以检查和修改ServletRequest和ServletResponse对象
    B.Servlet过滤器可以被指定和特定的URL关联,只有当客户请求访问该URL时,才会触发过滤器
    C.Servlet过滤器可以被串联在一起,形成管道效应,协同修改请求和响应对象
    ***************************************************************************************


    三、Servlet过滤器的作用:
    ***************************************************************************************
    A.查询请求并作出相应的行动。
    B.阻塞请求-响应对,使其不能进一步传递。
    C.修改请求的头部和数据。用户可以提供自定义的请求。
    D.修改响应的头部和数据。用户可以通过提供定制的响应版本实现。
    E.与外部资源进行交互。
    ***************************************************************************************


    四、Servlet过滤器的适用场合:
    ***************************************************************************************
    A.认证过滤
    B.登录和审核过滤
    C.图像转换过滤 
    D.数据压缩过滤 
    E.加密过滤 
    F.令牌过滤 
    G.资源访问触发事件过滤 
    H.XSL/T过滤 
    I.Mime-type过滤
    ***************************************************************************************


    五、Servlet过滤器接口的构成:
    ***************************************************************************************
    所有的Servlet过滤器类都必须实现javax.servlet.Filter接口。这个接口含有3个过滤器类必须实现的方法:

    A.init(FilterConfig):
    这是Servlet过滤器的初始化方法,Servlet容器创建Servlet过滤器实例后将调用这个方法。在这个方法中可以读取web.xml文件中Servlet过滤器的初始化参数

    B.doFilter(ServletRequest,ServletResponse,FilterChain):
    这个方法完成实际的过滤操作,当客户请求访问于过滤器关联的URL时,Servlet容器将先调用过滤器的doFilter方法。FilterChain参数用于访问后续过滤器

    B.destroy():
    Servlet容器在销毁过滤器实例前调用该方法,这个方法中可以释放Servlet过滤器占用的资源
    ***************************************************************************************


    六、Servlet过滤器的创建步骤:
    ***************************************************************************************
    A.实现javax.servlet.Filter接口
    B.实现init方法,读取过滤器的初始化函数
    C.实现doFilter方法,完成对请求或过滤的响应
    D.调用FilterChain接口对象的doFilter方法,向后续的过滤器传递请求或响应
    E.销毁过滤器
    ***************************************************************************************


    七、Servlet过滤器对请求的过滤:
    ***************************************************************************************
    A.Servlet容器创建一个过滤器实例
    B.过滤器实例调用init方法,读取过滤器的初始化参数
    C.过滤器实例调用doFilter方法,根据初始化参数的值判断该请求是否合法
    D.如果该请求不合法则阻塞该请求
    E.如果该请求合法则调用chain.doFilter方法将该请求向后续传递
    ***************************************************************************************


    八、Servlet过滤器对响应的过滤:
    ***************************************************************************************
    A.过滤器截获客户端的请求
    B.重新封装ServletResponse,在封装后的ServletResponse中提供用户自定义的输出流
    C.将请求向后续传递
    D.Web组件产生响应
    E.从封装后的ServletResponse中获取用户自定义的输出流
    F.将响应内容通过用户自定义的输出流写入到缓冲流中
    G.在缓冲流中修改响应的内容后清空缓冲流,输出响应内容
    ***************************************************************************************

    九、Servlet过滤器的发布:
    ***************************************************************************************
    A.发布Servlet过滤器时,必须在web.xml文件中加入<filter>元素和<filter-mapping>元素。

    B.<filter>元素用来定义一个过滤器:
    属性                   含义
    filter-name    指定过滤器的名字
    filter-class    指定过滤器的类名
    init-param    为过滤器实例提供初始化参数,可以有多个

    C.<filter-mapping>元素用于将过滤器和URL关联:
    属性                     含义
    filter-name    指定过滤器的名字
    url-pattern    指定和过滤器关联的URL,为”/*”表示所有URL
    ***************************************************************************************


    十一、Servlet过滤器使用的注意事项
    ***************************************************************************************
    A.由于Filter、FilterConfig、FilterChain都是位于javax.servlet包下,并非HTTP包所特有的,所以其中所用到的请求、响应对象ServletRequest、ServletResponse在使用前都必须先转换成HttpServletRequest、HttpServletResponse再进行下一步操作。

    B.在web.xml中配置Servlet和Servlet过滤器,应该先声明过滤器元素,再声明Servlet元素


    C.如果要在Servlet中观察过滤器生成的日志,应该确保在server.xml的localhost对应的<host>元素中配置如下<logger>元素:
    <Logger className = “org.apache.catalina.logger.FileLogger”
    directory = “logs”prefix = “localhost_log.”suffix=”.txt”
    timestamp = “true”/>

    自定义JSP标签[分享]

    一、基本概念:
    *************************************************************************************
    1.标签(Tag):
    标签是一种XML元素,通过标签可以使JSP网页变得简洁并且易于维护,还可以方便地实现同一个JSP文件支持多种语言版本。由于标签是XML元素,所以它的名称和属性都是大小写敏感的

    2.标签库(Tag library):
    由一系列功能相似、逻辑上互相联系的标签构成的集合称为标签库。

    3.标签库描述文件(Tag Library Descriptor):
    标签库描述文件是一个XML文件,这个文件提供了标签库中类和JSP中对标签引用的映射关系。它是一个配置文件,和web.xml是类似的。

    4.标签处理类(Tag Handle Class):
    标签处理类是一个Java类,这个类继承了TagSupport或者扩展了SimpleTag接口,通过这个类可以实现自定义JSP标签的具体功能
    *************************************************************************************


    二、自定义JSP标签的格式:
    *************************************************************************************
    1.<% @ taglib prefix=”someprefix” uri=”/sometaglib” %>
      为了使到JSP容器能够使用标签库中的自定义行为,必须满足以下两个条件:
       1.从一个指定的标签库中识别出代表这种自定义行为的标签
       2.找到实现这些自定义行为的具体类

       第一个必需条件-找出一个自定义行为属于那个标签库-是由标签指令的前缀(Taglib  Directive's Prefix)属性完成,所以在同一个页面中使用相同前缀的元素都属于这个标签库。每个标签库都定义了一个默认的前缀,用在标签库的文档中或者页面中插入自定义标签。所以,你可以使用除了诸如jsp,jspx,java,servlet,sun,sunw(它们都是在JSP白皮书中指定的保留字)之类的前缀。
     
     uri属性满足了以上的第二个要求。为每个自定义行为找到对应的类。这个uri包含了一个字符串,容器用它来定位TLD文件。在TLD文件中可以找到标签库中所有标签处理类的名称

    2.<someprefix:sometag key=”somevalue”/>
     当web应用程序启动时,容器从WEB-INF文件夹的目录结构的META-INF搜索所有以.tld结尾的文件。也就是说它们会定位所有的TLD文件。对于每个TLD文件,容器会先获取标签库的URI,然后为每个TLD文件和对应的URI创建映射关系。
    在JSP页面中,我们仅需通过使用带有URI属性值的标签库指令来和具体的标签库匹配
    *************************************************************************************


    三、自定义JSP标签的处理过程:
    *************************************************************************************
    1.在JSP中引入标签库:<% @ taglib prefix=”taglibprefix” uri=”tagliburi” %>
    2.在JSP中使用标签库标签:<prefix : tagname attribute=”tagattribute”>
    3.Web容器根据第二个步骤中的prefix,获得第一个步骤中声明的taglib的uri属性值
    4.Web容器根据uri属性在web.xml找到对应的<taglib>元素
    5.从<taglib>元素中获得对应的<taglib-location>元素的值
    6.Web容器根据<taglib-location>元素的值从WEB-INF/目录下找到对应的.tld文件
    7.从.tld文件中找到与tagname对应的<tag>元素
    8.凑<tag>元素中获得对应的<tag-class>元素的值
    9.Web容器根据<tag-class>元素的值创建相应的tag handle class的实例
    10. Web容器调用这个实例的doStartTag/doEndTag方法完成相应的处理
    *************************************************************************************


    四、创建和使用一个Tag Library的基本步骤:
    *************************************************************************************
    1.创建标签的处理类(Tag Handler Class)
    2.创建标签库描述文件(Tag Library Descrptor File)
    3.在web.xml文件中配置<tag>元素
    4.在JSP文件中引人标签库
    *************************************************************************************


    五、TagSupport类简介:
    *************************************************************************************
    1.处理标签的类必须扩展javax.servlet.jsp.TagSupport.
    2.TagSupport类的主要属性:

    A.parent属性:代表嵌套了当前标签的上层标签的处理类
    B.pageContex属性:代表Web应用中的javax.servlet.jsp.PageContext对象

    3.JSP容器在调用doStartTag或者doEndTag方法前,会先调用setPageContext和setParent方法,设置pageContext和parent。因此在标签处理类中可以直接访问pageContext变量

    4.在TagSupport的构造方法中不能访问pageContext成员变量,因为此时JSP容器还没有调用
      setPageContext方法对pageContext进行初始化
    *************************************************************************************


    六、TagSupport处理标签的方法:
    *************************************************************************************
    1.TagSupport类提供了两个处理标签的方法:
      public int doStartTag() throws JspException
      public int doEndTag()   throws JspException

    2.doStartTag:但JSP容器遇到自定义标签的起始标志,就会调用doStartTag()方法。    
      doStartTag()方法返回一个整数值,用来决定程序的后续流程。
      A.Tag.SKIP_BODY:表示<prefix:someTag>…</prefix:someTag>之间的内容被忽略
      B.Tag.EVAL_BODY_INCLUDE:表示标签之间的内容被正常执行

    3.doEndTag:但JSP容器遇到自定义标签的结束标志,就会调用doEndTag()方法。doEndTag 
      ()方法也返回一个整数值,用来决定程序后续流程。
       A.Tag.SKIP_PAGE:表示立刻停止执行网页,网页上未处理的静态内容和JSP程序均被
         忽。略任何已有的输出内容立刻返回到客户的浏览器上。
       B.Tag_EVAL_PAGE:表示按照正常的流程继续执行JSP网页
    *************************************************************************************


    七、用户自定义的标签属性:
    *************************************************************************************
    如果在标签中还包含了自定义的属性,例如:
    <prefix:Mytag attribute1="value1">
        ...
    </prefix:Mytag>
    那么在标签处理类中应该将这个属性作为成员变量,并且分别提供设置和读取属性的方法。
    *************************************************************************************


    八、创建标签处理类的步骤:
    *************************************************************************************
    1.创建包含JSP网页静态文本的文件(即是要替换自定义JSP标签的文本)
    2.在Web应用启动时装载静态文本
    3.创建标签处理类
    *************************************************************************************


    九、如何创建包含JSP网页静态文本的文件:    
    *************************************************************************************
    1.使用java.util.Properties类来存放要替换网页中自定义JSP标签的静态文本
    2.Properties类代表了一系列属性的集合,其实例既可以被保存到流中,也可以从流中加  
      载。这些文本以key/value的形式存放在WEB-INF目录下,例如key=value,在属性列表中
      这些key/value都是String类型的 
    *************************************************************************************

    十、Properties类的常用API:
    *************************************************************************************
    1.setProperty(String key, String value):调用Hashtable类的put方法添加属性
    2.getProperty(String key):获取属性列表中key对应的属性值
    3.load(InputStream in):从输入流对象InputStream中读取属性列表(Properties list)
    4.store(OutputStream out,String comment):使用适当的格式将属性列表的属性对写入输
      出流对象中,默认使用ISO-88590-1编码格式,以行的方式处理输入。属性的key/value之
      间以”=、:”配对,以回车、换行分隔key/value对
    *************************************************************************************

    十一、ServletContext类的常用API:
    *************************************************************************************
    1.getContext(String uripath):返回服务器中uripath所代表的ServletContext对象
    2.getInitParameter(String name):返回ServletConfig对象中name参数的值
    3.getMineType(String file):返回file参数代表的文件的MIME类型
    4.getRequestDispatcher(String path):返回path代表的RequestDispacher对象
    5.getResourceAsStream(String path):以输入流的形式返回path对应的资源,在输入留中对象可以为任意形式的数据,path参数必须以“/”开始且相对于Context Root
    *************************************************************************************

    十二、如何使用ServletContxt读取并保存属性文件:
    *************************************************************************************
    1.创建java.util.Properties类对象
    2.获取ServletContext对象
    3.将属性文件以输入流的形式读入到某个输入流对象中
    4.将输入流对象加载到Properties对象中
    5.将Properties对象保存到ServletContext对象中
    *************************************************************************************

    十三、如何在Web应用启动时装载静态文本:
    *************************************************************************************
    1.创建继承了HttpServlet类的子类,在web.xml中配置这Servlet时设置load-on-startup属性:
    <servlet>
    <servlet-name>someclass</servlet-name>
    <servlet-class>somepackage.SomeClass</servlet-clas
    <load-on-startup>1</load-on-startup>
    </servlet>
    2.在这个Servlet的init()方法中创建java.util.Properties类
    3.获取当前Web应用的ServletContext对象
    4.将WEB-INF目录下的属性文件读入到输入流InputStream中:
    InputStream in = context.getResourceAsString("WEB-INF/someproperties.properties");
    5.将输入流加载到属性对象中
          ps.load(in);        
    6.将属性对象保存到上下文中。
    context.setAttribute("attributeName",ps);
    *************************************************************************************

    十四、如何创建标签处理类:
    *************************************************************************************
    1.引入必需的资源: 
          import javax.servlet.jsp.*;
        import javax.servlet.http.*;
        import java.util.*;
        import java.io.*;
    2.继承TagSupport类并覆盖doStartTag()/doEndTag()方法
    3.从ServletContext对象中获取java.util.Properties对象
    4.从Properties对象中获取key对应的属性值
    5.对获取的属性进行相应的处理并输出结果
    *************************************************************************************

    十五、创建标签库描述文件(Tag Library Descriptor):
    *************************************************************************************
    1.标签库描述文件,简称TLD,采用XML文件格式,定义了用户的标签库。TLD文件中的元素可以分成3类:
        A.<taglib>:标签库元素
        B.<tag>:标签元素
        C.<attribute>:标签属性元素

    2.标签库元素<taglib>用来设定标签库的相关信息,它的常用属性有:
        A.shortname:    指定Tag Library默认的前缀名(prefix)
        B.uri:            设定Tag Library的惟一访问表示符

    3.标签元素<tag>用来定义一个标签,它的常见属性有:
        A.name:        设定Tag的名字
        B.tagclass:    设定Tag的处理类
        C.bodycontent:    设定标签的主体(body)内容
                1).empty:表示标签中没有body
                2).JSP:表示标签的body中可以加入JSP程序代码
                3).tagdependent:表示标签中的内容由标签自己去处理

    4.标签属性元素<attribute>用来定义标签的属性,它的常见属性有:
        A.name:属性名称
        B.required:属性是否必需的,默认为false
        C.rtexprvalue:属性值是否可以为request-time表达式,也就是类似于<%=…%>的表达式
    *************************************************************************************

    十六、在Web应用中使用标签:
    *************************************************************************************
    1.如果Web应用中用到了自定义JSP标签,则必须在web.xml文件中加入<taglib>元素,它用于声明所引用的标签所在的标签库
        <taglib>
            <taglib-uri>/sometaglib</taglib-uri>
            <taglib-location>/WEB-INF/someTLD.tld</taglib-location>
        </taglib>

    2.<taglib-uri>:设定Tag Library的惟一标示符,在Web应用中将根据它来引用Tag Libray
    3.<taglib-location>:指定和Tag Library对应的TLD文件的位置
    4.在JSP文件中需要加入<% @ taglib% >指令来声明对标签库的引用。例如:
    <% @ taglib prefix = “somePrefix” uri = "/someuri" %>

    5.prefix表示在JSP网页中引用这个标签库的标签时的前缀,uri用来指定Tag Library的标识符,它必须和web.xml中的<taglib-uri>属性保持一致。

  • 相关阅读:
    Convert string to hex « Python recipes « ActiveState Code
    分享:301定向技术全面解决
    UTF8 ANSI Unicode/UCS2 UCS4 所占存储比较_高山流水_百度空间
    分享:Arcadia 0.12.1 发布,Ruby 集成开发环境
    分享:探索 Python、机器学习和 NLTK 库
    Windows Codepage: 936 (Simplified Chinese GBK)
    分享:QT 5.0 正式版发布,支持 C++11
    分享:探索 Python、机器学习和 NLTK 库
    分享:Gearmand 1.0.2 和 1.1.4 发布,作业调度系统
    Convert string to hex « Python recipes « ActiveState Code
  • 原文地址:https://www.cnblogs.com/baiduligang/p/4247678.html
Copyright © 2020-2023  润新知