目录
万能图
还是看一下这张图 太重要了
过滤器是在请求进入 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() 方法 拦截处理
- 首先排除不需要拦截的路径 遍历数组 元素相同直接返回 ture
- 接着检查登录状态 从 HttpSession 里面去拿
- 根据登录状态往 response(HttpServletResponse) 里面塞数据返回
- 接着可以校验权限级别 验证 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"));
}
}
如何配置拦截器
跟过滤器一个道理
也是两种配置方式
一个是基于配置文件 一个是基于注解