过滤器和监听器

1. 过滤器(Filter)

1.1 介绍

Filter即为过滤,用于在Servlet之外对request和response进行修改。
主要用于对用户请求进行预处理,或者对HttpServletResponse进行后处理。
使用Filter的流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后再对服务器响应进行后处理。多个Filter合起来称之为一个Filter链。
若是一个过滤器链,则请求时先配置先执行,响应时以相反的顺序执行。

1.2 实现

  1. 编写java类实现Filter接口,并实现其doFilter方法;doFilter方法中需要设置放行,否则请求无法到达资源(filterChain.doFilter(servletRequest,servletResponse)
  2. 通过@WebFilter注解设置其所能拦截的资源。
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.xml.crypto.dsig.spec.XPathType;
import java.io.IOException;

@WebFilter("/*")
//@WebFilter("/s01")
public class Filter01 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        //System.out.println("filter01 init...");
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //放行前做请求拦截
        System.out.println("filter01 拦截请求...");
        filterChain.doFilter(servletRequest,servletResponse);//放行资源
        //放行后做响应拦截
        System.out.println("filter01 处理响应...");
    }
    @Override
    public void destroy() {
        //System.out.println("filter01 destroy...");
    }
}

乱码问题:(Tomcat8及以上版本GET请求不会出现乱码,不需要处理)

GET请求:
	new String(request.getParameter("参数名").getBytes(StandardCharsets.UTF_8));
POST请求:
	request.setCharacterEncoding("UTF-8");
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;


@WebFilter("/s01")
public class Filter02 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("filter02 init...");
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //放行前做请求拦截

        System.out.println("filter02 拦截请求...");
        HttpServletRequest request=(HttpServletRequest)servletRequest;
        HttpServletResponse response=(HttpServletResponse) servletResponse;

        //处理请求乱码(POST)
        request.setCharacterEncoding("UTF-8");
        //处理GET请求乱码问题
        String method=request.getMethod();
        if("GET".equalsIgnoreCase(method)){
            String serverInfo=request.getServletContext().getServerInfo();
            String versionStr=serverInfo.substring(serverInfo.indexOf("/")+1,serverInfo.indexOf("."));
            if(Integer.parseInt(versionStr)<8){
                HttpServletRequest myRequest=new MyWapper(request);
                filterChain.doFilter(myRequest,response);
                return;
            }
        }
        

        filterChain.doFilter(servletRequest,servletResponse);//放行资源

        //放行后做响应拦截
        System.out.println("filter02 处理响应...");
    }
    @Override
    public void destroy() {
        System.out.println("filter02 destroy...");
    }
}
class MyWapper extends HttpServletRequestWrapper {
    //定义成员变量,提升构造器中request对象的范围
    private HttpServletRequest request;

    public MyWapper(HttpServletRequest request){
        super(request);
        this.request=request;
    }
    /**
     * 重写getParamter()方法
     */
    @Override
    public String getParameter(String name) {
        String value=request.getParameter(name);
        if(value!=null||"".equals(value.trim())){
            value=new String(value.getBytes(StandardCharsets.UTF_8));
        }
        return value;
    }
}

1.3 用户非法访问拦截实例

login.jsp(登录页面)

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>login.jsp</title>
</head>
<body>
<h2>欢迎</h2>
<from action="login" id="loginForm">
    <ul>
        <li>姓名:<input type="text" id="uname" name="uname"/></li>
        <li>密码:<input type="password" id="upd" name="upd"/></li>
        <button type="button" id="sub" onclick="login()">登录</button>
        <button type="reset" id="reset">重置</button>
    </ul>
</from>
<script src="js/user.js" type="text/javascript"></script>
</body>
</html>

index.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>index</title>
  </head>
  <body>
  <h2>欢迎${uname}登录</h2>
  </body>
</html>

user.js(外部js校验)

function  login(){
    //判断不为空则提交
    var uname=document.getElementById("uname").value;
    if(uname!=null&&uname.trim()!=""){
        document.getElementById("loginForm").onsubmit;
    }
}

LoginAccessFilter.java(过滤器)

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 非法访问拦截
 *      拦截所有资源 /*
 *      需要放行的资源
 *          放行指定页面(无需登录即可访问的页面,如登录注册等)
 *          放行静态资源(img、js、css等)
 *          放行指定操作(无需登录即可进行的操作,如登录操作)
 *          登录状态放行(判断session中用户信息是否为空)
 */
@WebFilter("/*")
public class LoginAccessFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //基于HTTP请求
        HttpServletRequest request=(HttpServletRequest) servletRequest;
        HttpServletResponse response=(HttpServletResponse) servletResponse;
        //获取请求的路径
        String url=request.getRequestURI();
        //放行指定页面
        if(url.contains("/login.jsp")){
            filterChain.doFilter(request,response);
            return;
        }
        //放行静态资源
        if(url.contains("/js")||url.contains("/img")||url.contains("/css")){
            filterChain.doFilter(request,response);
            return;
        }
        //放行指定操作
        if(url.contains("/login")){
            filterChain.doFilter(request,response);
            return;
        }

        //登录状态放行(判断session中用户信息是否为空)
        String uname=(String)request.getSession().getAttribute("user");
        if(uname!=null)
        {
            filterChain.doFilter(request,response);
            return;
        }

        response.sendRedirect("login.jsp");
        //用户未登录时,拦截请求跳转到登录页面
    }
}

LoginServlet.java

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
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("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("用户登录...");
        String uname=req.getParameter("uname");
        System.out.println(uname);

        if("admin".equals(uname)){
            req.getSession().setAttribute("user",uname);
            //跳转到首页
            resp.sendRedirect("index.jsp");
        }else{
            req.getRequestDispatcher("login.jsp").forward(req,resp);
        }
    }
}

2. 监听器

2.1 介绍

Web监听器是Servlet中一种特殊的类,能够监听web中的特定事件,比如ServletContext、HttpSession、ServletRequest的创建和销毁;变量的创建、销毁、修改等。

2.2 实现

监听器有三类8种:

  • 监听生命周期:
    ServletRequestListener
    HttpSessionListener
    ServletContextListener
  • 监听值变化:
    ServletRequestAttributeListener
    HttpServletAttributeListener
    ServletContextAttributeListener
  • 针对session中的对象:
    监听session中的java对象(JavaBean),是JavaBean直接实现监听器的接口
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener
public class Listener01 implements HttpSessionListener {
    //session被创建时执行,服务器自动调用,
    //(有Servlet创建session时:HttpSession session=req.getSession();)
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        System.out.println("session is created...");
    }
    //session被销毁时执行,服务器自动调用
    //(有Servlet销毁session时:req.getSession().invalidate();)
    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        System.out.println("session is destroyed...");
    }
}

2.3 在线人数统计实例

OnlineListener.java

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

/**
 * 在线人数统计:
 *  初始化为0
 *  当有session创建时+1
 *  当有session销毁时-1
 */
@WebListener
public class OnlineListener implements HttpSessionListener {
    private Integer onlineNum=0;
    @Override
    public void sessionCreated(HttpSessionEvent se) {
        onlineNum++;
        se.getSession().getServletContext().setAttribute("onlineNumber",onlineNum);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent se) {
        onlineNum--;
        se.getSession().getServletContext().setAttribute("onlineNumber",onlineNum);
    }
}

OnlineServlet.java

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 javax.servlet.http.HttpSession;
import java.io.IOException;

@WebServlet("/online")
public class OnlineServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        HttpSession session=req.getSession();

        String key=req.getParameter("key");
        if("logout".equals(key)){
            session.invalidate();
            return;
        }
        /*进入登录操作*/

        Integer onlineN=(Integer) session.getServletContext().getAttribute("onlineNumber");
        //System.out.println(onlineN);
        resp.setContentType("text/html;charset=UTF-8");
        resp.getWriter().write("<h2>当前在线人数:"+onlineN+"</h2><a href='online?key=logout'>退出</a>");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值