欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

过滤器和监听器

程序员文章站 2022-04-10 14:56:38
...

过滤器

1.Servlet最激动人心三大技术:Servlet,Filter,Listener

2.过滤器(Filter):Servlet三大技术之一,在服务器可以管理所有web资源,本质特殊java类.
WEB开发人员通过Filter技术,对web服务器管理 的所有web资源:例如Jsp, Servlet, 静态图片文件或静态html文件等进行拦截,从而实现一些特殊 的功能。
过滤器的作用:实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功 能。

3.过滤器工作原理:
过滤器和监听器

4.手动写过滤类:
4.1:先创建一个Java类,实现javax.servlet.Filter接口;
4.2:实现接口中init(),doFilter(),destroy();
4.3:在web.xml中注册过滤器
注意:配置版的过滤器在过滤器链中顺序由注册顺序.

		eg:<!--注册过滤器-->
<filter>
    <filter-name>FirstFilter</filter-name><!--过滤器注册名-->
    <filter-class>com.qf.day46.filter.FirstFilter</filter-class><!--过滤器全限制类名:包名+类名-->
</filter>
<!--配置过滤过滤请求的路径-->
<filter-mapping>
    <filter-name>FirstFilter</filter-name><!--过滤器的注册名,与上面注册名相同-->
    <url-pattern>/*</url-pattern><!--过滤所有请求-->
</filter-mapping>


//等同于用注解在类名上注册

@WebFilter(filterName = “SecondFilter”,value = “/")//配置注册信息和映射请求
简写为:@WebFilter("/
”)

注意:注解版的过滤器在过滤器链中顺序由注册过滤器名称决定.

5.过滤器的生命周期:当项目发布时,由服务器容器调用构造方法,实例化过滤器,再由服务器容器通过过滤实例调用init()初始过滤器,当客户端发送请求到服务器时,由服务器容器通过过滤器实例调用doFilter方法,再将请求传到Servlet中处理,Servlet处理完请求响应信息,由服务器容器通过过滤器实例调用doFilter方法,再将响应信息传到客户端.当web项目停止发布时就调由服务器容器通过过滤器实例调用destroy()销毁过滤器实例.
(与web项目同生共死)

6.Servlet3.0之后,注解的过滤器:在过滤类上面配置注解@WebFilter,可配置属性
过滤器和监听器

7.字符编码过滤器:
原来实现:请求和响应对象是在Servlet中处理编码
现在实现:在过滤器中处理编码,将处理好编码的请求和响应对象传Servlet中,Servlet就 不会再处理编码
实现思路:声明一个字符编码过滤器,在过滤器中将响应的编码和请求编码提前编码后,后 面在将请求和响应对象传Servlet中就不用处理编码.注意,因为get请求的 编码无法统一在类中设置,所以就想重写获得请求中数据的方法.因为要重 写获得请求中数据的方法,所以请求对象要用装饰都模式.

	eg:/**
 * 字符编码过滤器
 */
@WebFilter("/*")
public class EncoddingFilter implements Filter {
    public void init(FilterConfig config) throws ServletException {

    }
    public void destroy() {
    }

    /**
     * 过滤方法
     * @param request
     * @param response
     * @param chain
     */
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
        //统一处理响应编码
        response.setCharacterEncoding("utf-8");
        /*处理请求编码*/
        //将请求对象转换为HttpServletRequest
        HttpServletRequest request2=(HttpServletRequest)request;
        //获得请求方法类型
        if ("GET".equalsIgnoreCase(request2.getMethod())){
            //创建请求的装饰者对象,将原来的请求对象作为构造方法的参数
            MyRequest mr=new MyRequest(request2);
            chain.doFilter(mr, response);
        }else if("POST".equals(request2.getMethod())){//post请求
            request2.setCharacterEncoding("utf-8");
            chain.doFilter(request2, response);
        }
    }

    /**
     * 装饰者请求类(成员内部类)
     */
    public class MyRequest extends HttpServletRequestWrapper{
        public HttpServletRequest request;

        public MyRequest(HttpServletRequest request) {
            super(request);
            this.request=request;
        }

        /**
         * 重写获得单个请求值的方法
         * @param name
         * @return String
         */
        @Override
        public String getParameter(String name) {
            //获得请求中值
            String value=super.getParameter(name);
            try {
                if(value!=null&&!value.equals("")){
                    //重写编码
                    value=new String(value.getBytes("ISO-8859-1"),"utf-8");

                }
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return value;
        }

        /**
         * 重写获得请求中一组数据值的方法
         * @param name
         * @return String
         */
        @Override
        public String[] getParameterValues(String name) {
            //获得请求中一组数据值
            String[] values=super.getParameterValues(name);
            //将数据值一一编码
            if (values!=null||values.length!=0){
                for (int i=0;i<values.length;i++){
                    try {
                        values[i]=new String(values[i].getBytes("ISO-8859-1"),"utf-8");
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }
            }
            return values;
        }

        /**
         * 重写获得请求中所有值的方法
         * @return String
         */
        @Override
        public Map<String, String[]> getParameterMap() {
            Map<String,String[]> hmap1=super.getParameterMap();
            //处理请求中每个数据的编码
            for (String key:hmap1.keySet()){
                //通过key得到value值
                String[] values=hmap1.get(key);
                //将数据值一一编码
                if (values!=null||values.length!=0){
                    for (int i=0;i<values.length;i++){
                        try {
                            values[i]=new String(values[i].getBytes("ISO-8859-1"),"utf-8");
                        } catch (UnsupportedEncodingException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
            return hmap1;
        }
    }

}

8.权限验证过滤器
原来效果:无论用户是否登录都可以直接访问首页,或其他页面.
实现效果:只有登录过的用户才能访问首页和其他页面,没有登录过的用户,如果直接访问 首页或其他页面,让其3秒跳转到登录页并提示你还没有登录,无法作其他操作.
实现原理:因为每次请求时都要先经过过滤器再经过Servlet,所以就想一个权限验证过滤 器,在这个过滤器中作判断,判断只有登录过的用户才放行调用
chain.doFilter (mr, response);,否则让用户跳转到登录页面.
就超市系统来说:只有登录的页面,登录的请求方法,已经登录过的用户,css,js,img放行

	eg:/**
 * 权限验证过滤器
 */
@WebFilter("/*")
public class AccessFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //将请求和响应对象转换为子类对象
        HttpServletRequest request=(HttpServletRequest) req;
        HttpServletResponse response=(HttpServletResponse)resp;
        //获得session登录的用户信息
        Object ob=request.getSession().getAttribute("u");
        //获得请求的uri
        String uri=request.getRequestURI();
        //获得请求的方法名
        String method=request.getParameter("method");

        //如果是默认起始页,/web_market/login.jsp,登录请求,已经登录过的用户也要放行
        if("/web_market/".equals(uri)||"/web_market/login.jsp".equals(uri)||"login".equals(method)||ob!=null){
            //放行,继续执行请求
            chain.doFilter(request, response);
        }else{//没登录,无法处理后面的请求,就要三秒跳转到登录页面
            //设置响应的内容类型
            response.setContentType("text/html;charset=utf-8");
            response.getWriter().write("你还没有登录,无法进行其他操作,3秒后跳转到登录页面");
            response.setHeader("refresh","3;url=login.jsp");
        }
    }

    public void init(FilterConfig config) throws ServletException {

    }
}

监听器

1.监听器:Servlet的三大技术之一,本质是一种特殊Java类.
作用:监听器用于监听web应用中某些对象
(request,session,application(相当于Servlet中ServletContext对象))、信息的创建、销毁、增加,修改,删除等动作 的发生,然后作出相应的响应处理。
事件监听涉及到三个组件:事件源、事件参数、事件监听器.

2.监听器的分类:
2.1:ServletContextListener接口; ServletContext对象监听器,监听ServletContext对 象创建和销毁.
2.2:ServletContextAttributeListener接口; ServletContext对象的属性监听器,监听 ServletContext对象的属性添加,修改,删除操作
2.3:HttpSessionListener接口;Session对象监听器,监听session对象创建和销毁.
2.4:HttpSessionAttributeListener接口;Session对象的属性监听器,监听session对象 的属性添加,修改,删除操作
2.5:ServletRequestListener接口; Request对象监听器,监听Request对象创建和销毁.
2.6:ServletRequestAttributeListener; Request对象的属性监听器,监听Request对象 的属性添加,修改,删除操作

3.手写监听器
3.1:创建一个Java类,实现监听器接口.
3.2:重写监听器接口中方法.
3.3:在web.xml中注册监听器.

		eg:<!--注册监听器-->
<listener>
    <listener-class>com.qf.day46.listener.FirstLintener</listener-class>
</listener>

4.注解版监听器:在监听器类上面配置@WebListener

5.监听器生命周期:项目发布时就创建监听器实例对象,当监听的对象创建时就调用监听方法, 当监听对象销毁时,就调用监听对象的销毁方法,但监听器实例还在,当项目停止发 布时,就销毁监听器对象.(与web项目同生共死)

6.统计网站访问总量
分析:来了一个客户端,访问总量就加一.
通过session对象判断是否来了客户.
访问总量数据存在全局对象中.

	eg:/**
 * 注解版的监听器
 */
@WebListener
public class SecondListener implements HttpSessionListener{

    public SecondListener() {
        System.out.println("SecondListener实例化方法");
    }

    public void sessionCreated(HttpSessionEvent e) {
        System.out.println("来了一个客户端...");
        //获得全局对象中访问总量
        Object ob=e.getSession().getServletContext().getAttribute("count");
        if (ob==null){//你是第一个访问的客户端
            e.getSession().getServletContext().setAttribute("count",1);
        }else{//不是第一个访问
            //声明一个变量存访问总量
            Integer num=Integer.valueOf(ob.toString())+1;
            e.getSession().getServletContext().setAttribute("count",num);
        }
        System.out.println("当前网站访问总量为:"+e.getSession().getServletContext().getAttribute("count"));
    }

    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("走了一个客户端");
    }
}
		

7.监听器监听属性:

	eg:/**
 * 属性监听器
 */
@WebListener
public class AtrributeListener implements ServletRequestAttributeListener, HttpSessionAttributeListener {


    /**
     * 请求对象中添加属性
     * @param e
     */
    @Override
    public void attributeAdded(ServletRequestAttributeEvent e) {
        System.out.println("向请求对象添加属性名:"+e.getName()+",属性值:"+e.getValue());
    }

    /**
     * 请求对象中删除属性
     * @param e
     */
    @Override
    public void attributeRemoved(ServletRequestAttributeEvent e) {
        System.out.println("删除请求对象中属性为:"+e.getName()+",属性值为:"+e.getValue());
    }

    /**
     * 请求对象中修改属性
     * @param e
     */
    @Override
    public void attributeReplaced(ServletRequestAttributeEvent e) {
        System.out.println("修改请求对象中属性为:"+e.getName()+",属性值为:"+e.getValue());
    }

    /**
     * 会话对象中添加属性
     * @param e
     */
    @Override
    public void attributeAdded(HttpSessionBindingEvent e) {
        System.out.println("向会话对象添加属性名:"+e.getName()+",属性值:"+e.getValue());
    }

    /**
     * 会话对象中删除属性
     * @param e
     */
    @Override
    public void attributeRemoved(HttpSessionBindingEvent e) {
        System.out.println("删除会话对象中属性为:"+e.getName()+",属性值为:"+e.getValue());
    }

    /**
     * 会话对象中修改属性
     * @param e
     */
    @Override
    public void attributeReplaced(HttpSessionBindingEvent e) {
        System.out.println("修改会话对象中属性为:"+e.getName()+",属性值为:"+e.getValue());
    }
}