JavaWeb开发 Servlet底层 Servlet 过滤器 过滤器和拦截器 手写一个限制访问路径的拦截器

发布于:2025-04-16 ⋅ 阅读:(24) ⋅ 点赞:(0)

目录

万能图

过滤器自我理解

案例 实现Filter 接口

配置文件 web.xml

将过滤器映射到 servlet

用处

拦截器 手写案例

重写 preHandle() 方法 拦截处理

重写 postHandle() 方法 后处理

重写 afterHandle() 方法 完成处理

代码

如何配置拦截器


万能图

还是看一下这张图 太重要了

过滤器是在请求进入 Servlet 容器前对请求进行

预处理 过滤 拦截等一系列操作

过滤器自我理解

过滤器虽然是 HTTP 请求进入 web 服务器后第一个经过的地方

但他是基于 Java Servlet 规范实现的

Servlet 过滤器是可用于 Servlet 编程的 Java 类,可以实现以下目的:

  • 在客户端的请求访问后端资源之前,拦截这些请求。
  • 在服务器的响应发送回客户端之前,处理这些响应。

案例 实现Filter 接口

//导入必需的 java 库
import javax.servlet.*;
import java.util.*;

//实现 Filter 类
public class LogFilter implements Filter  {

    public void  init(FilterConfig config) throws ServletException {
        // 获取初始化参数
        String site = config.getInitParameter("Site");

        // 输出初始化参数
        System.out.println("网站名称: " + site);
    }

    public void  doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws java.io.IOException, ServletException {

        // 输出站点名称
        System.out.println("站点网址:http://www.runoob.com");

        // 把请求传回过滤链
        chain.doFilter(request,response);
    }
    public void destroy( ){
        /* 在 Filter 实例被 Web 容器从服务移除之前调用 */
    }
}

配置文件 web.xml

定义过滤器,然后映射到一个 URL 或 Servlet,这与定义 Servlet,然后映射到一个 URL 模式方式大致相同。在部署描述符文件 web.xml 中为 filter 标签创建下面的条目:

<?xml version="1.0" encoding="UTF-8"?>  
<web-app>  
<filter>
  <filter-name>LogFilter</filter-name>
  <filter-class>com.runoob.test.LogFilter</filter-class>
  <init-param>
    <param-name>Site</param-name>
    <param-value>菜鸟教程</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>LogFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>  
  <!-- 类名 -->  
  <servlet-name>DisplayHeader</servlet-name>  
  <!-- 所在的包 -->  
  <servlet-class>com.runoob.test.DisplayHeader</servlet-class>  
</servlet>  
<servlet-mapping>  
  <servlet-name>DisplayHeader</servlet-name>  
  <!-- 访问的网址 -->  
  <url-pattern>/TomcatTest/DisplayHeader</url-pattern>  
</servlet-mapping>  
</web-app>  

将过滤器映射到 servlet

<filter>
  <filter-name>LogFilter</filter-name>
  <filter-class>com.runoob.test.LogFilter</filter-class>
  <init-param>
    <param-name>Site</param-name>
    <param-value>菜鸟教程</param-value>
  </init-param>
</filter>

通过注解也可以

在 LogFilter 上加上@ WebFilter 注解

然后再启动类里面用@ ServletComponentScan 注解 指定到过滤器类也行

用处

拦截器 手写案例

路径拦截器

手写了一个案例

是当当请求进入 web 服务器后 在到达 controller 之前

校验是否可以访问路径

首先我们创建一个类 实现 HandlerInterceptor 接口

重写 preHandle() 方法 拦截处理

  1. 首先排除不需要拦截的路径 遍历数组 元素相同直接返回 ture
  2. 接着检查登录状态 从 HttpSession 里面去拿
  3. 根据登录状态往 response(HttpServletResponse) 里面塞数据返回
  4. 接着可以校验权限级别 验证 token 的有效期等

重写 postHandle() 方法 后处理

在 request 里面记录一些东西 请求处理时间 响应头

等到请求前往 controller 后会进行处理

重写 afterHandle() 方法 完成处理

可以进行日志记录 之类的

代码

import HandlerInterceptor.HandlerInterceptor;
import org.springframework.util.AntPathMatcher;

import javax.servlet.http.*;

public final class LoginInterceptor implements HandlerInterceptor {

    // 不需要拦截的路径
    private static final String[] EXCLUDE_PATHS = {
            "/user/login",
            "/user/register",
            "/static/**",
            "/error"
    };

    @Override
    public boolean preHandle(HttpServletRequest request,
                             HttpServletResponse response,
                             Object handler) throws Exception {

        String requestURI = request.getRequestURI();
        // 1. 排除不需要拦截的路径 [8]()
        for (String path : EXCLUDE_PATHS) {
            if (new AntPathMatcher().match(path, requestURI)) {
                return true;
            }
        }
        // 2. 检查登录状态 [7]()
        HttpSession session = request.getSession();
        Object userInfo = session.getAttribute("LOGIN_USER");

        // 3. 当用户未登录时
        if (userInfo == null) {
            // 根据请求类型返回不同响应 [3]()
            if (isAjaxRequest(request)) {
                response.setContentType("application/json");
                response.getWriter().write("{\"code\":401,  \"msg\":\"未认证\"}");
            } else {
                response.sendRedirect("/login");
            }
            return false;
        }

        // 4. 可扩展的权限验证逻辑 [15]()
        // 例如验证token有效期、权限级别等
        return true;
    }

    // 后处理
    @Override
    public void postHandle(HttpServletRequest request,
                           HttpServletResponse response,
                           Object handler,
                           ModelAndView modelAndView) throws Exception {
        // 记录请求处理时间、修改响应头等 [10]()
        long startTime = (Long) request.getAttribute("requestStartTime");
        long executeTime = System.currentTimeMillis()  - startTime;
        request.setAttribute("executeTime",  executeTime);
    }

    // 完成处理
    @Override
    public void afterCompletion(HttpServletRequest request,
                                HttpServletResponse response,
                                Object handler,
                                Exception ex) throws Exception {
        // 资源清理、异常记录等 [7]()
        if (ex != null) {
            log.error("Request  processing error: " + request.getRequestURI(),  ex);
        }
    }

    // 判断是否为Ajax请求
    private boolean isAjaxRequest(HttpServletRequest request) {
        return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
    }
}

如何配置拦截器

跟过滤器一个道理

也是两种配置方式

一个是基于配置文件 一个是基于注解


网站公告

今日签到

点亮在社区的每一天
去签到