学习了将近快半年的springboot框架了,优点太多了。真的在很大程度上提高了我们的开发效率。但是,也依然存在一些盲区。就像上面提到的过滤器,拦截器,监听器你真的都清楚吗?下面我们一起来看看:
通俗理解:当你有一堆东西的时候,你只希望选择符合你要求的某一些东西。定义这些要求的工具,就是过滤器。(理解:就是一堆字母中取一个B)。
应用场景:过滤字符编码、做一些业务逻辑判断、URL级别的权限控制,敏感词汇的过滤,等等。它是随你的web应用启动而启动的,只初始化一次,以后就可以拦截相关请求,只有当你的web应用停止或重新部署的时候才销毁。
特点:
过滤器 (实现 javax.servlet.Filter 接口)
① 过滤器是在web应用启动的时候初始化一次, 在web应用停止的时候销毁.
② 可以对请求的URL进行过滤, 对敏感词过滤,
③ 挡在拦截器的外层
④ Filter 是 Servlet 规范的一部分
通俗理解:在一个流程正在进行的时候,你希望干预它的进展,甚至终止它进行,这是拦截器做的事情。(理解:就是一堆字母中,干预它,通过验证的少点,顺便干点别的东西)。
应用场景:
1、日志记录 :记录请求信息的日志
2、权限检查,如登录检查
3、性能检测:检测方法的执行时间。
特点:
拦截器 (实现 org.springframework.web.servlet.HandlerInterceptor 接口)
① 不依赖Spring容器, 可以使用 Spring 容器管理的Bean
② 拦截器通过动态代理进行
③ 拦截器应用场景, 性能分析, 权限检查, 日志记录
通俗理解:这就好比你在干活的时候有监工一样。时时刻刻关注着你。
应用场景:用来监听对象的创建与销毁的发生, 比如 session 的创建销毁, request 的创建销毁, ServletContext 创建销毁 。
特点:
监听器 (实现 javax.servlet.ServletRequestListener, javax.servlet.http.HttpSessionListener, javax.servlet.ServletContextListener 等等接口)
① 主要用来监听对象的创建与销毁的发生, 比如 session 的创建销毁, request 的创建销毁, ServletContext 创建销毁
我们通过一幅图来看一下他们之间的关系:
这是过滤器和拦截器的执行顺序(监听器知道上面的就行了)。
针对这个图再去理解上面的特点和一些使用场景你可能会更清楚。
最后在说一下:springboot中怎么去配置过滤器和拦截器
先创建一个springboot项目,目录结构如下:
过滤器如下:
package com.tff.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
public class FirstFilter implements Filter {
Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
logger.info("FirstFilter执行{}方法:Before","doFilter");
/* HttpServletRequest req = (HttpServletRequest)request;
String url = req.getRequestURI();
if(url.contains("user")){
chain.doFilter(request,response);
}else {
request.getRequestDispatcher("/failed").forward(request,response);
}*/
chain.doFilter(request,response);
logger.info("FirstFilter执行{}方法:after","doFilter");
}
}
就是实现Filter接口,重写doFilter方法。这个可以在这个方法里面过滤你要过滤的东西,也可以在其他配置类中处理(如果在这里处理,就是备注里面的内容),如果在其他配置类里面处理,请看下面(springboot项目建议在配置类中处理):
package com.tff.filter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/***
* 过滤器配置类
*/
public class FilterConfig {
/***
* 注册第一个过滤器
* @return
*/
@Bean
public FilterRegistrationBean firstFilter(){
FilterRegistrationBean registrationBean = new FilterRegistrationBean(new FirstFilter());
//可不设置,默认过滤路径为/*
registrationBean.addUrlPatterns("/user/*");
//有多个过滤器的时候,用于设置先后的顺序
registrationBean.setOrder(1);
return registrationBean;
}
}
OK ,springboot中的过滤器就已经ok了,
在来一起看一下拦截器:
创建一个拦截器类,实现HandlerInterceptor接口,重写一下一些方法:
package com.tff.interceptor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class FirstIntercepter implements HandlerInterceptor {
Logger logger = LoggerFactory.getLogger(this.getClass());
/***
* controller方法调用前执行
* @param request
* @param response
* @param handler
* @return 往下执行则返回true 否则返回false
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
logger.info("{}类执行{}方法",this.getClass().getSimpleName(),"preHandle");
return true;
}
/***
* controller方法调用之后视图渲染前执行
* @param request
* @param response
* @param handler
* @param modelAndView
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
logger.info("{}类执行{}方法",this.getClass().getSimpleName(),"postHandle");
}
/***
* controller方法调用且视图渲染完成后执行
* @param request
* @param response
* @param handler
* @param ex
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
logger.info("{}类执行{}方法",this.getClass().getSimpleName(),"afterCompletion");
}
}
拦截器的配置类(springboot推荐)
package com.tff.interceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
/**
* 重写添加拦截器方法
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new FirstIntercepter())
.addPathPatterns("/**")
.order(1);
}
}
拦截器就配置完成了
接下来我们写一个Controller类,来进行验证下:
package com.tff.web;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/user")
public class Controller {
Logger logger = LoggerFactory.getLogger(this.getClass());
@GetMapping("/hello")
public String test(){
logger.info("Controller类的{}方法执行了","hello");
return "hello";
}
}
浏览器地址栏输入:http://localhost:8080/user/hello
输出结果:
这个顺序刚好跟我们上面第一张图的顺序一样,也验证了这个流程。
欢迎各位大佬批评指正!