过滤器和监听器

次要内容

过滤器

介绍

Filter 即为过滤,用于在 Servlet 之外对 Request 或者 Response 进行批改。它次要用于对用户申请进行预处理,也能够对 HttpServletResponse 进行后处理。应用 Filter 的残缺流程: Filter 对用户申请进行预处理,接着将申请交给 Servlet 进行解决并生成响应,最初 Filter 再 对服务器响应进行后处理。在一个 web 利用中,能够开发编写多个 Filter,这些 Filter 组合 起来称之为一个 Filter 链。

单个过滤器

多个过滤器

若是一个过滤器链:先配置先执行(申请时的执行程序);响应时: 以相同的程序执行。

在 HttpServletRequest 达到 Servlet 之前,拦挡客户的 HttpServletRequest 。依据须要查看HttpServletRequest,也能够批改 HttpServletRequest 头和数据。

在HttpServletResponse 达到客户端之前,拦挡 HttpServletResponse。依据须要查看 HttpServletResponse,也能够批改 HttpServletResponse头和数据。

实现

能够通过实现一个叫做javax.servlet.Fileter的接口来实现一个过滤器,其中定义了 三个办法,init(), doFilter(), destroy()别离在相应的机会执行。前期察看生命周期。

Filter 的实现只须要两步:

Step1: 编写 java 类实现 Filter 接口,并实现其 doFilter 办法。

Step2: 通过@WebFilter注解设置它所能拦挡的资源。

@WebFilter("/*")public class Filter01 implements Filter {    @Override    public void init(FilterConfig filterConfig) throws ServletException {    }    @Override    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {    }    @Override    public void destroy() {    }} 

Filter 接口中有一个 doFilter 办法,当开发人员编写好 Filter,并配置对哪个 web 资源进行拦挡后,Web 服务器每次在调用 web 资源的 service 办法之前,都会先调用一下 filter 的 doFilter 办法。因而能够达到如下成果:

调用指标资源之前,让一段代码执行。

是否调用指标资源(即是否让用户拜访 web 资源)。

web 服务器在调用 doFilter 办法时,会传递一个 filterChain 对象进来,filterChain 对象是 filter 接口中最重要的一个对象,它提供了一个 doFilter 办法,开发人员能够依据需要决定 是否调用此办法,调用该办法,则 web 服务器就会调用 web 资源的 service 办法,即 web 资源就会被拜访,否则 web 资源不会被拜访。(实质是放行,调用doFilter办法后,即申请能够达到资源)

实例

申请乱码解决
/** * 字符乱码解决 *     乱码状况:                     Tomcat8及以上版本                            Tomcat7及以下版本                                      POST申请        乱码,须要解决                                乱码,须要解决                     request.setCharacterEncoding("UTF-8");                                  GET申请                     不会乱码,不须要解决                            乱码,须要解决             new String(request.getParameter("参数名").getBytes("ISO-8859-1"),"UTF-8");                           如何解决:             1、解决POST申请                 request.setCharacterEncoding("UTF-8");             2、解决GET申请且服务器版本在Tomcat8以下的                 1> 失去申请类型 (GET申请)                 2> 失去服务器的版本的信息                 3> 判断是GET申请且Tomcat版本小于8                 4> 解决乱码                   new String(request.getParameter("参数名").getBytes("ISO-8859-1"),"UTF-8");         */@WebFilter("/*")public class AEncodingFilter implements Filter {        public AEncodingFilter() {    }    public void destroy() {            }    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain) throws IOException, ServletException {        // 基于HTTP        HttpServletRequest request = (HttpServletRequest) arg0;        HttpServletResponse response = (HttpServletResponse) arg1;                // 解决申请乱码乱码 (解决POST申请)        request.setCharacterEncoding("UTF-8");                    // 解决GET申请且服务器版本在Tomcat8以下的        String method = request.getMethod();        // 如果是GET申请        if ("GET".equalsIgnoreCase(method)) {            // 服务器版本在Tomcat8以下的 Apache Tomcat/8.0.45            String serverInfo = request.getServletContext().getServerInfo();                         // 失去具体的版本号            String versionStr = serverInfo.substring(serverInfo.indexOf("/")+1, serverInfo.indexOf("."));            // 判断服务器版本是否小于8            if (Integer.parseInt(versionStr) < 8) {                // 失去自定义外部类  (MyWapper继承了HttpServletRequestWapper对象,而HttpServletRequestWapper对象实现了HttpServletRequest接口,所以MyWapper的实质也是request对象)                HttpServletRequest myRequest = new MyWapper(request);                // 放行资源                chain.doFilter(myRequest, response);                return;            }        }                // 放行资源        chain.doFilter(request, response);            }    public void init(FilterConfig fConfig) throws ServletException {            }            /**     * 定义外部类,继承HttpServletRequestWrapper包装类对象,重写getParameter()办法     */    class MyWapper extends HttpServletRequestWrapper {                // 定义成员变量,晋升结构器 中的request对象的范畴        private HttpServletRequest request;        public MyWapper(HttpServletRequest request) {            super(request);            this.request = request;        }        /**         * 重写getParameter()办法         */        @Override        public String getParameter(String name) {            String value = request.getParameter(name);                        if (value != null && !"".equals(value.trim())) {                try {                    // 将默认ISO-8859-1编码的字符转换成UTF-8                    value = new String(value.getBytes("ISO-8859-1"),"UTF-8");                } catch (UnsupportedEncodingException e) {                    e.printStackTrace();                }            }            return value;        }    }} 
用户非法拜访拦挡
/** * 非法拜访拦挡(当用户未登录时,拦挡申请到登录页面) *         拦挡的资源: *             拦挡所有资源  /* *         须要被放行的资源: *             不须要登录即可拜访的资源 *             1、放行指定页面,不须要登录能够拜访的页面 (例如:登录页面、注册页面等) *             2、放行动态资源(例如:css、js、image等资源) *             3、放行指定操作,不须要登录即可执行的操作(例如:登录操作、注册操作等) *             4、登录状态放行 (如果存在指定sessuin对象,则为登录状态) */    @WebFilter("/*")public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain chain) throws IOException, ServletException {                // 基于HTTP        HttpServletRequest request = (HttpServletRequest) arg0;        HttpServletResponse response = (HttpServletResponse) arg1;        // 失去申请的门路        String path = request.getRequestURI(); //     站点名/资源门路            // 1、放行指定页面,不须要登录能够拜访的页面 (例如:登录页面、注册页面等)        if (path.contains("/login.jsp") || path.contains("/register.jsp")) {             chain.doFilter(request, response);             return;        }        // 2、放行动态资源(例如:css、js、image等资源)        if (path.contains("/js")) {             chain.doFilter(request, response);             return;        }        // 3、放行指定操作,不须要登录即可执行的操作(例如:登录操作、注册操作等)        if (path.contains("/loginServlet")) {             chain.doFilter(request, response);             return;        }        // 4、登录状态放行 (如果存在指定sessuin对象,则为登录状态)        // 失去session域对象        String uname = (String) request.getSession().getAttribute("user");        // 如果session域对象不为空,则为登录状态,放行资源        if (uname != null && !"".equals(uname.trim())) {            chain.doFilter(request, response);             return;        }                    // 若以上条件均不满足,拦挡跳转到登录页面        response.sendRedirect("login.jsp");        return;    } 

监听器

介绍

web 监听器是Servlet 中一种的非凡的类,能帮忙开发者监听 web 中的特定事件, 比方 ServletContext,HttpSession,ServletRequest 的创立和销毁;变量的创立、销毁和批改等。 能够在某些动作前后减少解决,实现监控。例如能够用来统计在线人数等。

实现

监听器有三类8种:

⑴ 监听生命周期:

ServletRequestListener

HttpSessionListener

ServletContextListener

⑵ 监听值的变动:

ServletRequestAttributeListener

HttpSessionAttributeListener

ServletContextAttributeListener

⑶ 针对 session 中的对象:

监听 session 中的 java 对象(javaBean) ,是 javaBean 间接实现监听器 的接口。

示例

做一个对在线人数的监控。

实现步骤: 

Step1:创立一个监听器,须要实现某种接口,依据需要选取 HttpSessionListener

Step2:通过@WebListener注解配置该监听器

创立一个类,并实现 HttpSessionListener 接口,用来检测 Session 的创立和销毁。

1.在类中定义一个成员变量用来存储以后的 session 个数。(OnlineListener.java)

/** * 在线人数统计 *     当有新的session对象被创立,则在线人数+1; *     有session对象被销毁,在线人数-1; * @author Lisa Li * */@WebListenerpublic class OnlineListener implements HttpSessionListener {        // 默认在线人数    private Integer onlineNumber = 0;    /**     * 当有新的session对象被创立,则在线人数+1;     */    @Override    public void sessionCreated(HttpSessionEvent se) {        // 人数+1        onlineNumber++;        // 将人数存到session作用域中        // se.getSession().setAttribute("onlineNumber", onlineNumber);        // 将人数存到application作用域中        se.getSession().getServletContext().setAttribute("onlineNumber", onlineNumber);    }    /**     * 有session对象被销毁,在线人数-1;     */    @Override    public void sessionDestroyed(HttpSessionEvent se) {        // 人数-1        onlineNumber--;        // 将人数存到session作用域中        // se.getSession().setAttribute("onlineNumber", onlineNumber);        // 将人数存到application作用域中        se.getSession().getServletContext().setAttribute("onlineNumber", onlineNumber);    }} 

2.做一个测试的 Servlet 用来登录,和显示以后在线人数。(OnlineServlet.java)

/** * 在线人数统计 */public class OnlineServlet extends HttpServlet {    private static final long serialVersionUID = 1L;        protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {                // 失去参数        String key = request.getParameter("key");                // 判断是否为空 (不为空,且值为logout则为退出操作)        if (key != null && "logout".equals(key)) {            // 传递了参数,示意要做用户退出操作            request.getSession().invalidate();            return;        }                    // 创立session对象        HttpSession session = request.getSession();        // 获取sessio作用域中的在线人数        Integer onlineNumber = (Integer) session.getServletContext().getAttribute("onlineNumber");                                // 输入        response.setContentType("text/html;charset=UTF-8");        response.getWriter().write("<h2>在线人数:"+onlineNumber+"</h2><h4><a href='online?key=logout'>退出</a><h4>");            }} 

equest.getSession();
// 获取sessio作用域中的在线人数
Integer onlineNumber = (Integer) session.getServletContext().getAttribute(“onlineNumber”);

 // 输入    response.setContentType("text/html;charset=UTF-8");    response.getWriter().write("<h2>在线人数:"+onlineNumber+"</h2><h4><a href='online?key=logout'>退出</a><h4>");    } 

}