【笔记】JavaWeb-04-Filter&Listener


3. Filter

3.1 过滤器

参考资料:

过滤器开发(2步):

  1. 编写java类实现Filter接口,并实现其doFilter方法。
  2. 在web.xml文件中对编写的filter类进行注册,并设置它所能拦截的资源。

过滤器的生命周期:

public void init(FilterConfig filterConfig) throws ServletException;//初始化
和我们编写的Servlet程序一样,Filter的创建和销毁由WEB服务器负责。 web 应用程序启动时,web 服务器将创建Filter 的实例对象,并调用其init方法,读取web.xml配置,完成对象的初始化功能,从而为后续的用户请求作好拦截的准备工作(filter对象只会创建一次,init方法也只会执行一次)。开发人员通过init方法的参数,可获得代表当前filter配置信息的FilterConfig对象。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;//拦截请求
这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL的时候,Servlet过滤器将先执行doFilter方法。FilterChain参数用于访问后续过滤器。

public void destroy();//销毁
Filter对象创建后会驻留在内存,当web应用移除或服务器停止时才销毁。在Web容器卸载 Filter 对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源。

3.2 实例

页面中文字符编码的过滤器(防止中文乱码)

文件结构

image-20220205200653865

依赖包配置(pom.xml)


    
        javax.servlet
        servlet-api
        2.5
    
    
        javax.servlet.jsp
        javax.servlet.jsp-api
        2.3.3
    
    
    
    
        javax.servlet.jsp.jstl
        jstl-api
        1.2
    
    
    
    
        org.apache.taglibs
        taglibs-standard-impl
        1.2.5
        runtime
    

web.xml

<?xml version="1.0" encoding="UTF-8"?>

    
        ServletDemo01
        com.mystudy.servlet.ServletDemo01
    
    
        ServletDemo01
        /servlet/d1
    
    
        ServletDemo01
        /d1
    

    
    
        CharacterEncodingFilter
        com.mystudy.filter.CharacterEncodingFilter
    
    
        CharacterEncodingFilter
        /servlet/*
    

过滤器:CharacterEncodingFilter.java

注意:filterChain.doFilter(servletRequest,servletResponse);

public class CharacterEncodingFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("CharacterEncodingFilter初始化");
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        servletResponse.setContentType("text/html;charset=UTF-8");
        servletResponse.setCharacterEncoding("UTF-8");
        servletRequest.setCharacterEncoding("UTF-8");
        
        System.out.println("CharacterEncodingFilter执行前...");
        filterChain.doFilter(servletRequest,servletResponse); //如果不写,程序到此处将会被拦截停止
        System.out.println("CharacterEncodingFilter执行后...");
    }

    public void destroy() {
        System.out.println("CharacterEncodingFilter销毁");
    }
}

应用:ServletDemo01.java

public class ServletDemo01 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("中文乱码过滤器测试!!");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

    }
}

4. Listen监听

监听器:GUI编程中经常使用

实例

统计在线人数

web.xml



    com.mystudy.listen.SessionCountListen

SessionCountListen.java

public class SessionCountListen implements HttpSessionListener {

    //session创建
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        ServletContext ctx = httpSessionEvent.getSession().getServletContext();
        Integer onlienCount = (Integer) ctx.getAttribute("OnlienCount");
        if (onlienCount==null){
            onlienCount = new Integer(1);
        }else {
            int count = onlienCount.intValue();
            onlienCount = new Integer(count+1);
        }
        ctx.setAttribute("OnlienCount",onlienCount);
    }

    //session销毁
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        ServletContext ctx = httpSessionEvent.getSession().getServletContext();
        Integer onlienCount = (Integer) ctx.getAttribute("OnlienCount");
        if (onlienCount==null){
            onlienCount = new Integer(0);
        }else {
            int count = onlienCount.intValue();
            onlienCount = new Integer(count-1);
        }
        ctx.setAttribute("OnlienCount",onlienCount);

    }
}

index.jsp

前端显示servlet值的两种方法:

  • <%=xxx.xxx.xxx.getAttribute("参数名")%>
  • el表达式:${作用域.参数名}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>

  
    $Title$
  
  
  

当前有: ${applicationScope.OnlienCount} 人在线


当前有: <%=this.getServletConfig().getServletContext().getAttribute("OnlienCount")%> 人在线

5. 过滤、监听的常见应用

filter实现权限拦截:用户登录之后才能进入主页,用户注销后就不能进入主页了。

  1. 用户登录后,向Session放入用户的数据;
  2. 进入主页时需判断用户是否已经登录;要求:在过滤器中实现。(若直接通过地址栏进入主页,需要经过Filter判断是否登录)

5.1 实例

将session存在一个常量里:

Constant.java

public class Constant {
    public static String USER_SESSION = "USER_SESSION";
}

文件结构

image-20220207172747317

登录:ServletLogin.java

如果登陆成功,往session放一个信息,并且跳转到成功页面

public class ServletLogin extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String username = req.getParameter("username");
        if ("admin".equals(username)){// 登陆成功
            // 如果登陆成功,往session放一个信息,并且跳转到成功页面
            req.getSession().setAttribute(Constant.USER_SESSION,req.getSession().getId());
            resp.sendRedirect("/sys/success.jsp");
        }else {// 登陆失败
            resp.sendRedirect("/error.jsp");
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

登录页:login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    login


用户名:

action="/servlet/login"需要和web.xml里注册的一致

登录失败页:error.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>


    登陆失败


登陆失败

无权限或用户名错误

返回登录页面

注销:ServletLogout.java

注销页

public class ServletLogout extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 注销登录:判断session是否存在,若存在则移除,并重定向到登录页面
        Object user_session = req.getSession().getAttribute(Constant.USER_SESSION);
        if (user_session!=null){
            req.getSession().removeAttribute(Constant.USER_SESSION); // 移除该session
            resp.sendRedirect("/login.jsp");
        }
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doGet(req, resp);
    }
}

过滤器:SysFilter.java

public class SysFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // ServletRequest  -->  HttpServletRequest
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        // 获取Session,如果为空,则跳转到未登录(登陆错误)页
        if (request.getSession().getAttribute(Constant.USER_SESSION)==null){
            response.sendRedirect("/error.jsp");
        }
        filterChain.doFilter(request,response);
    }
    public void destroy() {
    }
}

web.xml


    ServletLogin
    com.mystudy.servlet.ServletLogin


    ServletLogin
    /servlet/login


    ServletLogout
    com.mystudy.servlet.ServletLogout


    ServletLogout
    /servlet/logout




    SysFilter
    com.mystudy.filter.SysFilter


    SysFilter
    /sys/*