拦截器与过滤器
- 拦截器
介绍:主要用于拦截用户请求并作出相应的处理。例如通过拦截器可以进行权限验证、记录请求信息的日志、登录验证等。
原理:所有的拦截器 (Interceptor) 和处理器 (Handler) 都注册在 HandlerMapping 中,Spring MVC 中所有的请求都是由 DispatcherServlet 分发的。当请求进入时,首先会得到处理该请求的 Handler (即 Controller 中对应的方法)以及所有拦截该请求的拦截器
实现:这里先定义一个拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | package com.elite.groovy.interceptor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.io.IOUtils; 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; /** * @author Smith * @date 2023/8/23 17:08 * @description 接口访问拦截器 */ @Slf4j @Component public class ProxyInterceptor implements HandlerInterceptor { /** * 预处理回调方法,实现处理器的预处理(如登录检查) * 第三个参数为响应的处理器,即controller * 返回true,表示继续流程,调用下一个拦截器或者处理器 * 返回false,表示流程中断,通过response产生响应 */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { log.info( "收到前端的请求,url:" + request.getRequestURL()); log.info( "请求参数 :" + IOUtils.toString(request.getInputStream(), "utf-8" )); return true ; } /** * 当前请求进行处理之后,也就是Controller方法调用之后执行, * 但是它会在DispatcherServlet 进行视图返回渲染之前被调用。 * 此时我们可以通过modelAndView对模型数据进行处理或对视图进行处理。 */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) { } /** * 方法将在整个请求结束之后,也就是在DispatcherServlet渲染了对应的视图之后执行。 * 这个方法的主要作用是用于进行资源清理工作的。 */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { } } |
其次配置拦截器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package com.elite.groovy.config; import com.elite.groovy.interceptor.ProxyInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.ArrayList; import java.util.List; @Configuration public class InterceptorConfig implements WebMvcConfigurer { @Autowired private ProxyInterceptor ipInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(ipInterceptor) .addPathPatterns( "/**" ); } } |
- 过滤器
介绍:过滤器是Servlet的高级特性之一,是实现Filter接口的Java类。其基本功能就是对servlet的调用进行干预,在servl请求和响应的过程中增加一些特定的功能。可以使用过滤器实现的功能有:统一编码,URL级别的权限访问控制,过滤敏感词汇,压缩请求信息
实现:
package com.elite.ngs.filter; import com.wisdge.web.IPUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import java.io.IOException; import java.util.concurrent.TimeUnit; /** * @author smith * @date 2023/1/11 13:44 */ @WebFilter(urlPatterns = {"/smsCodeSend_"}, filterName = "smsFilter") public class SmsFilter implements Filter { private static final Log log = LogFactory.getLog(SmsFilter.class); protected RedisTemplate redisTemplate; @Override public void init(FilterConfig filterConfig) throws ServletException { ServletContext servletContext = filterConfig.getServletContext(); WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(servletContext); redisTemplate = (RedisTemplate) webApplicationContext.getBean("redisTemplate"); log.debug("------smsFilter init!-------"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { log.debug("--------start smsFilter-------------"); HttpServletRequest request = (HttpServletRequest) servletRequest; String ip = IPUtils.getRemoteIP(request); log.debug("smsSend ip :" + ip); String smsKey = "SMS:" + ip; //先看Key是否存在 boolean flag = redisTemplate.hasKey(smsKey); if (flag) { //说明上次发送验证码的时间不超过一分钟 log.debug("smsKey exist"); } else { // 第一次调用,所以value(调用次数)设置为1 redisTemplate.opsForValue().set(smsKey, "1", 1, TimeUnit.MINUTES); filterChain.doFilter(request, servletResponse); } } @Override public void destroy() { log.debug("------smsFilter destroy----"); } }
配置filter
第一个是上面的例子,使用WebFilter注解,但是多个filter时无法控制先后顺序,只会根据filter的首字母顺序来确定先后顺序。
第二个是在web.xml中配置,执行顺序按配置的上下先后顺序执行
filter标签:fliter-name:指为过滤器的名字;filter-class:过滤器的完整类名
filter-mapping标签:fliter-name是filter标签中声明的名字;url-pattern用来设置filter所拦截的请求路径。
<filter> <filter-name>myFilter</filter-name> <filter-class>com.lsl.mylsl.filter.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <url-pattern>/test</url-pattern> </filter-mapping>
<filter> <filter-name>myFilter</filter-name> <filter-class>com.lsl.mylsl.filter.MyFilter</filter-class> </filter> <filter-mapping> <filter-name>myFilter</filter-name> <url-pattern>/test</url-pattern> </filter-mapping>
- 区别
a.过滤器依赖servlet容器(tomcat等,只能在web程序中使用);而拦截器不依赖servlet容器。它是个spring组件,由spring容器管理,可以单独使用。
b.过滤器可以拦截所有请求,包括访问静态资源的请求,拦截器只能拦截action请求,即访问controller的请求
c.拦截器可以获取IOC容器中的各个bean,而过滤器不行。可以在拦截器里注入一个service,可以调用业务逻辑
d.触发时机不同。过滤器是在请求进入容器后,但在进入servlet之前进行预处理,请求结束是在servlet处理完以后;拦截器是在请求进入servlet后,在进入Controller之前进行预处理的,Controller 中渲染了对应的视图之后请求结束。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!