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

来源:互联网 发布:配电网络规划与设计 编辑:程序博客网 时间:2024/05/02 21:05

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


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

原创粉丝点击