浅谈Springboot实现拦截器的两种方式

网友投稿 298 2022-12-17

浅谈Springboot实现拦截器的两种方式

目录一、拦截器方式1、配置HandlerInterceptor2、注册拦截器3、使用拦截器的坑二、过滤器方式1、实现Filter接口2、使用过滤器需要注意的

实现过滤请求有两种方式:

一种就是用拦截器,一种就是过滤器

拦截器相对来说比较专业,而过滤器虽然不专业但是也能完成基本的拦截请求要求。

一、拦截器方式

1、配置HandlerInterceptor

下面这个也是我们公司项目拦截器的写法,总体来说感觉还不错,我就记录了下来。

利用了一个静态Pattern变量存储不走拦截器的路径,然后在preHandle方法当中进行过滤,让他返回true。

@Component

public class LoginInterceptor implements HandlerInterceptor{

private static final Pattern SHOULD_NOT_FILTER_URL_PATTERN;

static {

List 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(InterceptorRegistrJBjAIy registry) {

// 多个拦截器组成一个拦截器链

// addPathPatterns 用于添加拦截规则

// excludePathPatterns 用户排除拦截

registry.addInterceptor(loginInterceptor()).addPathPatterns("/**");

super.addInterceptors(registry);

}

}

二、过滤器方式

本人这一篇博客写了关于filter的一些知识:https://jb51.net/article/204084.htm

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 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,可以调用业务逻辑

执行顺序如下:

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:java反射超详细讲解
下一篇:IDEA2021安装及常用功能设置
相关文章

 发表评论

暂时没有评论,来抢沙发吧~