JavaEE

JavaWeb基础恢复之过滤器 与 监听器

2018-04-25  本文已影响11人  平安喜乐698
目录
    1.过滤器
    2.监听器
1.过滤器
对所有资源请求进行拦截
    权限访问控制、过滤敏感词汇、压缩响应信息

    web应用程序启动时,服务器会创建Filter的实例对象,并调用其init方法。
    服务器每次调用web资源的service方法之前,会先调用一下filter的doFilter方法
    多个Filter组合起来称之为一个Filter链,按web.xml中顺序,决定先调用哪个Filter
步骤
 1.implements Filter
 2.web.xml配置

Filter处理类---统一设置编码

package com.sst.cx;

import java.io.IOException;
import java.util.Enumeration;

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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet Filter implementation class TestFilter
 */
@WebFilter("/TestFilter")
public class TestFilter implements Filter {

        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("----过滤器初始化----");
        }

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

            //对request和response进行一些预处理
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=UTF-8");
            
            System.out.println("前!!!");
            chain.doFilter(request, response);  //让目标资源执行,放行
            System.out.println("后!!!");
        }

        @Override
        public void destroy() {
            System.out.println("----过滤器销毁----");
        }
}
  <filter>
    <filter-name>TestFilter</filter-name>
    <filter-class>com.sst.cx.TestFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>TestFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
  </filter-mapping>

Filter处理类---统一设置编码(带有初始化参数的过滤器)

package com.sst.cx;

import java.io.IOException;
import java.util.Enumeration;

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.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet Filter implementation class TestFilter
 */
@WebFilter("/TestFilter")
public class TestFilter implements Filter {

        private FilterConfig filterConfig = null;
        // 设置默认的字符编码
        private String defaultCharset = "UTF-8";
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("----过滤器初始化----");
            this.filterConfig = filterConfig;
            
            // 获取 过滤器名
            String filterName = filterConfig.getFilterName();
            // 获取 在web.xml文件中配置的初始化参数
            String initParam1 = filterConfig.getInitParameter("name");
            String initParam2 = filterConfig.getInitParameter("like");
            // 获取 在web.xml文件中配置的初始化参数集合。
            Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
            while (initParameterNames.hasMoreElements()) {
                String paramName = (String) initParameterNames.nextElement();
            }
        }

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

            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse resp = (HttpServletResponse) response;
            // 得到在web.xml中配置的字符编码
            String charset = filterConfig.getInitParameter("charset");
            if(charset==null){
                charset = defaultCharset;
            }
            req.setCharacterEncoding(charset);
            resp.setCharacterEncoding(charset);
            resp.setContentType("text/html;charset="+charset);
            
            MyCharacterEncodingRequest requestWrapper = new MyCharacterEncodingRequest(req);
            chain.doFilter(requestWrapper, resp);
        }

        @Override
        public void destroy() {
            System.out.println("----过滤器销毁----");
        }
}



/**
* @ClassName: MyCharacterEncodingRequest
* @Description: Servlet API中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,
* (HttpServletRequestWrapper类实现了request接口中的所有方法,但这些方法的内部实现都是仅仅调用了一下所包装的的 request对象的对应方法)
* 以避免用户在对request对象进行增强时需要实现request接口中的所有方法。
* 所以当需要增强request对象时,只需要写一个类继承HttpServletRequestWrapper类,然后在重写需要增强的方法即可
*     1.实现与被增强对象相同的接口 
    2、定义一个变量记住被增强对象
    3、定义一个构造函数,接收被增强对象
    4、覆盖需要增强的方法
    5、对于不想增强的方法,直接调用被增强对象(目标对象)的方法
*/ 
class MyCharacterEncodingRequest extends HttpServletRequestWrapper{
    //定义一个变量记住被增强对象(request对象是需要被增强的对象)
    private HttpServletRequest request;
    //定义一个构造函数,接收被增强对象
    public MyCharacterEncodingRequest(HttpServletRequest request) {
        super(request);
        this.request = request;
    }
    /* 覆盖需要增强的getParameter方法
     * @see javax.servlet.ServletRequestWrapper#getParameter(java.lang.String)
     */
    @Override
    public String getParameter(String name) {
        try{
            //获取参数的值
            String value= this.request.getParameter(name);
            if(value==null){
                return null;
            }
            //如果不是以get方式提交数据的,就直接返回获取到的值
            if(!this.request.getMethod().equalsIgnoreCase("get")) {
                return value;
            }else{
                //如果是以get方式提交数据的,就对获取到的值进行转码处理
                value = new String(value.getBytes("ISO8859-1"),this.request.getCharacterEncoding());
                return value;
            }
        }catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
  <filter>
    <filter-name>TestFilter</filter-name>
    <filter-class>com.sst.cx.TestFilter</filter-class>
    <init-param>
      <description>配置过滤器的初始化参数1</description>
      <param-name>name</param-name>
      <param-value>hello</param-value>
    </init-param>
    <init-param>
      <description>配置过滤器的初始化参数2</description>
      <param-name>like</param-name>
      <param-value>java</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>TestFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
  </filter-mapping>

过滤器进阶

 装饰模式又名包装(Wrapper)模式
    在不必改变原类文件和使用继承的情况下,动态的扩展一个对象的功能。
 
 当某个对象的方法不适应业务需求时,通常有2种方式可以对方法:
    1.编写子类,覆盖需增强的方法。
    2.使用Decorator设计模式对方法进行增强。(无法得到class文件时)

 实现步骤
   1.编写一个类去继承被增强对象所继承的接口或父类。
   2.在类中定义一个变量(变量类型即需增强对象的类型)。
   3.在类中定义一个构造函数(接收需增强的对象)。
   4.覆盖需增强的方法。
 
 
 Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper,HttpServletRequestWrapper 类实现了request 接口中的所有方法


未完待续。。。
2.监听器
    一个用来监听其他对象方法或属性改变的普通类(触发后调用指定方法)


事件监听涉及到三个组件:事件源、事件对象、事件监听器
    当事件源上发生某一个动作时,它会调用事件监听器的某个方法(传入事件对象,通过事件对象,就可以拿到事件源)

监听器(处理java类)

例1

package com.sst.cx;

import java.awt.Frame;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

public class TestListener {
    public static void main(String[] args) {
        
        Frame f = new Frame();
        f.setSize(400, 400);
        f.setVisible(true);
        
        // 添加监听(注册事件监听器)
        f.addWindowListener(new WindowListener(){

            // 窗体处于活跃状态时调用
            public void windowActivated(WindowEvent e) {
                System.out.println("处于活跃状态");
            }

            // 窗体已经关闭后调用
            public void windowClosed(WindowEvent e) {
                System.out.println("窗体已经关闭");
            }

            // 正在关闭时调用
            public void windowClosing(WindowEvent e) {
                // 通过事件对象e来获取事件源对象
                Frame f = (Frame) e.getSource();
                System.out.println(f+"窗体正在关闭");
                f.dispose();
            }

            // 处于非活跃状态时调用
            public void windowDeactivated(WindowEvent e) {
                System.out.println("处于非活跃状态");
            }

            
            public void windowDeiconified(WindowEvent e) {
                System.out.println("?");
            }

            public void windowIconified(WindowEvent e) {
                System.out.println("?");
            }

            public void windowOpened(WindowEvent e) {
                System.out.println("窗体打开后调用");
            }
        });
    }
}

例2

package com.sst.cx;

import java.awt.Frame;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

public class TestListener {
    public static void main(String[] args) {
        
        //
        Person p = new Person();
        //注册监听p对象行为的监听器
        p.registerListener(new PersonListener() {
            //监听p吃东西这个行为
            public void doeat(Event e) {
                Person p = e.getSource();
                System.out.println(p + "在吃东西");
            }
            //监听p跑步这个行为
            public void dorun(Event e) {
                Person p = e.getSource();
                System.out.println(p + "在跑步");
            }
        });
        //p在吃东西
        p.eat();
        //p在跑步
        p.run();
    }
}




/**
* @ClassName: Person(事件源)
* @Description: 设计一个Person类作为事件源,这个类的对象的行为(比如吃饭、跑步)可以被其他的对象监听
*
*/  
public class Person {
    /**
    * @Field: listener
    *          在Person类中定义一个PersonListener变量来记住传递进来的监听器
    */ 
    private PersonListener listener;

    /**
    * @Method: eat
    * @Description: 设计Person的行为:吃
    *
    */ 
    public void eat() {
        if (listener != null) {
            /**
             * 调用监听器的doeat方法监听Person类对象eat(吃)这个动作,将事件对象Event传递给doeat方法,
             * 事件对象封装了事件源,new Event(this)中的this代表的就是事件源
             */
            listener.doeat(new Event(this));
        }
    }

    /**
    * @Method: run
    * @Description: 设计Person的行为:跑
    *
    */ 
    public void run() {
        if (listener != null) {
            /**
             * 调用监听器的dorun方法监听Person类对象run(跑)这个动作,将事件对象Event传递给doeat方法,
             * 事件对象封装了事件源,new Event(this)中的this代表的就是事件源
             */
            listener.dorun(new Event(this));
        }
    }

    /**
    * @Method: registerListener
    * @Description: 这个方法是用来注册对Person类对象的行为进行监听的监听器
    *
    * @param listener
    */ 
    public void registerListener(PersonListener listener) {
        this.listener = listener;
    }
}

/**
* @ClassName: PersonListener(事件监听器)
* @Description: 设计Person类(事件源)的监听器接口
*
*/ 
interface PersonListener {

    /**
    * @Method: doeat
    * @Description: 这个方法是用来监听Person对象eat(吃)这个行为动作,
    *                 当实现类实现doeat方法时就可以监听到Person类对象eat(吃)这个动作
    *
    * @param e
    */ 
    void doeat(Event e);

    /**
    * @Method: dorun
    * @Description: 这个方法是用来监听Person对象run(跑)这个行为动作,
    *                 当实现类实现dorun方法时就可以监听到Person类对象run(跑)这个动作
    *
    * @param e
    */ 
    void dorun(Event e);

}

/**
* @ClassName: Event(事件对象)
* @Description:设计事件类,用来封装事件源
*
*/ 
class Event {

    /**
    * @Field: source
    *          事件源(Person就是事件源)
    */ 
    private Person source;

    public Event() {
        
    }

    public Event(Person source) {
        this.source = source;
    }

    public Person getSource() {
        return source;
    }

    public void setSource(Person source) {
        this.source = source;
    }
}

JavaWeb中的监听器

用于
    1.监听域对象(ServletContext, HttpSession和 ServletRequest)自身的创建和销毁的事件监听器。
    2.监听域对象中的属性的增加和删除的事件监听器。
    3.监听绑定到HttpSession域中的某个对象的状态的事件监听器。

监听ServletContext对象的创建和销毁事件

    ServletContextListener接口

    创建:服务器启动后创建ServletContext(针对每一个Web应用)
    销毁:服务器关闭前关闭ServletContext(代表每一个web应用)

步骤:
 1.implements ServletContextListener
 2.web.xml
监听类

package com.sst.cx;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

/**
 * Application Lifecycle Listener implementation class MyServletContextListener
 *
 */
@WebListener
public class MyServletContextListener implements ServletContextListener{

    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        // TODO Auto-generated method stub
        System.out.println("ServletContext--对象销毁");
         
    }

    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        // TODO Auto-generated method stub
        System.out.println("ServletContext--对象创建"); 
    } 
}
web.xml中+

 <!-- 注册针对ServletContext对象进行监听的监听器 -->
 <listener>
 <description>ServletContextListener监听器</description>
 <!--实现了ServletContextListener接口的监听器类 -->
 <listener-class>com.sst.cx.MyServletContextListener</listener-class>
 </listener>

监听HttpSession域对象的创建和销毁

    HttpSessionListener接口
        创建一个Session时,激发sessionCreated (HttpSessionEvent se) 方法
        销毁一个Session时,激发sessionDestroyed (HttpSessionEvent se) 方法。
监听类

package com.sst.cx;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * Application Lifecycle Listener implementation class MyHttpSessionListener
 *
 */
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println( se.getSession() + "=====创建了!!");
    }

    /* HttpSession的销毁时机需要在web.xml中进行配置,如下:
     * <session-config>
              <session-timeout>1</session-timeout>
          </session-config>
          这样配置就表示session在1分钟之后就被销毁
     */
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("session销毁了!!");
    }   
}
web.xml 同上
jsp 

触发:
  ${pageContext.session.id}

监听ServletRequest域对象的创建和销毁

    ServletRequestListener接口

        Request对象被创建(用户每一次访问都会创建request对象)时,调用监听器的requestInitialized(ServletRequestEvent sre)方法
        Request对象被销毁(当前访问结束,request对象就会销毁)时,调用监听器的requestDestroyed(ServletRequestEvent sre)方法
监听类

package com.sst.cx;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;

/**
 * Application Lifecycle Listener implementation class MyServletRequestListener
 *
 */
@WebListener
public class MyServletRequestListener implements ServletRequestListener {

    @Override
    public void requestDestroyed(ServletRequestEvent sre) {
        System.out.println(sre.getServletRequest() + "销毁了!!");   
    }

    @Override
    public void requestInitialized(ServletRequestEvent sre) {
        System.out.println(sre.getServletRequest() + "创建了!!");
    }
}
web.xml 同上
jsp 

触发:

         <%--使用c:url标签构建url,构建好的url存储在servletDemo1变量中--%>
       <c:url value="/servlet/ServletDemo1" scope="page" var="servletDemo1">
           <%--构建的url的附带的中文参数 ,参数名是:username,值是:孤傲苍狼--%>
           <c:param name="username" value="孤傲苍狼"></c:param>
       </c:url>
      <%--使用get的方式访问 --%>
       <a href="${servletDemo1}">超链接(get方式请求)</a>
       <hr/>
       <%--使用post方式提交表单 --%>
       <form action="${pageContext.request.contextPath}/servlet/ServletDemo1" method="post">
           用户名:<input type="text" name="username" value="孤傲苍狼" />
           <input type="submit" value="post方式提交">
       </form>
       
上一篇下一篇

猜你喜欢

热点阅读