1. 程式人生 > >Java專案微服務中新增攔截器實現

Java專案微服務中新增攔截器實現

目的:專案中需要攔截器的實現,讓沒有登陸的使用者無法通過url來實現頁面的渲染。

實現:

一、繼承HandlerInterceptorAdapter

public class LoginInterceptor extends HandlerInterceptorAdapter

二、重寫preHandler和afterCompletion

preHandler:前置方法,可以攔截在controller之前,return false被攔截,return true被放行

afterCompletion:完成方法,當檢視渲染完成之後執行

/**
 * 前置方法:在handler方法執行之前執行
 * false-被攔截
 * true-放行
 * @param request
 * @param response
 * @param handler
 * @throws Exception
 */
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    // 獲取token資訊
    String token = CookieUtils.getCookieValue(request, this.jwtProperties.getCookieName());
    // 判斷token是否為空
    if (StringUtils.isBlank(token)) {
        // 沒有登入,跳轉到登入頁
        response.sendRedirect("登陸頁面的url(從上個頁面進入登陸頁面的url)");
        return false;
    }
    // 解析jwt
    UserInfo userInfo = JwtUtils.getInfoFromToken(token, this.jwtProperties.getPublicKey());
    if (userInfo == null) {
        response.sendRedirect("登陸頁面的url(從上個頁面進入登陸頁面的url)");
        return false;
    }
    THREAD_LOCAL.set(userInfo);
    return true;
}

/**
 * 完成方法:在檢視渲染完成之後執行
 * @param request
 * @param response
 * @param handler
 * @param ex
 * @throws Exception
 */
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    // 必須要釋放資源,使用的是tomcat執行緒池,業務邏輯處理完成之後,執行緒並沒有結束,還回到執行緒池中了
    THREAD_LOCAL.remove();
}

三、使用ThreadLocal共享使用者資訊資料UserInfo

設定到ThreadLocal中在後續的業務邏輯中就可以使用UserInfo資料

private static final ThreadLocal<UserInfo> THREAD_LOCAL = new ThreadLocal<>();

THREAD_LOCAL.set(userInfo);

完整的攔截器程式碼:

@EnableConfigurationProperties(JwtProperties.class)
@Component
public class LoginInterceptor extends HandlerInterceptorAdapter {

    private static final ThreadLocal<UserInfo> THREAD_LOCAL = new ThreadLocal<>();

    public LoginInterceptor(JwtProperties jwtProperties) {
        this.jwtProperties = jwtProperties;
    }

    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 前置方法:在handler方法執行之前執行
     * false-被攔截
     * true-放行
     * @param request
     * @param response
     * @param handler
     * @throws Exception
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 獲取token資訊
        String token = CookieUtils.getCookieValue(request, this.jwtProperties.getCookieName());
        // 判斷token是否為空
        if (StringUtils.isBlank(token)) {
            // 沒有登入,跳轉到登入頁
            response.sendRedirect("登陸頁面的url(從上個頁面進入登陸頁面的url)");
            return false;
        }

        // 解析jwt
        UserInfo userInfo = JwtUtils.getInfoFromToken(token, this.jwtProperties.getPublicKey());
        if (userInfo == null) {
            response.sendRedirect("登陸頁面的url(從上個頁面進入登陸頁面的url)");
            return false;
        }

        THREAD_LOCAL.set(userInfo);
        return true;
    }

    /**
     * 完成方法:在檢視渲染完成之後執行
     * @param request
     * @param response
     * @param handler
     * @param ex
     * @throws Exception
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 必須要釋放資源,使用的是tomcat執行緒池,業務邏輯處理完成之後,執行緒並沒有結束,還回到執行緒池中了
        THREAD_LOCAL.remove();
    }

    /**
     * 獲取執行緒變數中的引數
     * @return
     */
    public static UserInfo get() {
        return THREAD_LOCAL.get();
    }
}

四、啟動攔截器

兩個條件:1、實現WebMvcConfigurer介面    2、新增@Configuration註解

重寫addInterceptors方法:

@Override
public void addInterceptors(InterceptorRegistry registry)

五、新增攔截器和攔截路徑

@Override
public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(loginInterceptor()).addPathPatterns("/**");
}

其中的addPathPatterns("/**")是指攔截所有的路徑

完整啟動攔截器程式碼:

@Configuration
@EnableConfigurationProperties(JwtProperties.class)
public class ProjectConfig implements WebMvcConfigurer {

    @Autowired
    private JwtProperties jwtProperties;

    @Bean
    public LoginInterceptor loginInterceptor() {
        return new LoginInterceptor(jwtProperties);
    }

    /**
     * 註冊攔截器到攔截器註冊器中,使攔截器生效
     * @param registry
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginInterceptor()).addPathPatterns("/**");
    }
}