【JavaWeb】Filter&Listener学习笔记

目录

Filter

案例代码:

生命周期:

解决全栈乱码:

Listener

案例代码:


    在实际开发过程中,我们需要对某一些访问资源进行筛选  过滤,当这个请求满足特定的情况,才能让这个请求访问目标资源,如果不满足条件,就不能访问目标资源. 例如:对于管理员的访问功能,我们应该在请求之前判断一下是否是管理员权限,如果当前用户是管理员权限的时候可以访问,反之则不可以.

Filter

    Filter是java中预先定义的接口,可以根据需求过滤不同的内容,具体的过滤内容需要自己定义一个实现类,然后实现接口中的过滤方法. 当客户端浏览器发出一个请求的时候,这个请求在访问真正的目标资源之前,进行一个条件的过滤,然后在请求目标资源,这个过程就可以通过过滤器来完成. 

    当我们访问的某一个资源的时候,如果访问的路径存在的话,filter会进行一个放行操作,正常执行后面的servlet代码,如果此时访问的路径不存在,那么filter就不会进行放行操作,此时控制台会输出filter的内容.

案例代码:

操作步骤:

  1. 编写一个类,实现javax.servlet.Filter接口
  2. 重写filter的方法,有事注dofilter的方法
  3. 在web.xml中配置filter(作用)
    1. 告诉servlet容器我是一个filter
    2. 告诉filter容器访问其他资源的时候会执行过滤操作.

web.xml代码:

    <filter>
        <filter-name>HelloFilter</filter-name>
        <filter-class>com.james.filter.HelloFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>HelloFilter</filter-name>
        <!--表示当前filter所拦截的路径设置-->
        <url-pattern>/demo2</url-pattern>
    </filter-mapping>

HelloFilter(Filter)代码:

public class HelloFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    /**
     * filter执行过滤 主要编写代码的方法 等效 Servlet中的service方法
     * 代码的逻辑 一行一行执行的
     */
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("入门过滤器执行 A");
        //不放行就相当于 当前请求就结束了 直接响应回去

        //放行 进入原来的链接路径 相当 于调用方法 DemoServlet.doGet(request,response)
        //filterChain.doFilter(servletRequest , servletResponse) ;//放行代码

        System.out.println("入门过滤器执行 B");
    }

    @Override
    public void destroy() {

    }
}

servlet代码:

public class DemoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.doGet(request,response);
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("demo被访问了");
        response.getWriter().print("demo");
    }
}

执行流程:

生命周期:

void init(FilterConfig config):初始化方法,在项目启动的时候就会执行,只执行一次

void doFilter(request,response,FilterChain chain):执行过滤方法,当请求匹配上的时候就会执行

void destroy():销毁,在项目被移除的时候或者服务器关闭的时候就会执行,只执行一次

Servlet:默认第一次被访问初始化 每一次执行Servlet执行service方法 服务器停止 执行destroy方法

        Filter是一个单实例的线程不安全的对象(不要给成员变量) 

        服务器启动的时候,服务器创建filter对象,且调用filter的init方法,实现初始化操作.

        当请求来的时候,若filter能匹配到此路径,服务器就会从线程池中获取一个线程,在线程中调用filter的doFilter方法,当doFilter方法执行了放行操作的时候才会到达下一个地方

        当线程正常关闭的时候,服务器会调用filter的destroy的方法实现销毁操作

注意:一个路径只能有一个servlet执行,但是一个路径可以有多个filter执行,且filter中不存在路径优先级问题

解决全栈乱码:

     每一个servlet的第一步操作都是处理和响应编码,而浏览器在发出一任何请求的时候,我们可以通过过滤器同一进行中文乱码的处理.  

     在Tomcat8.5处理了get请求的中文乱码,但是post没有进行处理,对于post请求我们之前的操作是通过request.setCharacterEncoding("utf-8");并且每一个servlet都要写一句这种代码,非常麻烦,通过过滤器我们便可以只写一次而对多个servlet有效.

代码步骤:

  1. 编写一个过滤器
  2. 配置过滤器的路径为   /*
  3. 编写过滤器的请求逻辑
package com.james.web.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "EncodingFilter" , urlPatterns = "/*")
public class EncodingFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //全站编码
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        //放行
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

Listener

    在我们java程序中,我们需要监事某些事情的执行,一旦被监视的对象发生相应的改变,我们需要采取相应的操作.

    JavaWeb中又三大域对象:

ServletRequest        HTTPSession     ServletContext

    今天就ServletContextLister来做一下小总结:

监听器一共有8个:

  1. 监听域对象的创建和销毁
    1. ServletRequestListener
    2. HttpSessionListener
    3. ServletContextListener
  2. 监听域对象对的属性操作
    1. ServletRequestAttributeListener
    2. HttpSessionAttributeListener
    3. ServletContextAttributeListener
  3. 监听特殊的JavaBean在session中的特殊处理
    1. HttpSessionBingdingListener
    2. HttpSessionActivationListener

监听器的主要概念:

    事件源:发生事件的对象

    事件:发生了什么事情

    监听器:一个接口,需要我们自己实现.

案例代码:

统计在线人数实例步骤分析:

1. 编写一个监听器,实现HttpSessionListener

2. 在session创建后的操作

  • 获取servletContext对象
  • 获取在线的人数
    • 若人数为null,则设置人数为1
    • 若人数不为null,设置人数+1\

3. 在session销毁后的操作

  • 获取servletContext对象
  • 获取在线人数
    • 将人数--,放入servletContext域中

4 . 创建一个servlet进行测试.

listener

package com.james.web.listener;

import javax.servlet.ServletContext;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

/**
 * 登录成功 或者 退出登录 其实操作的是 session的创建和销毁
 * 监听session的创建和销毁即可
 */
@WebListener
public class MyHttpSessionListener implements HttpSessionListener {
    /**
     * 数量+1
     * httpSessionEvent 事件对象
     */
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {

        HttpSession session = httpSessionEvent.getSession();
        System.out.println(session.getId()+",第一次被创建,放入servletContext中");
        //获得全局的域对象
        ServletContext sc = session.getServletContext();

        //先获得原来的登录数量
        Integer count = (Integer)sc.getAttribute("count");
        //以前一定登录过
        if(count != null && count !=0 ){ // 先判断非空 再判断值
            count++;
        }else{
            count=1; //以前没有登录过
        }
        sc.setAttribute("count" , count);
    }

    /**
     * 数量-1
     */
    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        //获得session
        HttpSession session = httpSessionEvent.getSession();
        System.out.println(session.getId() +" : 即将销毁 , 退出登录");
        //获得servletContext
        ServletContext servletContext = session.getServletContext();

        Integer count = (Integer)servletContext.getAttribute("count");
        //表示当前一定有人正在登录状态
        if(count != null && count >0 ){
            count -- ;
        }else{
            count= 0 ;
        }
        servletContext.setAttribute("count" , count);
    }
}

login

package com.james.web.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "LoginServlet" , urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("登陆成功:" +request.getSession().getId());
    }
}

logout

package com.james.web.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "LoginOutServlet" , urlPatterns = "/loginOut")
public class LoginOutServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("退出了session:" + request.getSession().getId());
        //销毁session
        request.getSession().invalidate();
    }
}

showCount:

package com.james.web.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(name = "ShowLogin" , urlPatterns = "/showLogin")
public class ShowLogin extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().print("当前人数为:" + getServletContext().getAttribute("count"));
    }
}

页面:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
    <a href="${pageContext.request.contextPath}/login">点我登录服务器-不需要做登录案例</a><br/>
    <a href="${pageContext.request.contextPath}/loginOut">点我退出登录</a><br/>
    <a href="${pageContext.request.contextPath}/showLogin">点我查看登录成功服务器人数</a>
    当前登录人数为: ${count}<br/>
  <%--jsp的底层有九大内置对象 默认自己调用request.getSession();--%>
  </body>
</html>

   通过session的创建(request.getsession())销毁(request.getSession().invalidate();)来调用监视器中的方法从而实现session个数的改变.最终能够在页面上进行显示.

猜你喜欢

转载自blog.csdn.net/weixin_43267344/article/details/108721334