SpringbMVC拦截器(Interceptor)

209 阅读2分钟

一:拦截器Interceptor

  1. 拦截器拦截以 .action结尾的url,拦截Action的访问。 Interfactor是基于Java的反射机制(APO思想)进行实现,不依赖Servlet容器。
  2. 拦截器可以在方法执行之前(preHandle)和方法执行之后(afterCompletion)进行操作,回调操作(postHandle),可以获取执行的方法的名称,请求(HttpServletRequest)
  3. Interceptor:可以控制请求的控制器和方法,但控制不了请求方法里的参数(只能获取参数的名称,不能获取到参数的值) (用于处理页面提交的请求响应并进行处理,例如做国际化,做主题更换,过滤等)。
    简而言之:Spring拦截器是基于AOP思想对HTTP资源进行拦截控制的一种手段

二:springmvc中拦截器的实现

1.创建一个自定义拦截器,实现接口HandlerInterceptor并重写方法preHandle,这个方法会在执行所有方法之前预先执行。

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

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

/*
 *   自定义重写拦截器
 * */
@Component
public class LoginIntercept implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1.得到session对象
        HttpSession session = request.getSession(false);
        if (session != null && session.getAttribute("userinfo") != null) {
            //说明已经登陆,可以放行
            return true;
        }
        // 执行到这行表示未登录,未登录就重定向到到登陆页面
        response.sendRedirect("/user/login");
        return false;
   

2.将自定义拦截器加入到 WebMvcConfigurer 的 addInterceptors 方法中。
代码实现

import org.springframework.beans.factory.annotation.Autowired;
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 AppConfig implements WebMvcConfigurer {

    @Autowired
    private LoginIntercept loginIntercept;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginIntercept).
                addPathPatterns("/**").
                excludePathPatterns("/user/login").
                excludePathPatterns("/user/reg").
                excludePathPatterns("/login.html").
                excludePathPatterns("/reg.html").
                excludePathPatterns("/**/*.css").
                excludePathPatterns("/**/*.jpg");
    }
}
  1. addPathPatterns:表示需要拦截的 URL,**的意思表示所有方法,在这表示拦截所有的方法
  2. excludePathPatterns:表示排除的 URL,也就是需要放行的方法。

3. 处理指定接口

我们也可以在拦截器里面进行一些业务逻辑的处理,比如放行部分接口、捕捉指定接口等。

public class LoginInterceptor implements HandlerInterceptor {

    // 处理指定接口
    private static final String TOKEN_LOGIN = "/user/token";
    private static final String USER_NO_URL = "/user/no"; // 拦截不存在的接口路径

    // 不要要校验的接口
    private static final List<String> NO_NEED_LOGIN = new ArrayList<>(Arrays.asList("/user/health", "/logout"));

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 获取访问的接口名
        String uri = request.getRequestURI();
        String contentPath = request.getContextPath();
        if (uri.startsWith(contentPath + "/")) {
            // 去掉contextPath
            uri = uri.replace(contentPath + "/", "/");
        }
        if (NO_NEED_LOGIN.contains(uri)) {
//            log.info("资源{}不需要登录,直接访问", uri);
            System.out.println("这个接口不需要验证,直接放行.");
            return true;
        }
        if (uri.equals(TOKEN_LOGIN)) {
            response.setStatus(200);
            response.setCharacterEncoding("utf-8");
            response.getWriter().println("处理指定接口,并返回数据信息."); // 可以返回相关json处理
            return false;
        }
        if (uri.equals(USER_NO_URL)) {
            response.setStatus(500);
            response.setCharacterEncoding("utf-8");
            response.getWriter().println("拦截的是未定义的接口."); // 可以返回相关json处理
            return false;
        }

        // 可以对每个接口进行身份校验 或者 编写相关业务逻辑
        System.out.println("执行了拦截器的preHandle方法");
        return true;
    }
}