servlet之过滤器&监听器

过滤器

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-388L9dWe-1607249381740)(C:\Users\hello\AppData\Roaming\Typora\typora-user-images\image-20201107204647321.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mK8Bvo34-1607249381744)(C:\Users\hello\AppData\Roaming\Typora\typora-user-images\image-20201107222543846.png)]

过滤器其实很简单就是实现Filter接口的java类,接口中有init(),doFilte(),destroy()方法。

init()和destory()方法就不用多说了,他俩跟Servlet是一样的。只有在Web服务器加载和销毁的时候被执行,只会被执行一次!

值得注意的是doFilter()方法,**它有三个参数(ServletRequest,ServletResponse,FilterChain),**从前两个参数我们可以发现:过滤器可以完成任何协议的过滤操作

FilterChain是一个接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5hBektje-1607249381749)(C:\Users\hello\AppData\Roaming\Typora\typora-user-images\image-20201107222933471.png)]

FilterChain.doFilter()就是放行给下一个过滤器,或者目标资源

例子:通过过滤器解决编码问题

jsp:

html>

  <head>

    <title>$Title$</title>
  </head>
  <body>
  <form action="/fliter" method="post">
    姓名: <input type="text" name="name">


    <input value="提交" type="submit">
  </form>
  </body>
</html>

过滤器:

过滤器注册:

 <filter>
        <filter-name>filterencode</filter-name>
        <filter-class>FilterDemo</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>filterencode</filter-name>
        <url-pattern>/fliter</url-pattern>
    </filter-mapping>

过滤器编写:

 @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //将request和response强转成http协议的
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        httpServletRequest.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("text/html;charset=UTF-8");
        System.out.println("第一经过过滤器");
        System.out.println("设置request的utf-8");
        System.out.println(httpServletRequest);
//放行
        filterChain.doFilter(httpServletRequest,servletResponse);

        System.out.println("第二次经过过滤器");
        System.out.println("设置response的utf-8");
        System.out.println(httpServletResponse);

    }

servlet:

 @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter pw=resp.getWriter();

        System.out.println("servlet-->"+req);
        String name=req.getParameter("name");
        System.out.println("获得前端的name"+name);
        pw.write("收到前端的name-->"+name);
        System.out.println("servlet-->"+resp);
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jaV7lNVW-1607249381754)(C:\Users\hello\AppData\Roaming\Typora\typora-user-images\image-20201107223328593.png)]

监听器

  • 监听器就是一个实现特定接口的普通java程序,这个程序专门用于监听另一个java对象的方法调用或属性改变,当被监听对象发生上述事件后,监听器某个方法将立即被执行

  • 监听器涉及三个组件:事件源,事件对象,事件监听器

  • 事件源发生动作时,调用监听器的方法,同时传递事件对象给事件监听器(从而监听器可以通过事件对象对时间源进行操作)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ltG71z2h-1607249381757)(C:\Users\hello\AppData\Roaming\Typora\typora-user-images\image-20201107172019394.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mQZceBHA-1607249381761)(C:\Users\hello\AppData\Roaming\Typora\typora-user-images\image-20201107174718883.png)]

解释

事件源中的这句代码是核心personListener.doEat(new Event(this))

# 由上图知
# 1. main方法中 产生事件源对象this(调用eat方法的对象) ,调用事件源方法,也就是事件发生
# 2. 事件发生 触发事件对象生成(new event(this))
# 3. 因为在main中通过 匿名对象 在事件源上注册了监听器(person.registerLister(匿名对象的listener))
# 4. 所以第2步事件对象的产生,使得监听器(匿名对象就是监听器)执行[personListener.doEat(new Event(this))]
注:在监听器的方法的执行过程中,因为封装了event,且event封装了事件源(此处为this) 故可在监听器中操作事件源

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VyyYF5tS-1607249381764)(C:\Users\hello\AppData\Roaming\Typora\typora-user-images\image-20201107195949110.png)]

监听器接口:

   /**
     * 事件监听器
     *
     * 监听Person事件源的eat和sleep方法
     */
    interface PersonListener{
    
        void doEat(Event event);
        void doSleep(Event event);
    }

事件对象:

   * 事件对象Even
     *
     * 事件对象封装了事件源
     *
     * 在监听器上能够通过事件对象获取得到事件源
     *
     *
     */
    class Event{
        private Person person;
    
        public Event() {
        }
    
        public Event(Person person) {
            this.person = person;
        }
    
        public Person getResource() {
            return person;
        }
    
    }

测试:

ublic static void main(String[] args) {

        Person person = new Person();

        //注册监听器,将监听器器赋给person中的监听器
        person.registerLister(new PersonListener() {
            @Override
            public void doEat(Event event) {
                Person person1 = event.getResource();
                System.out.println(person1 + "正在吃饭呢!");
            }

            @Override
            public void doSleep(Event event) {
                Person person1 = event.getResource();
                System.out.println(person1 + "正在睡觉呢!");
            }
        });


        //当调用eat方法时,触发事件,将事件对象传递给监听器,(事件对象event封装了事件源)最后监听器获得事件源,对事件源进行操作
        person.Eat();
    }

监听的实质,要监听的事件源方法中调用监听器的方法对事件源进行操作

servlet监听器

和其它事件监听器略有不同的是,servlet监听器的注册不是直接注册在事件源上,而是由WEB容器负责注册,开发人员只需在web.xml文件中使用<listener>标签配置好监听器

1.监听对象的创建和销毁
  • HttpSessionListener
  • ServletContextListener
  • ServletRequstListener

使用:

   <listener>
       <listener-class>Listener1</listener-class>  
   </listener>
ublic class Listener1 implements ServletContextListener,
        HttpSessionListener, ServletRequestListener {

    // Public constructor is required by servlet spec
    public Listener1() {
    }
    
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("容器创建了");
    }

    public void contextDestroyed(ServletContextEvent sce) {

        System.out.println("容器销毁了");
    }


    public void sessionCreated(HttpSessionEvent se) {

        System.out.println("Session创建了");
    }

    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("Session销毁了");
    }


    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
        
    }

    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {

    }
}
2.监听context,Session,Request属性的变化
  • ServletContextAttributeListener
  • HttpSessionAttributeListener
  • ServletContextAttributeListener

三个接口中的方法名都一致,只不过接受的参数不同,都为

  • attributeAdded()
  • attributeRemoved()
  • attributeReplaced()

    public class Listener1 implements ServletContextAttributeListener {
    
        @Override
        public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
            System.out.println("Context对象增加了属性");
        }
    
        @Override
        public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
            System.out.println("Context对象删除了属性");
    
        }
    
        @Override
        public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
            System.out.println("Context对象替换了属性");
    
        }
    }
3.监听session内的对象

即监听添加进session的对象

实现HttpSessionBindingListener接口,JavaBean 对象可以感知自己被绑定到 Session 中和从 Session 中删除的事件【和HttpSessionAttributeListener的作用是差不多的】
实现HttpSessionActivationListener接口,JavaBean 对象可以感知自己被活化和钝化的事件(当服务器关闭时,会将Session的内容保存在硬盘上【钝化】,当服务器开启时,会将Session的内容在硬盘式重新加载【活化】)

测试:监听session的钝化和活化

  1. 修改tomcat的配置,META-INF下的context.xml
<Context>
  <Manager className="org.apache.catalina.session.PersistentManager" maxIdleSwap="1">
  <Store className="org.apache.catalina.session.FileStore" directory="zhongfucheng"/>
  </Manager>
</Context>
  1. User既是监听器又是事件源
/*
* 由于涉及到了将内存的Session钝化到硬盘和用硬盘活化到内存中,所以需要实现Serializable接口
*
* 该监听器是不需要在web.xml文件中配置的。但监听器要在事件源上实现接口
* 也就是说,直接用一个类实现HttpSessionBindingListener和HttpSessionActivationListener接口是监听不到Session内对象的变化的。
* 因为它们是感知自己在Session中的变化!
* */
public class User implements HttpSessionBindingListener,HttpSessionActivationListener,Serializable {

    private String username ;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }


    @Override
    public void sessionWillPassivate(HttpSessionEvent httpSessionEvent) {

        HttpSession httpSession = httpSessionEvent.getSession();

        System.out.println("钝化了");

    }

    @Override
    public void sessionDidActivate(HttpSessionEvent httpSessionEvent) {
        HttpSession httpSession = httpSessionEvent.getSession();
        System.out.println("活化了");

    }
    @Override
    public void valueBound(HttpSessionBindingEvent httpSessionBindingEvent) {

        System.out.println("绑定了对象");
    }
    @Override
    public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("解除了对象");

    }
}
  1. 测试代码
        User user = new User();
        request.getSession().setAttribute("aaa", user);
        request.getSession().removeAttribute("aaa");
vent) {

        System.out.println("绑定了对象");
    }
    @Override
    public void valueUnbound(HttpSessionBindingEvent httpSessionBindingEvent) {
        System.out.println("解除了对象");

    }
}
  1. 测试代码
        User user = new User();
        request.getSession().setAttribute("aaa", user);
        request.getSession().removeAttribute("aaa");
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值