Chinaunix首页 | 论坛 | 博客
  • 博客访问: 341205
  • 博文数量: 329
  • 博客积分: 2633
  • 博客等级: 少校
  • 技术积分: 3633
  • 用 户 组: 普通用户
  • 注册时间: 2011-04-22 15:43
文章分类

全部博文(329)

文章存档

2013年(244)

2012年(46)

2011年(39)

我的朋友

分类: 系统运维

2012-03-06 21:24:21

4Servlet、过滤器与侦听器

4.1Servlet包的构成与Servlet生命周期

以下是Servlet软件包中关键类和接口,图中包含了方法:

Servletjava服务器端的小程序,是java环境下实现动态网页的基本技术。Servlet程序能够调用javabeanjdbc、其他的ServletRMIEJBSOAPJNI等程序完成指定的功能,计算结果以html/xml等形式返回给客户端。

在应用中Servlet起到中间层的作用,将客户端和后台资源隔离开来。

Servlet API类主要放在javax.servletjavax.servlet.http这两个包中。javax.servlet中的类、接口定义和表述了Servlet实例与Servlet容器间的约定。javax.servlet.http中是Servlet程序在使用http协议工作时遵循的约定。Servlet包中最关键的是GenericServletHttpServlet这两个类。GenericServlet类实现了ServletServletSerializable三个接口的方法,定义了一个与协议无关的Servlet通用类,因为它是抽象类,所以一般作为父类用。HttpServlet是一个抽象类,继承了GenericServlet,增加了对HTTP的支持,是使用HTTP协议工作的Servlet程序的父类。用户编写的Servlet程序需要继承GenericServlet或者HttpServlet

4.1.1CenericServlet抽象类

GenericServlet抽象类为Servlet接口提供了通用实现,它与任何网络应用层协议无关。GenericServlet类除了实现Servlet接口,还实现了ServletConfig接口和Serializable接口。有以下方法:

service()抽象类,需要重置。

getServletConfig()返回一个ServletConfig对象。

getServletContext()返回一个ServletContext对象。

init()初始化方法。

destroy()Servlet容器销毁一个Servlet对象前都会自动调用这个。

getInitParameterNames()返回web.xml中给Servlet程序配置的初始化变量名

getInitParameter()返回web.xml中定义的初始化参数值。

4.1.2HttpServlet抽象类

HttpServlet 类是 GenericServlet 类的子类。HttpServlet 类为 Servlet 接口提供了与HTTP协议相关的通用实现,也就是说,HttpServlet对象适合运行在与客户端采用HTTP协议通信的Servlet容器或者Web 服务器中。在开发JavaWeb应用时,自定义的Servlet类一般都扩展HttpServlet类。有以下方法:

       service()不是抽象类了。

       doGet()当客户端以GET方式提交请求时,该方法被自动调用来处理客户端的请求。

       doPost()当客户端以POST方式提交请求时,该方法被自动调用来处理客户端的请求。

4.1.3Servlet程序的生命周期

以下是HttpServlet的生命周期:

HttpServlet程序

1.初始化(加载资源)

2.service:doGet(),doPost(),doPut(),doTrace(),doDeleter(),doOptions()

3.销毁(释放资源)

4.2Servlet编程

4.2.1Servlet程序的编写过程

主要是doGet()doPost()函数处理请求。

4.2.2第一个Servlet程序

一些参数的说明不写了,如果想了解Servlet大程序如何制作可以参照简单博客程序:

http://blog.chinaunix.net/uid-25728370-id-3118389.html

4.2.3ServletHTML表单

Servlet中读取表单的方法同jsp,通过调用request隐含对象中的方法实现。在Servlet程序的doGet()或者doPost()方法中,方法的第一个形参HttpServletRequest对象与jsp中的request隐含对象相当。

4.2.4Servlet通信

Servlet通信是指Servletjsp间、servletservlet间传递信息。比较通用的数据传递方法是利用jsprequestsessionapplication作用范围变量实现。

4.2.5Servletsession跟踪

Servlet实现session跟踪的方法主要有隐藏表单域、cookieURL重写、session隐含对象等实现,编程方法基本上同jsp

4.2.6JSP页面作Servlet程序

Web.xml中的元素下的写成:/xx.jsp。这样把原来需要卸载doGet()或者doPost()中的程序段写在xx.jsp中即可。依次的把各个Servlet写在某一个jsp页面中。

4.3过滤器

过滤器是一个中间组件,用于拦截源数据和目的数据之间的消息,并且过滤二者之间传递的数据对于web应用程序,过滤器驻留在web服务器上的web组件,它可以过滤从客户端传递到服务器端的请求和响应

4.3.1过滤器的基本工作原理

FilterServletjsp一样,属于servlet2.3/2.4规范中的一种组件,它被装配在web应用中,对到达web应用的请求(request)或从web应用中输出的响应(response)信息进行拦截和过滤

4.3.2过滤器的API接口及部署信息

1).Filter接口是过滤器API的核心。实现的三个方法:

init()方法:在应用程序启动时用容器调用,web容器调用本方法来初始化过滤器,servlet容器仅调用过滤器实现的init()方法一次

doFilter()方法:servlet容器接收到URL映射的过滤器的每次请求时都会调用该方法, doFilter()方法给过滤器对象一个机会来处理请求,转发请求道过滤器链中的下一个组件,或者自己回复客户端

destroy()方法:servlet容器将此方法作为过滤器对象的最后一个方法俩调用,以指示过滤器的生命周期结束

2).FilterConfig接口:该接口主要为过滤器提供初始化,可读取在web.xml的配置。FilterConfig接口声明了四个方法:

getFilterName():返回在部署描述文件中指定的过滤器的名称

getInitParameter(string):返回在部署描述文件中指定的参数值

getInitParameterNames():返回在部署描述文件中指定的所有参数的名称

getServletContext():返回web应用程序的servletContext

3). FilterChain接口:由容器实现,由容器将其实例作为参数传到Filter接口的doFilter方法。FilterChain接口只有一个方法,doFilter方法:我们从一个过滤器的对象的doFilter方法中调用此方法以继续过滤器链的传递过程,它会将控制转到链中的下一个组件。

4.3.3第一个过滤器程序

主要把要过滤的事情放在函数doFilter中实现例如代码:

package com.wsy.Filter;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

public class ModifyCode implements Filter{

    protected FilterConfig filterConfig;

    private String targetEncoding="UTF-8";

    public void init(FilterConfig config)throws ServletException{

       this.filterConfig=config;

       this.targetEncoding=config.getInitParameter("code");

    }

    public void doFilter(ServletRequest request,ServletResponse response,FilterChain chain)throws ServletException{

       //System.out.println(this.targetEncoding);

       HttpServletRequest srequest=(HttpServletRequest)request;

       try{

           srequest.setCharacterEncoding(this.targetEncoding);

           chain.doFilter(request, response);

       }catch(Exception e){

           e.printStackTrace();

       }

      

    }

    public void destroy(){

       this.filterConfig=null;

    }

}

Web.xml上面写上:

>

    <filter-name>modifycodefilter-name>

    <filter-class>com.wsy.Filter.ModifyCodefilter-class>

    <init-param>

       <param-name>codeparam-name>

       <param-value>UTF-8param-value>

    init-param>

</filter>

    <filter-name>modifycodefilter-name>

    <url-pattern>/*url-pattern>

    <dispatcher>REQUESTdispatcher>

    <dispatcher>FORWARDdispatcher>

    <dispatcher>INCLUDEdispatcher>

    <dispatcher>ERRORdispatcher>

其中chain.doFilter(request, response);语句使得多个过滤器如果一起执行的话,会不断递归进去完,一个个结束回来,某种程度上有点像两阶段锁协议。

4.3.4用过滤器解决request中文乱码问题

客户端数据一般通过HTTPGET/POST提交给服务器,在服务器用request.getParameter()读取参数时,很容易出现中文乱码现象。可以在tomcat中的server.xml的字段设置URLEncoding属性也可以在request.setCharacterEncoding()来设置。

4.4侦听器

主要侦听Servlet容器中的事件,所侦听的事件发生之后,容器激活侦听器,执行预定的操作。侦听器侦听的事件主要是jsp隐含对象applicationsessionrequest对象上发生的事件,主要有隐含对象的创建与销毁事件,相关作用范围变量的创建、修改和销毁事件。

web.xml中部署入元素。

4.4.1Servlet Context侦听器

上述侦听器是Servlet对于上下文相关的侦听。它的接口是javax.servlet.ServletContextListenerjavax.servlet.Servlet-ContextAttributeListener。在WEB端实现监听 (一系列的监听接口)

1).ServletContextListener:对整个Servlet上下文监听(启动、销毁)

public void contextInitialized(ServletContextEvent sce):上下文初始化函数

public void contextDestroyed(ServletContextEvent sce):上下文销毁函数

ServletContextEvent事件:取得一个ServletContextapplication)对象

public ServletContext getServletContext()

2).ServletContextAttributeListener:对Servlet上下文属性的监听

public void attributeAdded(ServletContextAttributeEvent scab):增加属性(setAttribute)触发

public void attributeRemoved(ServletContextAttributeEvent scab):属性删除(removeAttribute

public void attributeReplaced(ServletContextAttributeEvent scab):属性替换(第二次设置同一个属性)触发

上述方法的参数时ServletContextAttributeEventServletContextAttributeEvent事件:能取得设置属性的名称与内容

    public String getName():得到属性名称

    public Object getValue():得到属性的值

3).实现:

public class XXX implements ServletContextListener,ServletContextAttributeListener {...}

4.4.2ServletRequest侦听器

这个侦听器主要有两个接口。

1). ServletRequestListener接口

当需要对用户的每次请求进行监听时,可以使用ServletRequestListener接口

requestDestroyed(ServletRequestEvent arg0)request销毁的时候调用。

requestInitialized(ServletRequestEvent arg0)request初始化的时候调用。

ServletRequestListener接口一旦监听到事件后,将产生ServletRequestEvent的事件处理对象,此事件定义的方法如下:

Public ServletRequest getServletRequest()  取得ServletRequest对象

Public ServletContext getServletContext()   取得ServletContext对象

2). ServletRequestAttributeListener接口,对request范围属性的监听,此接口定义的方法如下:

Public void attributeAddedServletRequestAttributeEvent srae 属性增加是调用

Public void attributeReplaced(ServletRequestAttributeEvent srae)  属性替换时调用

Public void attributeRemoved(ServletRequestAttributeEvent srae)  属性删除时调用

加入监听器后,request属性的操作会产生ServletRequestAttributeEvent事件,此事件定义的方法如下:

Public String getName()  取得设置的属性名称

Pulbic object getName()  取得设置的属性内容

4.4.3HttpSession侦听器

主要侦听与session隐含对象相关的事件,包括四个侦听器接口。

1).HttpSessionListener接口

监听上下文中session对象的创建与销毁事件,方法有:

public void sessionCreated(HttpSessionEvent se)

public void sessionDestroyed(HttpSessionEvent se)

例如:

public class MySessionListener implements HttpSessionListerner {

public void sessionCreated(HttpSessionEvent se){

HttpSession session = se.getSession();

    System.out.println(“session已经建立,id号是”+session.getId());

}

 public void sessionDestroyed(HttpSessionEvent se){

  System.out.println(“id号是”+session.getId()+”即将失效”);

}

}

然后不要忘记了在web.xml文件中部署该监听器,如下:

   xx.MySessionListener

2).HttpSessionAttributeListener接口,监听session中的属性被添加,修改、或删除。有以下方法:

public void attributeAdded(HttpSessionBindingEvent se) 

public void attributeRemoved(HttpSessionBindingEvent se)

public void attributeReplaced(HttpSessionBindingEvent se)

例如:

session.setAttribute("zhangsan","12345");

session.setAttribute("zhangsan","67890");

public void attributeReplaced(HttpSessionBindingEvent se){

   String name = se.getName();//"zhangsan"

   String oldValue = se.getValue();//"12345"

   String newValue = (String)(se.getSession().getAttribute(name));//"67890"

}

3).HttpSessionBindingListener接口,监听session中的属性被添加,或删除。有以下方法:

public void valueBound(HttpSessionBindingEvent event)

public void valueUnbound(HttpSessionBindingEvent event)

这个监听器可以与HttpSessionAttributeListener不同的是它要求添加的属性要实现该接口,并且不需要在web.xml文件中部署。

如以下代码:

session.setAttribute(“zh”,new User(“zhangsan”));

Session.removeAttribute(“zh”);

public class User implements HttpSessionBindingListener {

   private String name;

   public User(String name) {

        this.name = name;

   }

 public void valueBound(HttpSessionBindingEvent arg0) {

       System.out.println("绑定了属性"+arg0.getName()+":"+arg0.getValue().toString());

   }

 public void valueUnbound(HttpSessionBindingEvent arg0) {

       System.out.println("解除了属性"+arg0.getName());

 }

 public String toString() {

       return this.name;

   }

}

4).HttpSessionActivationListener接口,侦听的是session转移事件。当一台JVM中的session隐含对象被存储并等待转移至另一台JVM时,此时称发生了passivate事件(钝化事件)。当session隐含对象被成功转移至另一台JVM后,容器激活接收到的session隐含对象,此时称发生了Active事件(激活事件)。详细的说,这个监听器也是由属性类来实现的,但它不是监听属性被添加或解除,而是监听session对象被钝化或激活。那么什么是钝化呢?钝化就是将session对象的状态序列化成字节码的形式,然后把这些字节码存储到硬盘上或通过网络将这些字节码传送到另外一个虚拟机中(Java中将这一机制成为序列化)。激活就是将这些字节码恢复成对象当初的状态的过程(反序列化)。为什么需要钝化和激活呢?一 Web服务器可以将一个session的状态通过钝化的形式将状态保存到硬盘上,这样就能够为更多的用户提供服务,当这个用户又需要这个session 对象的时候再通过激活就可以恢复这个session的状态了。当有多个Web服务器的时候,服务器通过负载均衡有可能将session对象的状态从一个虚拟机传送到另外一个虚拟机,此时在一个虚拟机上钝化该session对象,而在另外一个虚拟机上激活该对象。需要注意的是钝化和激活是需要时间的,会对你的程序性能有影响。钝化和激活是服务器做的事情,你不能在你的程序中对session对象进行钝化。

阅读(1008) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~