Springboot 拦截器 浅谈Springboot实现拦截器的两种方式
怪咖软妹@ 人气:2想了解浅谈Springboot实现拦截器的两种方式的相关内容吗,怪咖软妹@在本文为您仔细讲解Springboot 拦截器的相关知识和一些Code实例,欢迎阅读和指正,我们先划重点:Springboot,拦截器,下面大家一起来学习吧。
实现过滤请求有两种方式:
一种就是用拦截器,一种就是过滤器
拦截器相对来说比较专业,而过滤器虽然不专业但是也能完成基本的拦截请求要求。
一、拦截器方式
1、配置HandlerInterceptor
下面这个也是我们公司项目拦截器的写法,总体来说感觉还不错,我就记录了下来。
利用了一个静态Pattern变量存储不走拦截器的路径,然后在preHandle方法当中进行过滤,让他返回true。
@Component public class LoginInterceptor implements HandlerInterceptor{ private static final Pattern SHOULD_NOT_FILTER_URL_PATTERN; static { List<String> urlList = new ArrayList<>(); // 将不走拦截器的请求存放到Pattern urlList.add("(socket/.*)"); urlList.add("(user/findUserList)"); StringBuilder sb = new StringBuilder(); for (String url : urlList) { sb.append(url); sb.append("|"); } sb.setLength(sb.length() - 1); SHOULD_NOT_FILTER_URL_PATTERN = Pattern.compile(sb.toString()); } /** * 在请求处理之前进行调用(Controller方法调用之前) */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { HttpSession session = request.getSession(); // 获取访问的url String servletPath = request.getServletPath(); // 排除特定请求 if (SHOULD_NOT_FILTER_URL_PATTERN.matcher(servletPath).find()) { return true; } if (session.getAttribute("user") != null) { // 可能有的项目在校验完session,还会校验token String token = request.getHeader("access_token"); // 此处业务省略。。。 return true; } return false; } /** * 请求处理之后进行调用,但是在视图被渲染之前(Controller方法调用之后) */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // TODO Auto-generated method stub } /** * 在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作) */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // TODO Auto-generated method stub } }
2、注册拦截器
配置完上面的拦截器还需要注册拦截器。
WebMvcConfigurerAdapter类是 Spring内部的一种配置方式
采用JavaBean的形式来代替传统的xml配置文件形式进行针对框架个性化定制
@Configuration public class MyWebAppConfigurer extends WebMvcConfigurerAdapter { @Autowired private LoginInterceptor loginInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { // 多个拦截器组成一个拦截器链 // addPathPatterns 用于添加拦截规则 // excludePathPatterns 用户排除拦截 registry.addInterceptor(loginInterceptor).addPathPatterns("/**"); super.addInterceptors(registry); } }
3、使用拦截器的坑
继承WebMvcConfigurerAdapter 重写addInterceptors方法的时候,一定要使用注入方式,将loginInterceptor注入到变量当中,要么就使用@Bean注解的方式,将loginInterceptor(拦截器)注入到容器。
之所以这么搞是因为拦截器在 Bean 初始化之前进行,所以在拦截器中无法像这样注入 Bean。
就算加了@Component,他是存放于容器当中了,但是他存放容器当中的对象属性,是空属性。
在WebMvcConfigurerAdapter 使用@Autowired注入了一遍拦截器,属性就有值了。
说白了不管采用哪种方案,目的只有一个,让对象的属性有值,因为拦截器比其他对象初始化早,导致属性为空,想让他有值,就想办法让他重新走一遍spring注入容器,也可以采用这种方式:
@Configuration public class MyWebAppConfigurer extends WebMvcConfigurerAdapter { // 这么写的目的是为了在SessionInterceptor中能注入spring中的service @Bean LoginInterceptor loginInterceptor() { return new LoginInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { // 多个拦截器组成一个拦截器链 // addPathPatterns 用于添加拦截规则 // excludePathPatterns 用户排除拦截 registry.addInterceptor(loginInterceptor()).addPathPatterns("/**"); super.addInterceptors(registry); } }
二、过滤器方式
本人这一篇博客写了关于filter的一些知识:https:
1、实现Filter接口
import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.springframework.stereotype.Component; @Component @WebFilter(filterName = "requestParamFilter",urlPatterns = "/*") public class RequestParamFilter implements Filter { private static final Pattern SHOULD_NOT_FILTER_URL_PATTERN; static { List<String> urlList = new ArrayList<>(); // 将不走拦截器的请求存放到Pattern urlList.add("(socket/.*)"); urlList.add("(user/findUserList)"); StringBuilder sb = new StringBuilder(); for (String url : urlList) { sb.append(url); sb.append("|"); } sb.setLength(sb.length() - 1); SHOULD_NOT_FILTER_URL_PATTERN = Pattern.compile(sb.toString()); } @Override public void init(FilterConfig filterConfig) throws ServletException { } // 发送请求会执行这个方法 // 一个doFilter相当于拦截器的执行前和执行后 // filterChain.doFilter后面的内容就是执行后的内容,假如不执行filterChain.doFilter方法相当于方法被拦截 @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("sunhan---请求参数过滤器!---test1"); HttpServletRequest request = (HttpServletRequest)servletRequest; HttpSession session = request.getSession(); // 获取访问的url String servletPath = request.getServletPath(); // 排除特定请求 if (SHOULD_NOT_FILTER_URL_PATTERN.matcher(servletPath).find()) { filterChain.doFilter(servletRequest,servletResponse); } System.out.println("开始拦截了................"); //业务代码 } @Override public void destroy() { } }
2、使用过滤器需要注意的
拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑
执行顺序如下:
加载全部内容