卖不甜枣 发表于 2024-7-19 08:53:50

过滤器、监听器、拦截器

目录

一、 主要内容
二、 过滤器
2.1 介绍
2.2 实现
MyFilter01
MyFilter02
MyServlet01
MyServlet02
2.3 说明
2.4 实行顺序
1. 利用 web.xml
2. 利用注解和@Order
3. 利用FilterRegistrationBean
2.5字符乱码
三、监听器
3.1介绍
3.2实现
3.3在线人数统计
OnlineListener
OnlineServlet2
四、拦截器
4.1介绍
4.2实现方式
1.实现HandlerInterceptor接口
2.实现WebRequestInterceptor接口
3.继续HandlerInterceptorAdapter类
4.注册拦截器
4.3解决的标题
4.4与Spring Boot的集成
4.4实行顺序控制
4.5身份验证明例
步调一:创建拦截器
步调二:配置拦截器
步调三:测试
注意事项
五、过滤器和拦截器区别 (面试常问)
六、如何理解"拦截器只能拦截部分web哀求"
1.拦截器的作用范围
2.为什么拦截器不能拦截全部Web哀求?
3.如何拦截全部Web哀求?


一、 主要内容

过滤器(Filter)监听器(Listener)拦截器(Interceptor)关注点web哀求系统级别参数、对象Action(部分Web哀求)实现方式函数回调事件Java反射机制应用场景设置字符编码统计网站在线人数拦截未登任命户URL级别的权限访问控制清晰逾期session审计日志过滤敏感词汇压缩响应信息是否依赖Servlet容器是否Servlet提供的支持Filter接口ServletRequestListener HttpSessionListener ServletContextListenerSpring提供的支持HandlerInterceptor WebRequestInterceptor HandlerInterceptorAdapter级别系统级别系统级别非系统级别
二、 过滤器

2.1 介绍



[*] Filter 即为过滤,用于在 Servlet 之外对 Request或者 Response 举行修改。
[*] 它主要用于对用户哀求举行预处 理,也可以对 HtpServletResponse 举行后处理。
[*] 利用 Filter 的完备流程: Filter 对用户哀求举行预处理,接着将哀求交给 Servlet 举行处理并天生响应,末了 Filter 再对服务器响应举行后处理。
[*] 在一个 web 应用中,可以开发编写多个 Filter,这些 Filter 组合起来称之为一个 Filter 链。
https://i-blog.csdnimg.cn/direct/9c5e340fb0c9413eb375a768dfc495fc.png
https://i-blog.csdnimg.cn/direct/a5421597b2204e93adecb9e50fc7c22a.png
若是一个过滤器链:先配置先实行(哀求时的实行顺序);响应时:以相反的顺序实行
   在 HttpServletRequest 到达 Servlet 之前,拦截客户的HttpServletRequest。根据需要查抄 HttpServletRequest,也可修改 HttpServletRequest 头和数据。 在HttpServletResponse 到达客户端之前,拦截 HttpServletResponse。 根据需要查抄HttpServletResponse,也可修改 HttpServletResponse头和数据
2.2 实现



[*] 通过实现javax.servlet.Fileter的接口来实现一个过滤器。
[*] 此中界说了 三个方法:init(),doFilter(),destroy(),分别在相应的机遇实行。后期观察生命周期。
[*] Filter 的实现只需要两步:

[*] 1:编写 java 类实现 Filter接口,并实现其 doFilter 方法
[*] 2:通过@WebFilter注解设置它所能拦截的资源。
[*] filterChain.doFilter(servletRequest, servletResponse); 放行

/*和/**
在Spring MVC框架中,配置拦截器(Interceptor)的路径模式时,/*和/**这两个通配符有以下区别:


[*] /*:

[*] 匹配一级目录下的全部哀求路径。
[*] 它只匹配直接跟在指定路径后面的第一级子路径。
例如,如果配置为 /user/*,那么它会匹配 /user/john 或 /user/admin,但不会匹配 /user/profile/edit。

[*] /**:

[*] 匹配任意多级目录下的全部哀求路径。
[*] 它可以匹配任何深度的子路径。
例如,如果配置为 /user/,那么它会匹配 /user/john、/user/admin、/user/profile/edit 等等。
总结来说,/*只匹配直接下一层的路径,而/**可以匹配全部层级的路径,包括直接下一层和更深条理的路径。
在实际应用中,如果你想要对整个应用步调的全部哀求举行拦截,通常会选择利用 /** ,由于它提供了更全面的覆盖。而 /* 更适合需要精细控制某些特定一级目录下的哀求的情况。

MyFilter01

package com.dev.filter;

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

/**
* 实现过滤器
* 1. 实现javax.servlet.Filter接口
* 2. 重写方法
* 3. 在doFilter方法中编写过滤逻辑(控制资源访问)
* 4,配置过滤器,设置拦截路径
*/
// 拦截所有资源
@WebFilter("/myServlet01")
public class MyFilter01 implements Filter {
 
 
@Override
 
 
public void init(FilterConfig filterConfig) throws ServletException {
 
}
 
 
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

 
 
 
 
// 处理请求数据
 
 
 
 
System.out.println("filter01start ");

 
 
 
 
filterChain.doFilter(servletRequest, servletResponse);

 
 
 
 
// 处理响应数据
 
 
 
 
System.out.println("filter01end");
 
}

 
 
@Override
 
 
public void destroy() {

 
}
} ​ MyFilter02

package com.dev.filter;

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

/**
* 实现过滤器
* 1. 实现javax.servlet.Filter接口
* 2. 重写方法
* 3. 在doFilter方法中编写过滤逻辑(控制资源访问)
* 4,配置过滤器,设置拦截路径
*/
// 拦截所有资源
@WebFilter("/myServlet02")
public class MyFilter01 implements Filter {
 
 
@Override
 
 
public void init(FilterConfig filterConfig) throws ServletException {
 
}
 
 
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

 
 
 
 
// 处理请求数据
 
 
 
 
System.out.println("filter02start ");

 
 
 
 
filterChain.doFilter(servletRequest, servletResponse);

 
 
 
 
// 处理响应数据
 
 
 
 
System.out.println("filter02end");
 
}

 
 
@Override
 
 
public void destroy() {

 
}
}
​ MyServlet01

package com.dev.filter;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import java.io.IOException;

@WebServlet("/myServlet01")
public class MyServlet01 extends HttpServlet {
 
 
@Override
 
 
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
 
 
 
 
System.out.println("servlet01......");
 
}
}
​ MyServlet02

package com.dev.filter;

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import java.io.IOException;

@WebServlet("/myServlet02")
public class MyServlet02 extends HttpServlet {
 
 
@Override
 
 
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
 
 
 
 
System.out.println("servlet02......");
 
}
} ​
   注意


[*] 界说两个拦截器

[*] MyFilter01 @WebFilter("/myServlet")
[*] MyFilter02 @WebFilter("/*)

[*] 界说两个Servlet:

[*] MyServlet01 @WebServlet("/myServlet")
[*] MyServlet02 @WebServlet("/myServlet02")


访问


[*] /myServlet02 ------ filter02start ==>servlet02==>filter02end
[*] /myServlet ------ filter01start ==>filter02start ==>servlet01==>filter02end==>filter01end
2.3 说明



[*] 过滤器

[*] 在哀求到达资源之前,过滤器会举行预处理(处理request);在响应到达客户端之前,过滤器会举行后处理(处理response)

[*] 过滤器链

[*] 当存在多个过滤器时,先配置的先实行(如果没有配置文件,则按照字母排序)

[*] 过滤器1、过滤器2、过滤器3

[*] 当哀求访问资源时,过滤器实行的顺序是1->2->3;
[*] 到达资源后,响应的顺序为 3->2->1;



2.4 实行顺序

1. 利用 web.xml

过滤器的实行顺序就是它们在web.xml中声明的顺序。最先声明的过滤器将最先实行,而末了声明的过滤器将在响应阶段末了实行
   <!-- web.xml -->
<filter>
 
 
<filter-name>AuthFilter</filter-name>
 
 
<filter-class>com.example.AuthFilter</filter-class>
</filter>

<filter-mapping>
 
 
<filter-name>AuthFilter</filter-name>
 
 
<url-pattern>/secure/*</url-pattern>
</filter-mapping>

<filter>
 
 
<filter-name>LoggingFilter</filter-name>
 
 
<filter-class>com.example.LoggingFilter</filter-class>
</filter>

<filter-mapping>
 
 
<filter-name>LoggingFilter</filter-name>
 
 
<url-pattern>/*</url-pattern>
</filter-mapping>
​实行顺序说明


[*] 对于全部哀求,LoggingFilter都会被触发,由于它匹配全部URL模式。
[*] 对于以/secure/开头的哀求,除了LoggingFilter之外,AuthFilter也会被触发。
[*] 由于AuthFilter在web.xml中先于LoggingFilter声明,以是对于匹配/secure/的哀求,AuthFilter会先于LoggingFilter实行。
[*] 对于非/secure/的哀求,仅LoggingFilter会被实行。
因此,纵然过滤器处理差异的URL模式,它们的实行顺序仍然基于配置文件中的声明顺序。

2. 利用注解和@Order

在Spring框架中,可以利用@WebFilter注解团结@Order注解来指定过滤器的实行顺序。@Order注解需要一个整数参数,数值越小的过滤器将越早实行
@Order(1)
@WebFilter(urlPatterns = "/*")
public class FirstFilter implements Filter {
 
 
// ...
}

@Order(2)
@WebFilter(urlPatterns = "/*")
public class SecondFilter implements Filter {
 
 
// ...
}
3. 利用FilterRegistrationBean

在Spring Boot或Spring MVC中,你也可以通过FilterRegistrationBean在配置类中注册过滤器
@Configuration
public class FilterConfig {

 
 
@Bean
 
 
public FilterRegistrationBean<FirstFilter> firstFilterRegistration() {
 
 
 
 
FilterRegistrationBean<FirstFilter> registration = new FilterRegistrationBean<>();
 
 
 
 
registration.setFilter(new FirstFilter());
 
 
 
 
registration.addUrlPatterns("/*");
 
 
 
 
registration.setOrder(1);
 
 
 
 
return registration;
 
}

 
 
@Bean
 
 
public FilterRegistrationBean<SecondFilter> secondFilterRegistration() {
 
 
 
 
FilterRegistrationBean<SecondFilter> registration = new FilterRegistrationBean<>();
 
 
 
 
registration.setFilter(new SecondFilter());
 
 
 
 
registration.addUrlPatterns("/*");
 
 
 
 
registration.setOrder(2);
 
 
 
 
return registration;
 
}
} ​
2.5字符乱码

哀求Tomcat7及以下版本Tomcat8及以上版本POST乱码,需要处理乱码,需要处理GET乱码,需要处理不会乱码,无需处理 处理


[*] POST

[*] request.setCharacterEncoding("UTF-8");

[*] GET (服务器版本在 Tomcat7及以下版本)

[*] 得到哀求类习惯
[*] 得到服务器版本信息
[*] 判定哀求为GET且版本小于8
[*] 处理乱码

package com.dev.filter;

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

/**
* 请求乱码统一处理
*tomcat8及以上版本 POST请求乱码问题
*tomecat7以下版本 POST/GET请求乱码问题
*/
@WebFilter("/**")
public class AEncodingFilter implements Filter {
 
 

 
 
public AEncodingFilter(){
 
 

 
}
 
 
@Override
 
 
public void init(FilterConfig filterConfig) throws ServletException {
 
 

 
}
 
 

 
 
@Override
 
 
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
 
 
 
 
// 基于HTTP
 
 
 
 
HttpServletRequest request = (HttpServletRequest) servletRequest;
 
 
 
 
HttpServletResponse response = (HttpServletResponse) servletResponse;
 
 
 
 

 
 
 
 
// 处理请求乱码问题
 
 
 
 
request.setCharacterEncoding("UTF-8");
 
 
 
 

 
 
 
 
// 放行
 
 
 
 
filterChain.doFilter(request, response);
 
 
 
 

 
}
 
 

 
 
@Override
 
 
public void destroy() {
 
 

 
}
} ​ 三、监听器

3.1介绍

web 监听器是Servlet 中一种的特别的类,能资助开发者监听 web 中的特定事件,好比 ServletcontextHttpSession,ServletRequest 的创建和烧毁;变量的创建、烧毁和修改等。 可以在某些动作前后增加处理,实现监控。例如可以用来统计在线人数等。
3.2实现

监听器有三类8种:


[*] 监听生命周期

[*] ServletRequestListener
[*] HttpSessionListener
[*] ServletContextListener

[*] 监听值的变化

[*] ServletRequestAttributeListener
[*] HttpSessionAttributeListener
[*] ServletContextAttributeListener

[*] 针对 session 中的对象

[*] 监听 session 中的 java 对象(javaBean),是javaBean 直接实现监听器 的接口

3.3在线人数统计


OnlineListener

package com.dev.listener;

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

/**
* 在线人数统计
*/
@WebListener
public class OnlineListener implements HttpSessionListener {
 
 

 
 
// 得到在线人数
 
 
public static int onlineCount = 0;
 
 

 
 
/**
 
 
* 当有新的session创建时,在线人数加一
 
 
* @param httpSessionEvent
 
 
*/
 
 
@Override
 
 
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
 
 
 
 
onlineCount++;
 
 
 
 

 
 
 
 
// 将在线人数放入session作用域中
 
 
 
 
// httpSessionEvent.getSession().setAttribute("onlineCount", onlineCount);
 
 
 
 
// 将在线任务放入application作用域中
 
 
 
 
httpSessionEvent.getSession().getServletContext().setAttribute("onlineCount", onlineCount);
 
}
 
 

 
 
/**
 
 
* 当session销毁时,在线人数减一
 
 
* @param httpSessionEvent
 
 
*/
 
 
@Override
 
 
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
 
 
 
 
onlineCount--;
 
 
 
 
// 将在线人数放入session作用域中
 
 
 
 
// httpSessionEvent.getSession().setAttribute("onlineCount", onlineCount);
 
 
 
 
// 将在线任务放入application作用域中
 
 
 
 
httpSessionEvent.getSession().getServletContext().setAttribute("onlineCount", onlineCount);
 
}
}
​ OnlineServlet2

package com.dev.listener;

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("/online")
public class OnlineServlet2 extends HttpServlet {
 
 

 
 
@Override
 
 
public void service(HttpServletRequest req, HttpServletResponse res) throws IOException {
 
 
 
 

 
 
 
 
//得到动作
 
 
 
 
String action = req.getParameter("action");
 
 
 
 
if ("logout".equals(action)) {
 
 
 
 
 
 
// 退出
 
 
 
 
 
 
req.getSession().invalidate();
 
 
 
 
 
 
return;
 
 
 
}
 
 
 
 

 
 
 
 
// 得到当前访问的ip
 
 
 
 
String ip = req.getRemoteAddr();
 
 
 
 
System.out.println("当前访问的ip为:" + ip );
 
 
 
 

 
 
 
 

 
 
 
 
// 获取session作用域中的在线人数
 
 
 
 
// Integer onlineCount =(Integer) req.getSession().getAttribute("onlineCount");
 
 
 
 
// 获取application作用域中的在线人数
 
 
 
 
Integer onlineCount =(Integer) req.getSession().getServletContext().getAttribute("onlineCount");
 
 
 
 

 
 
 
 
// 响应数据 在页面中显示人数
 
 
 
 
res.setContentType("text/html;charset=utf-8");
 
 
 
 
res.getWriter().write("当前在线人数为:" + onlineCount+"<a href='myServlet03?action=logout'>退出</a>");
 
 
 
 
res.getWriter().flush();
 
 
 
 
res.getWriter().close();
 
}
} ​ 四、拦截器

4.1介绍

拦截器(Interceptor)是Java Web应用中的一种设计模式,主要用于在哀求到达目的组件(如控制器)之前或响应离开目的组件之后实行一些特定的逻辑。在Spring框架中,拦截器是AOP(面向切面编程)的一个应用,可以用来实现诸如权限验证、日志记录、事务管理、性能监控等功能。
4.2实现方式

1.实现HandlerInterceptor接口

在Spring MVC中,拦截器可以通过实现HandlerInterceptor接口来创建
该接口包罗三个方法:


[*] preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception: 在哀求处理之前调用,可以用于权限验证、数据校验等。如果返回false,则哀求处理停止,不会继续实行后续的拦截器或控制器方法。
[*] postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception: 在哀求处理之后,但在视图渲染之前调用,可以用于日志记录、缓存处理等。
[*] afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception: 在视图渲染之后调用,可以用于资源清理等操作。
 
import org.springframework.web.servlet.HandlerInterceptor;
 
import org.springframework.web.servlet.ModelAndView;

 
import javax.servlet.http.HttpServletRequest;
 
import javax.servlet.http.HttpServletResponse;

 
public class CustomInterceptor implements HandlerInterceptor {

 
 
 
@Override
 
 
 
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 
 
 
 
 
// 在这里实现你的逻辑
 
 
 
 
 
return true;
 
 
 
}

 
 
 
@Override
 
 
 
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
 
 
 
 
 
// 在这里实现你的逻辑
 
 
 
}

 
 
 
@Override
 
 
 
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
 
 
 
 
 
// 在这里实现你的逻辑
 
 
 
}
 
}
 
2.实现WebRequestInterceptor接口

这个接口与HandlerInterceptor雷同,但是它在更早的阶段被调用,以致在哀求映射之前。这使得它适合做一些全局的初始化工作。实现WebRequestInterceptor接口需要重写以下方法:


[*] preHandle(WebRequest request):在哀求处理之前调用。
[*] postHandle(WebRequest request, ModelMap model):在哀求处理之后调用。
[*] afterCompletion(WebRequest request, Exception ex):在哀求处理完成之后调用。

3.继续HandlerInterceptorAdapter类

如果你不想实现HandlerInterceptor接口中的全部方法,可以继续HandlerInterceptorAdapter类,这是一个适配器类,它为HandlerInterceptor接口提供了默认实现,你只需要重写你感兴趣的方法即可。
 
import org.springframework.web.servlet.HandlerInterceptorAdapter;​  
public class CustomInterceptor extends HandlerInterceptorAdapter {​  
 
 
@Override  
 
 
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
 
 
 
 
// 在这里实现你的逻辑  
 
 
 
 
return true;  
 
 
}  
}  
4.注册拦截器

一旦你创建了拦截器,就需要在Spring配置中注册它。这可以通过实现WebMvcConfigurer接口的addInterceptors方法来完成。
import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;​@Configurationpublic class WebConfig implements WebMvcConfigurer {​  
 
@Override  
 
public void addInterceptors(InterceptorRegistry registry) {  
 
 
 
registry.addInterceptor(new CustomInterceptor())  
 
 
 
 
 
 
.addPathPatterns("/**"); // 指定拦截器应用的全部哀求  
}}​
4.3解决的标题

拦截器可以解决多种标题:


[*] 权限控制:在哀求到达控制器之前验证用户权限。
[*] 日志记录:记录哀求和响应的详细信息,有助于调试和审计。
[*] 性能监控:计算哀求处理时间,监控应用性能。
[*] 数据校验:查抄哀求参数的有用性,防止非法哀求。
[*] 资源清理:确保在哀求处理完毕后开释资源。
4.4与Spring Boot的集成

在Spring Boot中利用拦截器,可以通过以下步调:


[*] 创建拦截器类并实现HandlerInterceptor接口。
[*] 在Spring配置类中注册拦截器,通常通过实现WebMvcConfigurer接口的addInterceptors方法。
import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;​import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;​public class MyInterceptor implements HandlerInterceptor {​  
 
@Override  
 
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
 
 
 
System.out.println("Pre-handle logic...");  
 
 
 
return true; // 返回true表示继续处理哀求  
}​  
 
@Override  
 
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {  
 
 
 
System.out.println("Post-handle logic...");  
}​  
 
@Override  
 
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {java  
 
 
 
System.out.println("After completion logic...");  
}}​ 接下来,在Spring配置类中注册这个拦截器:
import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;​@Configurationpublic class WebConfig implements WebMvcConfigurer {​  
 
@Override  
 
public void addInterceptors(InterceptorRegistry registry) {  
 
 
 
registry.addInterceptor(new MyInterceptor())  
 
 
 
 
 
 
.addPathPatterns("/**"); // 指定拦截器应用的全部哀求  
}}​
4.4实行顺序控制

拦截器的实行顺序可以通过以下方式控制:


[*] 配置顺序:在addInterceptors方法中,拦截器的添加顺序决定了它们的实行顺序。
[*] 实现Ordered接口:让拦截器实现Ordered接口并重写getOrder()方法,返回一个整数,数值越小,优先级越高。
import org.springframework.core.Ordered;import org.springframework.web.servlet.HandlerInterceptor;​public class MyInterceptor implements HandlerInterceptor, Ordered {​  
 
@Override  
 
public int getOrder() {  
 
 
 
return 1; // 优先级高于其他返回值大于1的拦截器  
}​  
 
// 其他方法...} ​ 4.5身份验证明例

假设我们有一个Spring Boot应用,此中某些资源是受掩护的,只有颠末身份验证的用户才能访问。我们可以利用拦截器来查抄用户的会话状态,确保只有已登录的用户才能访问这些资源。
步调一:创建拦截器

起首,我们需要创建一个拦截器类,实现HandlerInterceptor接口,并覆盖preHandle方法来实行身份验证逻辑。
import org.springframework.stereotype.Component;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;​import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;​@Componentpublic class AuthenticationInterceptor implements HandlerInterceptor {​  
 
@Override  
 
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
 
 
 
// 从session中获取用户信息  
 
 
 
HttpSession session = request.getSession(false);  
 
 
 
if (session != null) {  
 
 
 
 
 
Object user = session.getAttribute("user");  
 
 
 
 
 
if (user != null) {  
 
 
 
 
 
 
 
// 用户已登录,答应哀求继续  
 
 
 
 
 
 
 
return true;  
 
 
 
 
}  
 
 
}  
 
 
 
 
 
 
 
// 用户未登录,重定向到登录页面  
 
 
 
response.sendRedirect(request.getContextPath() + "/login");  
 
 
 
return false;  
}​  
 
@Override  
 
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {  
 
 
 
// 这里可以处理哀求后的逻辑,例如日志记录  
}​  
 
@Override  
 
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {  
 
 
 
// 这里可以处理哀求完成后的清理工作  
}} ​
步调二:配置拦截器

接下来,我们需要在Spring配置类中注册这个拦截器,并指定它应该应用于哪些URL。
import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;​@Configurationpublic class WebConfig implements WebMvcConfigurer {​  
 
@Override  
 
public void addInterceptors(InterceptorRegistry registry) {  
 
 
 
registry.addInterceptor(new AuthenticationInterceptor())  
 
 
 
 
 
 
.addPathPatterns("/protected/*") // 指定拦截器应用于/protected下的全部哀求  
 
 
 
 
 
 
.excludePathPatterns("/protected/login", "/protected/logout"); // 排除登录和登出路经  
}}​ 步调三:测试

如今,每当有哀求尝试访问/protected/*下的资源时,AuthenticationInterceptor都会被调用。如果用户没有登录,他们将被重定向到登录页面。如果已经登录,则哀求将继续正常处理。
注意事项



[*] 确保登录和登出路由被排除在拦截器之外,否则用户将无法访问这些页面。
[*] 考虑到安全性,可能还需要在拦截器中加入更复杂的认证逻辑,例如查抄JWT令牌等。
[*] 如果应用中有多个拦截器,它们的实行顺序可以通过实现Ordered接口并重写getOrder()方法来控制。
通过这种方式,拦截器可以资助我们在Spring Boot应用中实现细粒度的访问控制,进步应用的安全性和健壮性。

五、过滤器和拦截器区别 (面试常问)

过滤器(Filter)和拦截器(Interceptor)在Java Web应用步调中饰演偏紧张的脚色,它们用于在哀求到达目的组件(如Servlet或JSP)之前或之后实行特定的逻辑。两者都可以在哀求过程中参与并可能阻止哀求。
尽管它们有相似的功能,但它们在实现机制、作用范围、依赖环境等方面存在明显差异。


[*] 实现机制:

[*] 过滤器是基于函数回调的,通常通过实现javax.servlet.Filter接口来创建。过滤器会拦截全部进入Servlet容器的哀求和响应,并且可以访问HttpServletRequest和HttpServletResponse对象。
[*] 拦截器是基于Java的反射机制(动态代理)实现的,通常与框架如Spring MVC一起利用。拦截器可以访问更广泛的上下文信息,好比Spring MVC的ModelAndView对象,以及控制器方法的参数和返回值。

[*] 依赖环境:

[*] 过滤器依赖于Servlet容器,如Tomcat、Jetty等,因此只能在Web环境中利用。
[*] 拦截器不依赖于Servlet容器,可以在任何利用Spring MVC框架的应用中利用,纵然是在非Web环境中也可以实现雷同的功能。

[*] 作用范围:

[*] 过滤器可以拦截几乎全部的HTTP哀求,包括对静态资源的哀求。
[*] 拦截器通常只拦截那些由控制器处理的哀求,即所谓的“action”哀求,不会拦截静态资源哀求。

[*] 生命周期:

[*] 过滤器在Servlet容器启动时初始化,在容器关闭时烧毁,每个哀求只调用一次doFilter()方法。
[*] 拦截器可以多次调用,取决于哀求的路径和配置,每次哀求可以调用多次拦截器的preHandle()、postHandle()和afterCompletion()方法。

[*] 配置方式:

[*] 过滤器通过web.xml文件或注解(如@WebFilter)配置。
[*] 拦截器通常通过Spring的配置类或XML文件配置。


六、如何理解"拦截器只能拦截部分web哀求"

截器主要用于拦截和处理由控制器(Controller)处理的哀求,而不是全部的Web哀求。
这是由于拦截器的设计初衷是为了处理业务逻辑层面的哀求,如权限查抄、日志记录、数据预处理等,这些通常与具体的业务操作相关联。
1.拦截器的作用范围



[*] 控制器哀求:拦截器主要针对由控制器处理的哀求,即通过HTTP方法(GET、POST等)调用控制器方法的哀求。拦截器可以访问控制器方法的参数、返回值、以及模子和视图对象。
[*] 静态资源哀求:拦截器通常不会拦截静态资源(如CSS、JavaScript、图片等)的哀求,由于这些哀求不涉及业务逻辑,而是直接由Web服务器或Servlet容器处理。
[*] 非控制器路径:对于不通过控制器处理的哀求,如直接指向特定资源或Servlet的哀求,拦截器也不会举行拦截。
2.为什么拦截器不能拦截全部Web哀求?



[*] 设计目的:拦截器的设计目的是为了在业务逻辑层面上举行干预,而并非处理底层的网络通信或静态资源的分发。
[*] 性能考虑:如果拦截器拦截全部哀求,包括静态资源哀求,可能会引入不必要的性能开销,由于静态资源的处理通常非常快速,而拦截器的参与可能会增加延迟。
[*] 框架限制:Spring MVC的拦截器机制是基于控制器的,因此它天然不适合处理那些不由控制器处理的哀求。
3.如何拦截全部Web哀求?



[*] 如果需要对全部Web哀求举行处理,包括静态资源哀求,那么应该利用过滤器(Filter)。过滤器是Servlet容器级别的,它可以拦截全部进入容器的哀求,无论这些哀求是针对控制器还是静态资源。
[*] 过滤器的实现和配置与拦截器差异,它通过实现javax.servlet.Filter接口来创建,并在web.xml文件或利用@WebFilter注解来配置。
总结来说,拦截器在Spring MVC中主要用于处理与业务逻辑相关的哀求,而过滤器则可以用于处理全部类型的Web哀求,包括静态资源哀求。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 过滤器、监听器、拦截器