美文网首页
JavaEE学习day-54:监听器和过滤器

JavaEE学习day-54:监听器和过滤器

作者: 开源oo柒 | 来源:发表于2019-09-28 22:49 被阅读0次

    一、监听器的使用

    1.监听器的介绍:

    Servlet 监听器是 Servlet 规范中定义的一种特殊类,用于监听 ServletContext、HttpSession 和 ServletRequest 等域对象的创建与销毁事件,以及监听这些域对象中属性发生修改的事件。

    • 作用:

    监听request、session、application三个域对象的创建,销毁和数据的变更(添加、修改和删除)。

    2.监听器的使用:

    • 监听session对象的使用:

    实现接口:
    javax.servlet.http.HttpSessionAttributeListener;
    javax.servlet.http.HttpSessionListener;
    接口中的方法:
    (1)监听session的创建和销毁:HttpSessionListener:
    SessionCreated(HttpSessionEvent se);
    sessionDestroyed(HttpSessionEvent se);
    (2)监听session的作用域数据的变更:
    AttributeAdded(Http SessionBindingEvent event);
    attributeRemoved(HttpSessionBindingEvent event);
    attributeReplaced(HttpSessionBindingEvent event);

    • 监听Request对象的使用:

    实现接口:
    javax.servlet.ServletRequestListener;
    javax.servlet.ServletRequestAttributeListener;
    接口中的方法:
    (1)监听Request的创建和销毁:
    requestInitialized(ServletRequestEvent sre);
    requestDestroyed(ServletRequestEvent sre);
    (2)监听Request的作用域数据的变更:
    attributeAdded(ServletRequestAttributeEvent srae);
    attributeRemoved(ServletRequestAttributeEvent srae);
    attributeReplaced(ServletRequestAttributeEvent srae);

    • 监听Application对象的使用:

    实现接口:
    javax.servlet.http.HttpSessionAttributeListener;
    javax.servlet.ServletContextListener;
    接口中的方法:
    (1)监听application对象的创建和销毁:
    contextInitialized(ServletContextEvent sce);
    contextDestroyed(ServletContextEvent sce);
    (2)监听application对象的数据的变更:
    attributeAdded(ServletContextAttributeEvent event);
    attributeRemoved(ServletContextAttributeEvent event);
    attributeReplaced(ServletContextAttributeEvent event);

    3.案例在线人数的统计:

    • 实现思路:

    定义一个计数器;每当session创建时计数器就加1;session被销毁时计数器就-1。

    • 在原项目中创建监听器:
    package com.zlw.listener;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    import javax.servlet.http.HttpSessionEvent;
    import javax.servlet.http.HttpSessionListener;
    
    public class MyListener implements HttpSessionListener,ServletContextListener{
    
        //监听Context对象
        @Override
        public void contextInitialized(ServletContextEvent sce) {
            int count = 0;
            //获取Application对象
            ServletContext sc = sce.getServletContext();
            sc.setAttribute("count", count);
        }
        @Override
        public void contextDestroyed(ServletContextEvent sce) {
            
        }
        //监听session对象
        @Override
        public void sessionCreated(HttpSessionEvent se) {
            //获取Application对象中的计数器
            ServletContext sc = se.getSession().getServletContext();
            int count = (int)sc.getAttribute("count");
            //计数器自增
            ++count;
            //然后将计数器存储到application中
            sc.setAttribute("count", count);
        }
    
        @Override
        public void sessionDestroyed(HttpSessionEvent se) {
            //获取Application对象中的计数器
            ServletContext sc = se.getSession().getServletContext();
            int count = (int) sc.getAttribute("count");
            //计数器自减
            --count;
            //然后再将计数器存储到Application中
            sc.setAttribute("count",count);
        }
    }
    
    • web.xml文件配置:
    !-- 监听器的配置 -->
      <listener>
      <listener-class>com.zlw.listener.MyListener</listener-class>
      </listener>
    
    • 增加效果:


      效果

    二、过滤器的使用

    1.问题:

    Servlet 的作用是针对浏览器发起的请求,进行请求的处理。通过 Servlet 技术我们可以灵活的进行请求的处理,但是我们不但要对请求记性处理,我们还需对服务器的资源进行统一的管理 ,比如请求编码格式的统一设置,资源的统一分配等等。


    原理图

    2.过滤器的作用:

    过滤器可以拦截所有的请求;可以添加多个过滤,考虑性能一般不会添加过多过滤器;是由服务器创建的。
    可以用来限制访问的权限;
    过滤敏感的关键字;
    解决乱码问题。

    3.创建过滤器和实现方法:

    • 接口:

    javax.servlet.Filter;

    • 实现方法:

    init方法:服务器启动时调用;
    doFilter方法;进行业务处理。
    destory方法:服务器关闭时调用;

    • doFilter方法的作用:

    服务器在接收到浏览器发过来的请求后,先解析请求信息,创建对象request和response然后根据请求URL地址判断如果符合过滤器的过滤范围,则会调用过滤器中的doFilter来进行请求拦截,并将request和response对象作为实参传递给doFilter方法。我们可以在doFilter方法中声明过滤器拦截代码。

    • doFilter中的参数:

    ServletRequest:接收此次拦截的请求的request实参
    ServletResponse:接收此次拦截的请求的response实参
    FilterChain:可以进行请求放行

    • 过滤器拦截的范围:

    拦截所有:/*
    拦截部分Servlet的请求:*.do
    拦截指定Servlet的请求:和要拦截的指定的Servlet的url-pattern配置完全一致即可,例如:/my。
    注意:过滤器之间会出现多重拦截,如果是按照拦截拦截范围的大小在web.xml中自大而小进行的配置,则会先执行大范围的拦截器,再执行小范围的拦截器。

    • web.xml文件配置:

    <filter>
    <filter-name>配置的过滤器名称</filter-name>
    <filter-class>要配置的过滤器的全限定路径:包名.类名</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>配置的过滤器名称</filter-name>
    <url-pattern>过滤器拦截请求地址的范围</url-pattern>
    </filter-mapping>

    • 代码示例:
    package com.zlw.filter;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    public class MyFilter implements Filter{
    
        @Override
        public void destroy() {
            System.out.println("MyFilter过滤器被销毁!");
            
        }
        //
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            System.out.println("MyFilter.doFilter(我是过滤器MyFilter:佩奇小区门口的保安)");
            //放行
            chain.doFilter(request, response);
            System.out.println("(*^_^*)");
        }
    
        @Override
        public void init(FilterConfig filterconfig) throws ServletException {
            System.out.println("创建了MyFilter过滤器");
        }
    }
    
    package com.zlw.filter;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    public class MyFilter2 implements Filter {
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            System.out.println("MyFilter2.doFilter(我是佩奇家楼门口的保安!)");
            chain.doFilter(request, response);
        }
        @Override
        public void destroy() {
            // TODO Auto-generated method stub  
        }
    }
    
    package com.zlw.filter;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    public class MyFilter3 implements Filter {
        //创建
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            // TODO Auto-generated method stub
            
        }
        //操作
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            System.out.println("MyFilter3.doFilter(我是佩奇家门口的保安!)");
            chain.doFilter(request, response);
        }
        //销毁
        @Override
        public void destroy() {
            // TODO Auto-generated method stub  
        }
    }
    
    package com.zlw.serlvet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class MySerlvet extends HttpServlet {
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            System.out.println("MyServlet.service(小猪佩奇家被访问了!)");
        }
    }
    
      <!--过滤器配置  :拦截所有-->
      <filter>
        <filter-name>myFilter</filter-name>
        <filter-class>com.zlw.filter.MyFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>myFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
      <!--过滤器配置:拦截部分  -->
      <filter>
        <filter-name>myFilter2</filter-name>
        <filter-class>com.zlw.filter.MyFilter2</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>myFilter2</filter-name>
        <url-pattern>*.do</url-pattern>
      </filter-mapping>
      <!--过滤器配置:拦截指定的Servlet的请求  -->
      <filter>
        <filter-name>myFilter3</filter-name>
        <filter-class>com.zlw.filter.MyFilter3</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>myFilter3</filter-name>
        <url-pattern>/my.do</url-pattern>
      </filter-mapping>
    
    • 结果: 结果

    4.解决乱码问题:

    • 分析图:
    • 解决Post方式提交的乱码问题:

    request.setCharacterEncoding("utf-8");

    • 解决Get方式提交乱码问题:

    String userName = request.getParamenter(" ");
    String str = new String (userName.getBytes("ios-8859-1"),utf-8);

    • 代码示例:
    package com.zlw.filter;
    
    import java.io.IOException;
    
    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.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class EncodingFilter implements Filter{
        private String encoding;
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            encoding = filterConfig.getInitParameter("encoding");//获取配置文件中参数的值
            System.out.println(encoding);
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest)request;
            HttpServletResponse resp = (HttpServletResponse)response;
    //      req.setCharacterEncoding("utf-8");
    //      resp.setContentType("text/html;charset=utf-8");
            req.setCharacterEncoding(encoding);
            resp.setContentType("text/html;charset="+encoding);
            chain.doFilter(request, response);//将请求继续向下传递
        }
    
        @Override
        public void destroy() {
            // TODO Auto-generated method stub
        }
    }
    
    • Serlvet
    package com.zlw.serlvet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class LoginServlet extends HttpServlet {
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
            //获取用户输入的用户名和密码
            String userName = request.getParameter("userName");
            String userPass = request.getParameter("userPass");
            //如何处理地址栏传参或get提交的乱码问题
            userName = new String (userName.getBytes("iso-8859-1"));
            System.out.println(userName+"---"+userPass);
            if(("admin".equals(userName)&&"admin".equals(userPass))||("张三".equals(userName)&&"admin".equals(userPass))){
                request.getSession().setAttribute("userName", userName);
                response.sendRedirect("index.jsp");
            }else{
                response.sendRedirect("login.jsp");
            }
        }
    }
    
    • jsp页面
    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
      
      </head>
      <body>
        <h3 style="color: red">登录成功</h3>
      </body>
    </html>
    
    <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>
    <%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    %>
    
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
      <head>
        <base href="<%=basePath%>">
        
        <title>测试乱码解决</title>
        
      </head>
      
      <body>
      <form action="login"method="get">
       用户名:<input type="text" name="userName" />
        密码:<input type="password" name="passName" />
        <input type="submit" value="登录" />
        </form>
      </body>
    </html>
    
    • web.xml文件配置:
    <filter>
        <filter-name>EncodingFilter</filter-name>
        <filter-class>com.zlw.filter.EncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
      </filter>
        <filter-mapping>
         <filter-name>EncodingFilter</filter-name>
         <url-pattern>/*</url-pattern>
      </filter-mapping>
    

    三、项目权限管理功能

    1.需求:

    不同的用户在对同一功能使用时,有的用户可以直接使用,有的用户会被提示权限不足。

    1.功能实现思路:

    (1)在数据库中创建一个URL权限表,该表存储了该系统需要被管理的URL。
    (2)在数据库中创建用户权限中间表,用来进行权限分配。
    (3)在数据库中将权限给用户分配好。
    (5)在用户登录成功后查询该用户具备的URL权限,存储到该用户的session中。
    (6)在过滤器中对当前发起请求的用户的请求地址进行校验,校验该用户是否具备该请求地址的权限,如果具备则放行执行,如果不具备则提示权限不足。

    2.数据库创建:

    URL权限表:t_url
    编号: urlid
    url地址 :location
    描述:remark

    用户权限中间表:t_user_url
    uid
    urlid
    SQL语句的设计:查询当前登录用户的url信息
    子查询:
    select * from t_url where urlid in (select urlid from t_user_url where uid=?)
    联合查询:
    select * from t_url tu,t_user_url tul where tu.urlid=tul.urlid and tul.uid=?)

    3.JDBC操作数据库:

    //查询当前用户的URL权限信息
        @Override
        public List<Url>getUserUrlInfoDao(int uid){
            //声明jdbc变量
            Connection conn = null;
            PreparedStatement ps = null;
            ResultSet rs = null;
            //声明变量
            String sql = "select * from t_url where urlid in (select urlid from t_user_url where uid=?)";
            List<Url> lu = null;
            
            try {
                conn = DBUtil.getConnection();
                ps = conn.prepareStatement(sql);
                ps.setInt(1, uid);
                rs = ps.executeQuery();
                lu = new ArrayList<Url>();
                while(rs.next()){
                    Url ul = new Url();
                    ul.setUrlid(rs.getInt("urlid"));
                    ul.setLocation(rs.getString("location"));
                    ul.setRemark(rs.getString("remark"));
                    lu.add(ul);
                }
            } catch (SQLException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return lu;
            
        }
    

    4.Filter监听器:

    package com.zlw.filter;
    
    import java.io.IOException;
    import java.util.List;
    
    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.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    import com.zlw.pojo.Url;
    /**
     * * Filter案例之统一编码格式:
     *      在doFilter中使用
     *              //设置请求编码格式
    *                   request.setCharacterEncoding("utf-8");
    *               //设置响应编码格式
    *                   response.setContentType("text/html;charset=utf-8");
    *   Filter案例之session管理
    *           在过滤器中获取session对象,然后查看session中的数据是否还在
    *           如果数据没了,则因为session失效则重定向到登录页面。如果数据还在
    *           session没有失效,则放行
    *           
    *           问题1:
    *               在过滤器中使用session校验后发现登录页面的访问成了死循环,因为登录页面的
    *               请求也就是login.jsp的请求也会被过滤器拦截,而此时session中没有相关数据的
    *               造成又重定向到登录页面......
    *           解决1:
    *               对login.jsp和登录请求进行放行
    *           问题2:
    *               过滤器会拦截所有的请求,包括静态资源(css文件\js文件\image图片)请求也会拦截。
    *               造成页面中的样式和动态效果等出不来
    *           解决2:
    *               对静态资源放行
                        
     *  @author zhang
     *
     */
    public class MyFilter implements Filter {
    
        @Override
        public void destroy() {
            // TODO Auto-generated method stub
    
        }
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            //设置请求编码格式
            request.setCharacterEncoding("utf-8");
            //设置响应编码格式
            response.setContentType("text/html;charset=utf-8");
    //      chain.doFilter(request, response);
            //强转Request对象
            HttpServletRequest req = ((HttpServletRequest)request);
            //强转response对象
            HttpServletResponse resp = ((HttpServletResponse)response);
            //获取此次请求的uri
            String uri = req.getRequestURI();
            //获取此次请求的method
            String method = req.getParameter("method");
            System.out.println("当前请求的method"+method);
            System.out.println("当前请求的uri为:"+uri);
            if("/project2/login.jsp".equals(uri)||"/project2/reg.jsp".equals(uri)||("/project2/data".equals(uri))&&"userLogin".equals(method)||uri.startsWith("/project2/css/")||uri.startsWith("/project3/js/")||uri.startsWith("/project2/images/")){
                
                //放行
                chain.doFilter(request, response);
                
            }else{
                
                //获取session对象
                HttpSession session = req.getSession();
                Object obj = session.getAttribute("user");
                //判断
                if(obj!=null){
                    //获取权限信息
                        List<Url> li = (List<Url>)session.getAttribute("lu");
                        //权限校验
                        for (Url url : li) {
                            if(url.getLocation().equals(method)||url.getLocation().equals(uri)){
                                //放行
                                chain.doFilter(request, response);
                                return;
                            }
                        }
                    //响应
                        resp.getWriter().write("power");
                        return;
                }else{
                    //重定向到登录页面
                    resp.sendRedirect("/project2/login.jsp");
                }
            }
        }
    
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            // TODO Auto-generated method stub
        }
    }
    
    • web.xml文件配置:
    <!-- 监听器的配置 -->
      <listener>
      <listener-class>com.zlw.listener.MyListener</listener-class>
      </listener>
    
    张三登录 李四登录

    相关文章

      网友评论

          本文标题:JavaEE学习day-54:监听器和过滤器

          本文链接:https://www.haomeiwen.com/subject/dpinuctx.html