1. 程式人生 > >SpringBoot兩種方式實現攔截器

SpringBoot兩種方式實現攔截器

一、使用Interceptor攔截器

1.首先新建一個攔截器實現HandlerInterceptor介面

以一個簡單的token驗證為例,驗證通過,將使用者資訊放入作用域,返回true

不通過返回false

@Service
public class UserTokenInterceptor implements HandlerInterceptor {
	@Autowired
	private SysusertokenMapper sysusertokenMapper;
	@Autowired
	private SysloginuserMapper sysloginuserMapper;
	@Autowired
	private SysuserMapper sysuserMapper;
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// 在請求處理之前進行呼叫(Controller方法呼叫之前),返回true才會繼續往下執行,返回false取消當前請求
		boolean isAccess = false;
		String tokenCode = request.getHeader("Token");
		if (tokenCode != null && !"".equals(tokenCode)) {
			//查詢未過期的
			Sysusertoken sysusertoken = sysusertokenMapper.selectByTokenCode(tokenCode);
			if (sysusertoken != null) {
				Sysloginuser sysloginuser  = sysloginuserMapper.selectByPrimaryKey(sysusertoken.getLoginid());
				Sysuser sysuser = sysuserMapper.selectByPrimaryKey(sysloginuser.getUserid());
				request.getSession().setAttribute("user",sysuser);
				request.getSession().setAttribute("token",tokenCode);			
				isAccess = true;
			}
		}
		return isAccess;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {

	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {

	}

}

2.新建一個配置類來管理攔截器,將你之前新建的攔截器注入進來

addPathPatterns("/**")是攔截所有請求

excludePathPatterns("","",...)配置無需攔截的請求

package com.gcexe.monitor.filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

@Component
public class UserTokenAppConfigurer extends WebMvcConfigurationSupport{
	
	@Autowired
	private UserTokenInterceptor userTokenInterceptor;
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		// 多個攔截器組成一個攔截器鏈
        // addPathPatterns 用於新增攔截規則
        // excludePathPatterns 使用者排除攔截
		registry.addInterceptor(userTokenInterceptor).addPathPatterns("/**")
		.excludePathPatterns("/account/login","/account/register");		
		super.addInterceptors(registry);
	}
}

注意加上@Component註解,使其可以被掃描到

二、使用servlet的filter攔截器

新建一個類實現javax.servlet.Filter介面,通過@WebFilter註解來配置要攔截的請求,doFilter方法是要進行的操作。

package com.gcexe.monitor.filter;

import java.io.IOException;
import java.util.Arrays;

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.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.gcexe.monitor.persistence.dao.SysloginuserMapper;
import com.gcexe.monitor.persistence.dao.SysuserMapper;
import com.gcexe.monitor.persistence.dao.SysusertokenMapper;
import com.gcexe.monitor.persistence.entity.Sysloginuser;
import com.gcexe.monitor.persistence.entity.Sysuser;
import com.gcexe.monitor.persistence.entity.Sysusertoken;

@Component
@WebFilter(urlPatterns = "/**", filterName = "monitorFilter")
public class TokenAuthorFilter implements Filter {
	@Autowired
	private SysusertokenMapper sysusertokenMapper;
	@Autowired
	private SysloginuserMapper sysloginuserMapper;
	@Autowired
	private SysuserMapper sysuserMapper;

	private static final String[] excludePathPatterns = { "/monitor/account/login", "/monitor/account/register" };

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub

	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
			throws IOException, ServletException {
		// 在請求處理之前進行呼叫(Controller方法呼叫之前),返回true才會繼續往下執行,返回false取消當前請求
		boolean isFilter = false;
		HttpServletRequest request = (HttpServletRequest) req;
		HttpServletResponse response = (HttpServletResponse) resp;
		// 不攔截登陸和註冊
		String url = request.getRequestURI();
		if (Arrays.asList(excludePathPatterns).contains(url)) {
			chain.doFilter(request, response);
			return;
		}

		String tokenCode = request.getHeader("Token");
		if (tokenCode != null && !"".equals(tokenCode)) {
			// 查詢未過期的
			Sysusertoken sysusertoken = sysusertokenMapper.selectByTokenCode(tokenCode);
			if (sysusertoken != null) {
				Sysloginuser sysloginuser = sysloginuserMapper.selectByPrimaryKey(sysusertoken.getLoginid());
				Sysuser sysuser = sysuserMapper.selectByPrimaryKey(sysloginuser.getUserid());
				request.getSession().setAttribute("user", sysuser);
				request.getSession().setAttribute("token", tokenCode);
				isFilter = true;
			}
		}
		if (isFilter) {
			chain.doFilter(request, response);
		}

	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

}

執行chain.doFilter(request,response)方法類似於上面的返回true,讓程式繼續往下執行

可以自己配置返回內容,無需攔截的請求,我這裡是定義了一個數組,自行判斷,對應地址直接執行chain.doFilter(reuqest.response),同樣注意加上@Component註解

兩種方式均可以使用,相比較而言,第一種方式較為方便,我一開始也是使用的這種,但是後來需要整合Spring Boot Validator框架時,發現驗證資料一直不生效,後來發現是和Inteceptor有衝突,去掉攔截就可以驗證了,暫時還沒找到解決的辦法,所以改為使用第二種方法。