过滤器-监听器-9

过滤器

1

什么是过滤器
	在生活中有很多跟过滤相关的东西:净水器,空气净化器这些都可以称为过滤器;他们主要的作用就是过滤杂质的。
	在web项目中:当客户端的请求到达服务器的时候,这个请求可以被过滤器拦截下来,过滤器就可以针对这个请求进行一系列过滤操作。最后可以选择是否放行这个请求,如果选择了放行,那么这个请求就可以到达目标资源(servlet html  css 图片等资源),目标资源处理完成后会给客户端响应,这个响应又会经过一次过滤器
过滤器的作用
	一般来说就是用来处理,登录校验,编码处理,处理敏感字符等
	能够统一处理的一般都可以选择交给过滤器处理
	
	类似于进门  与出门

1

过滤器的执行流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BSOEAQet-1681801915116)(servlet.assets/image-20220412105152584.png)]

过滤器的实现

定义一个类,实现Filter接口
实现接口中的方法
配置过滤器:xml配置或注解配置
xml配置

实现乱码处理

package com.zlt.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

public class CharsetFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("init");
    }

    /**
     * 执行过滤的方法
     * @param req
     * @param resp
     * @param chain
     * @throws IOException
     * @throws ServletException
     */
    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        if("get".equalsIgnoreCase(request.getMethod())){
            request = new MyRequest(request);

        } else if("post".equalsIgnoreCase(request.getMethod())){
            request.setCharacterEncoding("UTF-8");
        }
        //放行  方法之前是目标方法之前执行 方法之后是目标方法之后执行  不写这个方法目标方法就不会执行
        chain.doFilter(request,resp);
        System.out.println("after");
    }

    @Override
    public void destroy() {
        System.out.println("destroy");
    }
}

在web.xml中进行配置

<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"
         metadata-complete="false">
  <display-name>Archetype Created Web Application</display-name>
  <filter>
    <filter-name>charset</filter-name>
    <filter-class>com.zlt.filter.CharsetFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>charset</filter-name>
    <!--决定了哪些请求会经过这个过滤器-->
    <url-pattern>/*</url-pattern>
  </filter-mapping>

</web-app>

注解配置

//用户登录校验

package com.zlt.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

@WebFilter(value = "/*",initParams = @WebInitParam(name="uris",value = "/user/update,/user/updateDo"))
public class LoginFilter implements Filter {

    private List<String> uris;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //可以获取初始化参数
        String s = filterConfig.getInitParameter("uris");
        uris = Arrays.asList(s.split(","));
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        String requestURI = req.getRequestURI();//   /userManager/user/update
        requestURI = requestURI.substring(req.getContextPath().length());
        if(uris.contains(requestURI)){
            Object cur_user = req.getSession().getAttribute("CUR_USER");
            if(cur_user == null){
                resp.sendRedirect("/userManager/user/login");
                return;
            }
        }
        chain.doFilter(req,response);

    }

    @Override
    public void destroy() {

    }
}

过滤器的细节

注解配置过滤器需要servlet3.0及以上的版本
xml配置是没有版本限制的
<filter-mapping>
    <filter-name>charset</filter-name>
    <!--决定了哪些请求会经过这个过滤器-->
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
  </filter-mapping>
  dispatcher 配置
  	FORWARD 转发到对应的资源
  	INCLUDE 当一个资源包含另一个资源的时候,加载另一个资源会经过过滤器 主要用于动态包含
  	REQUEST 默认值 浏览器请求资源的时候
  	ASYNC 异步访问的时候
  	ERROR 错误跳转到资源的时候
  	
拦截配置  url-pattern
	/user  只会拦截 /user
	/user/* 拦截user下面的所有请求
	*.jsp  只会拦截jsp页面
	/* 拦截所有请求
	
	
过滤器的执行流程
	1.请求到达服务器的时候先执行过滤器
	2.过滤器的doFilter方法是在执行过滤
	3. chain.doFilter(req,response); 是在执行目标资源
	4.chain.doFilter(req,response); 之后的代码是目标资源执行完成在响应之前会执行的东西
	5.如果有多个过滤器就会组成过滤链
	
	过滤链的顺序
		xml顺序   <filter-mapping> 谁在前谁先执行
		注解顺序 按类名字母顺序  AFilter 会比BFilter先执行
		
	假设有两个过滤器 AFilter BFilter
	1. AFilter
	2. BFilter
	3. 目标资源
	4. BFilter
	5. AFilter
	
过滤器的生命周期
服务器启动的时候创建对象 执行一次init方法
请求到达过滤器就执行doFilter 方法执行过滤 每个请求会执行一次
服务器关闭的时候对象销毁 销毁之前会执行一次destroy方法
  	
错误页面配置

  <error-page>
    <error-code>404</error-code>
    <location>/404.html</location>
  </error-page>

  <error-page>
    <error-code>500</error-code>
    <location>/500.html</location>
  </error-page>

  <error-page>
    <exception-type>java.lang.NullPointerException</exception-type>
    <location>/404.html</location>
  </error-page>

监听器

1

监听器也是三大组件之一
	事件监听机制
		事件源 事件发生的地方
		事件对象 事件发生的各种信息
		事件监听器 事件发生后的处理方法
对于web程序而言,事件监听器主要分为如下几种
对于三种作用域的监听 
	监听作用域的创建与销毁
	ServletRequestListener 监听request的创建与销毁
	    public void requestDestroyed(ServletRequestEvent sre); 监听request的销毁 请求结束了
        public void requestInitialized(ServletRequestEvent sre); 监听request的创建 接收新的请求
    HttpSessionListener 监听session的创建与销毁
    	public void sessionCreated(HttpSessionEvent se);  session的创建 会话的新建
	    public void sessionDestroyed(HttpSessionEvent se); session的销毁 会话的关闭
	ServletContextListener 监听上下文的创建和销毁	
    	public void contextInitialized(ServletContextEvent sce); 上下文的初始化  服务器启动
	    public void contextDestroyed(ServletContextEvent sce); 上下文的销毁 服务器关闭
	    
监听作用域的数据改变  一般三个方法 添加 删除 替换
	ServletRequestAttributeListener
	HttpSessionAttributeListener
	ServletContextAttributeListener
    	public void attributeAdded(ServletRequestAttributeEvent srae); 作用域中数据的添加
        public void attributeRemoved(ServletRequestAttributeEvent srae); 数据的删除
        public void attributeReplaced(ServletRequestAttributeEvent srae); 数据的替换

实现一个监听器一般根据需要实现上面6个接口中的一个或多个,然后进行配置即可

利用监听器实现在线人数统计

先监听服务器的启动,放入初始数字到上下文对象中

package com.zlt.listener;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

public class MyServletContextListener implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        //先获取到servletContext的对象
        System.out.println("application创建成功");
        sce.getServletContext().setAttribute("onLineCount",0);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {

    }
}

xml配置监听器

<listener>
    <listener-class>com.zlt.listener.MyServletContextListener</listener-class>
  </listener>

登录成功后需要将在线人数+1

//登录成功
            HttpSession session = request.getSession();
            session.setAttribute("CUR_USER",user);
            Cookie cookie = new Cookie("JSESSIONID",session.getId());
            cookie.setPath("/userManager");
            cookie.setMaxAge(60 * 60);
            response.addCookie(cookie);
            //在线人数+1
            int onLineCount = (int) request.getServletContext().getAttribute("onLineCount");
            request.getServletContext().setAttribute("onLineCount",onLineCount + 1);
            response.sendRedirect("/userManager/user/main");

监听session的销毁

package com.zlt.listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSessionBindingEvent;

@WebListener
public class MySessionListener implements  HttpSessionListener {

    // Public constructor is required by servlet spec
    public MySessionListener() {
    }


    // -------------------------------------------------------
    // HttpSessionListener implementation
    // -------------------------------------------------------
    public void sessionCreated(HttpSessionEvent se) {
        /* Session is created. */
    }

    public void sessionDestroyed(HttpSessionEvent se) {
        /* Session is destroyed. */
        // session销毁的时候如果里面有CUR_USER 则表示离线了
        Object cur_user = se.getSession().getAttribute("CUR_USER");
        if(cur_user != null){
            ServletContext servletContext = se.getSession().getServletContext();
            int onLineCount = (int) servletContext.getAttribute("onLineCount");
            servletContext.setAttribute("onLineCount",onLineCount - 1);

        }
    }

}

1

d());
cookie.setPath(“/userManager”);
cookie.setMaxAge(60 * 60);
response.addCookie(cookie);
//在线人数+1
int onLineCount = (int) request.getServletContext().getAttribute(“onLineCount”);
request.getServletContext().setAttribute(“onLineCount”,onLineCount + 1);
response.sendRedirect(“/userManager/user/main”);


监听session的销毁

```java
package com.zlt.listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.http.HttpSessionBindingEvent;

@WebListener
public class MySessionListener implements  HttpSessionListener {

    // Public constructor is required by servlet spec
    public MySessionListener() {
    }


    // -------------------------------------------------------
    // HttpSessionListener implementation
    // -------------------------------------------------------
    public void sessionCreated(HttpSessionEvent se) {
        /* Session is created. */
    }

    public void sessionDestroyed(HttpSessionEvent se) {
        /* Session is destroyed. */
        // session销毁的时候如果里面有CUR_USER 则表示离线了
        Object cur_user = se.getSession().getAttribute("CUR_USER");
        if(cur_user != null){
            ServletContext servletContext = se.getSession().getServletContext();
            int onLineCount = (int) servletContext.getAttribute("onLineCount");
            servletContext.setAttribute("onLineCount",onLineCount - 1);

        }
    }

}

1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员zhi路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值