SpringBoot兩種方式實現攔截器
阿新 • • 發佈:2019-01-01
一、使用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有衝突,去掉攔截就可以驗證了,暫時還沒找到解決的辦法,所以改為使用第二種方法。