美文网首页
Java入门系列15 -- 过滤器与监听器

Java入门系列15 -- 过滤器与监听器

作者: YanZi_33 | 来源:发表于2021-12-14 14:44 被阅读0次

过滤器

  • Filter即过滤,它主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理;

  • 使用Filter的完整流程,Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Fliter再对服务器响应进行后处理,在一个web应用中,可以开发编写多个Filter,这些Fliter组合起来称之为一个Fliter链;

  • Filter通过java.servlet.Filter的接口来实现,主要步骤如下所示:

    • 首先创建Java类,实现Filter接口;
    • 然后通过@WebFilter注解,设置它所能拦截的资源;
  • 案例代码,创建Servlet01Servlet02Filter01Filter02,代码如下:

  • Servlet01文件

package com.sf.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("/servlet01")
public class Servlet01 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet01...");
    }
}
  • Servlet02文件
package com.sf.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("/servlet02")
public class Servlet02 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("Servlet02...");
    }
}
  • Filter01文件
package com.sf.filter;

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

//通过注解指定拦截servlet01资源
@WebFilter("/servlet01")
//拦截所有的资源
//@WebFilter("/*")
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() {

    }
}
  • Filter02文件
package com.sf.filter;

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

//通过注解指定拦截servlet01资源
@WebFilter("/servlet01")
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 正在拦截...");
        //放行资源
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.println("Filter02 正在处理响应...");
    }

    @Override
    public void destroy() {

    }
}
  • Filter01与Filter02都拦截了Servlet01,结果如下所示:
image.png
  • Filter拦截请求的顺序与拦截响应的顺序是相反的;
  • @WebFilter("/*")可拦截所有的资源;
  • filterChain.doFilter()是放行资源,如果不放行则会出现资源拦截,无法执行servlet的service方法;
请求乱码的处理
  • Servlet 文章中关于请求乱码的情况有详细的阐述,下面我们来实现拦截所有请求,进行请求乱码的统一处理;
  • 创建AEncodingFilter过滤器,代码入下:
package com.sf.filter;

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.io.UnsupportedEncodingException;

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

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        //基于HTTP
        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 version = serverInfo.substring(serverInfo.indexOf("/")+1,serverInfo.indexOf("."));
            if (Integer.parseInt(version) < 8) {
               //自定义内部类MyWapper 重写getParameter方法
               HttpServletRequest myRequest = new MyWapper(request);
               filterChain.doFilter(myRequest,response);
               return;
            }
        }
        //放行资源
        filterChain.doFilter(request,response);
    }

    @Override
    public void destroy() {

    }

    class MyWapper extends HttpServletRequestWrapper {
        private HttpServletRequest request;
        public MyWapper(HttpServletRequest request) {
            super(request);
            this.request = request;
        }

        /**
         * 重写getParameter方法
         * @param name
         * @return
         */
        @Override
        public String getParameter(String name) {
            String value = request.getParameter(name);
            if (value != null && !"".equals(value)) {
                try {
                    value = new String(value.getBytes("ISO-8859-1"),"UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
            }
            return value;
        }
    }
}
用户非法访问拦截
  • 下面实现当用户在未登录的情况下,不能访问需要登录的页面,也就是说用户在访问资源时,进行资源拦截,
    • 无需登录的页面,放行页面;
    • 放行静态资源;
    • 放行指定操作 无需登录就可执行的操作 登录操作,注册操作;
    • 登录状态 需要放行 判断session信息;
    • 当用户未登录时,拦截请求跳转到登录页面;
  • 创建过滤器LoginAccessFilter文件,代码如下:
package com.sf.filter;

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

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

    //只要是 资源 路径 请求 操作 都会被拦截
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("LoginAccessFilter doFilter...");
        //当用户未登录时,拦截请求跳转到登录页
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;

        //放行资源
        //1.放行指定页面 无需登录的页面
        String url = request.getRequestURI();
        if (url.contains("/login.jsp")) {
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }
        //2.放行静态资源
        if (url.contains("/js") || url.contains("/image") || url.contains("css")) {
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }
        //3.放行指定操作 无需登录就可执行的操作 登录操作,注册操作
        if (url.contains("/login")) {
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }
        //4.登录状态 需要放行 判断session信息
        String name = (String) request.getSession().getAttribute("name");
        if (name != null) {
            filterChain.doFilter(servletRequest,servletResponse);
            return;
        }

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

    @Override
    public void destroy() {

    }
}
  • 创建登录逻辑处理文件LoginServlet,代码如下:
package com.sf.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("/login")
public class LoginServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("LoginServlet...");
        String name = req.getParameter("name");
        if ("admin".equals(name)) {
            req.getSession().setAttribute("name",name);
            resp.sendRedirect("index.jsp");
        } else {
            req.getRequestDispatcher("login.jsp").forward(req,resp);
        }
    }
}
  • 创建前台登录页面login.jsp文件;
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>登录页面</title>
</head>
<body>
    <form action="login" id="loginForm">
        姓名: <input type="text" name="name" id="name">
        <button type="button" onclick="login()">登录</button>
    </form>

    <script src="js/user.js" type="text/javascript">

    </script>

</body>
</html>
  • 创建进行登录的js文件user.js
function login() {
    var name = document.getElementById("name").value;
    if (name != null && name.trim() != "") {
        document.getElementById("loginForm").submit();
    }
}
  • 创建登录成功的首页文件index.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
      <h2>欢迎${name}登录!!!</h2>
  </body>
</html>

监听器

  • web监听器是Servlet中一种特殊的类,能帮助开发者监听web中的特定事件,例如ServletContext,HttpSession,ServletRequest的创建与销毁,变量的创建,销毁和修改等等,可以在某些动作前后增加处理,实现监控;
  • 监听器分为三类8种;
    • 监听生命周期:ServletRequestListener,HttpSessionListener,ServletContextListener;
    • 监听值的变化:ServletRequestAttributeListener,HttpSessionAttributeListener,ServletContextAttributeListener;
    • 监听session中Java对象;
  • 案例代码:创建Java类Listener01
package com.sf.listener;

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

public class Listener01 implements HttpSessionListener {
    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        System.out.println("Session对象 被创建");
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        System.out.println("Session对象 被销毁");
    }
}
监听器 -- 在线人数统计
  • 创建监听器类OnLineListener,代码如下:
package com.sf.listener;

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

public class OnLineListener implements HttpSessionListener {
    //统计在线人数
    private Integer onlineNumber;

    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        onlineNumber++;
        //将人数存入session作用域中
        httpSessionEvent.getSession().setAttribute("onlineNumber",onlineNumber);
        //将人数存入application作用域中
        httpSessionEvent.getSession().getServletContext().setAttribute("onlineNumber",onlineNumber);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        onlineNumber--;
        //将人数存入session作用域中
        httpSessionEvent.getSession().setAttribute("onlineNumber",onlineNumber);
        //将人数存入application作用域中
        httpSessionEvent.getSession().getServletContext().setAttribute("onlineNumber",onlineNumber);
    }
}

  • 创建Servlet类OnlineServlet,代码如下:
package com.sf.servlet;

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

@WebFilter("/onlineServlet")
public class OnlineServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //创建session对象
        HttpSession session = req.getSession();
        String key = req.getParameter("key");
        if (key != null && "logout".equals(key)) {
            session.invalidate();
            return;
        }
        //获取当前人数
        Integer onlineNumber = (Integer) session.getServletContext().getAttribute("onlineNumber");
        resp.setContentType("text/html;charset=UTF-8");
        //返回给客户端
        resp.getWriter().write("<h2>当前在线人数: "+onlineNumber+"</h2> <a href='online?key=logout'>退出</a>");
    }
}

相关文章

网友评论

      本文标题:Java入门系列15 -- 过滤器与监听器

      本文链接:https://www.haomeiwen.com/subject/tleefrtx.html