javaEE(Listener监听器和Filter过滤器)

Listener监听器

javaweb监听器介绍

       1.监听web对象创建与销毁的监听器

                            ServletContextListener

                            HttpSessionListener

                            ServletRequestListener 

2.监听web对象属性变化

                            ServletContextAttributeListener

                            HttpSessionAttributeListener

                            ServletRequestAttributeListener  

3.监听session绑定javaBean

                            HttpSessionBindingListener

                            HttpSessionActivationListener

1.    javaweb监听器创建步骤

Ø  创建一个类,实现指定的监听器接口     

Ø  重写接口中的方法.

Ø  在web.xml文件中配置监听


监听对象创建销毁

ServletContextListener在系统启动时,调用contextInitialized()方法

HttpSessionListener在访问jsp页面或者servlet创建session时候,调用sessionCreated()

session时间到了,或者invalidate()时候,调用sessionDestroyed()

ServletRequestListener在访问页面的时候,调用requestInitialized();

监听对象属性变化

ServletRequestAttributeListener在添加属性的时候调用(注意第一次添加后会调用替换方法,因为request自动加了一些属性)

监听session绑定和活化.钝化

HttpSessionBindingListener绑定在javaBean上,如果此对象绑定了HttpSessions就会调用绑定方法(不需要xml配置,因为他不虚启动)

案列:定时销毁Session(可以直接设置session存留时间,这个案例是定时调度Timer的教程)

1.创建HttpSessionListener,当session对象创建时,就将这个session对象装入一个集合中

2.将List<HttpSession>保存到ServletContext域中。

3.HttpSession中有一个方法getLastAccessedTime();他可以获得session对象最后使用的时间。

4.使用invalidate方法销毁

创建实现ServletContextListener接口

public class MyServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext对象创建了");
        ServletContext context = servletContextEvent.getServletContext();
        //创建一个集合用于存储所有的session对象 注意:需要加锁,并发的创建session添加时候,会有问题
        List<HttpSession> sessions = Collections.synchronizedList(new ArrayList<HttpSession>());
        //把集合放到application域中
        context.setAttribute("sessions",sessions);
        //服务器启动就执行此方法,所以在这里加上计时器对象
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                //Iterator和listIterator都可以删除,区别在于listIterator可以倒序遍历,可以添加元素,而Iterator不能
                ListIterator<HttpSession> iterator = sessions.listIterator();
                while (iterator.hasNext()){
                    HttpSession next = iterator.next();
                    long l = next.getLastAccessedTime();
                    if(System.currentTimeMillis()-l>5000){//如果时间大于5秒,把session销毁
                        next.invalidate();//使之无效
                        iterator.remove();
                    }
                }
            }
        },5000,5000);//延迟2秒后执行,每间隔5秒执行一次
    }
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("ServletContext对象删除了");
    }
}
创建实现HttpSessionListener接口

public class ServletSessionListener implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        //得到当前创建的session
        HttpSession session = httpSessionEvent.getSession();
        //得到application对象中的list集合,session中有getServletContext()方法
        ServletContext application = session.getServletContext();
        List<HttpSession> sessions = (List<HttpSession>) application.getAttribute("sessions");
        //把当前创建的session对象添加到集合中
        boolean add = sessions.add(session);
        System.out.println(session.getId()+"  :   "+(add==true?"添加成功":"添加失败"));
    }
    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        System.out.println("session销毁了");
    }
}
并且在xml配置信息

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
<listener>
    <listener-class>com.mck.entity.MyServletContextListener</listener-class>
</listener>
<listener>
    <listener-class>com.mck.entity.ServletSessionListener</listener-class>
</listener>
</web-app>



Filter过滤器(重要)

很多地方使用,比如验证是否登录,统一的编码设置,加密设置等。
快速入门:
1.创建一个类实现Filter接口
2.重写接口中的方法,doFiter方法是否真正过滤的
3.在web.xml文件中配置
注意:1.在Fiter的doFilter方法内如果没有执行chain.doFiter(request.response)那么资源是不会被访问到的。(需要放行)
2.在chain.doFiter()方法后,可以定义后面的操作(放行后又回到filter执行chain.dofilter后面的方法)
3.FilterChain过滤器链

如果有相同的过滤器拦截了某一个请求,则FilterChain会调用下一个过滤器

调用循序是xml的<filter-mapping>摆放的上下顺序!!(方法回执,先里面后外面)

Filter生命周期

Servlet生命周期:

实例化》》初始化》》服务》》销毁

当服务器启动,会创建filter对象,并调用init方法,只调用一次

当访问资源时,路径与filter的拦截路径匹配时,会执行filter中的doFilter,这个方法是真正拦截操作的方法

当服务器关闭时,会调用filter的destroy方法来进行销毁


FilterConfig类

用于获取filter初试化的参数


Filter实战(通过拦截器解决doGet提交和doPost提交乱码问题)

dopost方式通过拦截器

设置req.setContextType("text/html;charset=utf-8")

chain放行后,所有被拦截的servletl类都被设置了

doget方式通过包装设计模式(包装设计模式可以理解方法套一层皮,核心是改不了的,但是可以加额外的功能,如设置编码)

先了解两种模式

包装设计模式:1.实现被包装类相同的接口,2.被包装类作为参数传递包装类中(通过构造器),3.对需要重写的方法改动,不需要重写的,原样调用即可

适配器设计模式:适配器实现原理同上,区别在于,适配器实现接口所有的方法,需要重写方法直接调用即可。

思路:

1.通过拦截器得到HttpServletRequest

2.创建一个Myrequest类继承HttpServletRequestWrapper类(按照包装设计模式来说,应该实现HttpServletRequest接口,确实是,但是实现接口后发现,你只需要改动一个方法,但是却需要实现100多个其它方法,很麻烦,所以继承HttpServletRequestWrapper,这个类帮你实现了HttpServletRequest接口,并且没有改动方法,你只需要把需要改动的方法重写即可,这就是适配器模式(适配这个字就很方便,哈哈))

3.代码贴上来(包装类MyRequest)

public class MyRequest extends HttpServletRequestWrapper {
    HttpServletRequest request;
    public MyRequest(HttpServletRequest request){
        //HttpServletRequestWrapper适配器模式需要一个对象,原理和包装类一样
        //区别在于适配器模式把传递的对象接口的方法全部给实现了,不需要重新实现接口中方法,并且,需要那个方法,就单独调用重写那个方法
        super(request);
        this.request=request;
    }
    //重写方法
    public String getParameter(String name) {
        Map<String, String[]> map = getParameterMap();
        return map.get(name)[0];
    }
    //重写方法
    public String[] getParameterValues(String name) {
        Map<String, String[]> map = getParameterMap();
        return map.get(name);
    }
    //防止多次执行后又乱码了。
    private  boolean flag=true;
    //源头
    public Map<String, String[]> getParameterMap() {
        Map<String, String[]> map = request.getParameterMap();//调用传递过来的request参数的getParameterMap()方法
        if(flag) {//防止多次执行乱码,多次调用getParameter或者别的方法,就会坏变好变坏
            for (Map.Entry<String, String[]> e : map.entrySet()) {
                String[] value = e.getValue();//注意这里是引用类型 value指向实际堆内存地址改动可变
                for (int i = 0; i < value.length; i++) {
                    try {
                        value[i] = new String(value[i].getBytes("iso-8859-1"), "UTF-8");//转码
                    } catch (UnsupportedEncodingException e1) {
                        e1.printStackTrace();
                    }
                }
            }
            flag=false;
        }
        return map;
    }
}
4.再Filter中把request传递到MyRequest中,传递给其他页面,这时候其他页面就用的是包装类型,而不是原有的request


好了就这么多,跟黑马老师课程来的,觉得好就记录在网上供大家分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值