攔截器原理
在 Spring MVC 中,攔截器(Interceptor)是一種機制,用于攔截請求并在處理程序(Controller)執(zhí)行之前或之后執(zhí)行一些操作。攔截器允許您在請求的不同階段(如處理程序執(zhí)行前、處理程序執(zhí)行后、視圖渲染前、視圖渲染后等)添加自定義邏輯。
其中問號就是攔截器處理的范圍。
實現(xiàn)自定義攔截器
@Component
public class SampleInterceptor implements HandlerInterceptor {
// 在controller執(zhí)行前的邏輯
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 在controller執(zhí)行之前執(zhí)行的邏輯
System.out.println("Pre-handle logic");
return true; // 返回 true,將允許請求繼續(xù)傳遞到處理程序;
//返回 false,將阻止請求傳遞給處理程序
}
// 在controller執(zhí)行后、并在視圖渲染前執(zhí)行的邏輯
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("Post-handle logic");
}
//在服務器響應結束后執(zhí)行的邏輯
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("After-completion logic");
}
}
將自定義攔截器添加到SpringMvc中
@Configuration
public class InterceptorRoll implements WebMvcConfigurer {
@Autowired
LoginTicketInterceptor loginTicketInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
//registry.addInterceptor() 方法可以向注冊表中添加攔截器。
InterceptorRegistration interceptorRegistration = registry.addInterceptor(loginTicketInterceptor);
//添加攔截器生效路徑,以及攔截器忽略的路徑
...
}
}
使用攔截器實現(xiàn)權限驗證邏輯
關鍵鑒權邏輯圖解:
1.在請求controller之前先經(jīng)過攔截器,從cookie中獲取用戶標識,根據(jù)用戶標識,從redis中取出登錄憑證
2.如果登錄憑證有效,則設置一個線程與用戶信息進行綁定,并將用戶信息存入到視圖模型中
3.如果憑證無效則跳轉到登錄頁面
4.在用戶請求完之后,銷毀線程與用戶名的綁定
實現(xiàn):
1.創(chuàng)建工具類ThreadHolder
package com.duhong.util;
import com.duhong.entity.User;
import org.springframework.data.redis.core.StringRedisTemplate;
public class ThreadHolder {
static ThreadLocal<User> users=new ThreadLocal<>();
/**
* 設置線程信息
* @param user
*/
public static void setHolder(User user){
users.set(user);
}
/**
* 獲取當前線程的信息
* @return
*/
public static User getHolder(){
return users.get();
}
/**
* 解除線程與當前用戶的綁定
*/
public static void remove(){
users.remove();
}
}
2.創(chuàng)建自定義攔截器
@Component
public class LoginTicketInterceptor implements HandlerInterceptor {
@Autowired
StringRedisTemplate redisTemplate;//redis客戶端
@Autowired
UserMapper userMapper;//根據(jù)用戶id查詢用戶所有信息
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//獲取用戶的cookie
Cookie[] cookies = request.getCookies();
String loginOwner=null;
System.out.println("開始鑒權");
for(Cookie cookie:cookies){
if(cookie.getName().equals("loginOwner")){
loginOwner=cookie.getValue();
break;
};
}
LoginTicket ticket=new LoginTicket();
//如果loginOwner不等于null,從redis中獲取登錄簽證
if(loginOwner!=null) {
String s = redisTemplate.opsForValue().get(RedisUtil.getTicket(loginOwner));
ticket = RedisUtil.getObject(s);
//用戶已被授權
if (ticket != null && ticket.getStatus() == 1) {
User user = userMapper.selectById(ticket.getUserId());
//將用戶信息與當前線程綁定
ThreadHolder.setHolder(user);
return true;
}
}
//如果簽證不等于null,而且簽證的狀態(tài)無效則跳轉到登錄頁面
response.sendRedirect("/site/login");
return false;
}
/**
* 在視圖層渲染之前將用戶信息存入模型
* @param request
* @param response
* @param handler
* @param modelAndView
* @throws Exception
*/
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
if(ThreadHolder.getHolder()!=null&&modelAndView!=null){
//從當前線程中獲取用用戶信息
modelAndView.addObject("loginUser",ThreadHolder.getHolder());
}
}
/**
* 在服務器響應完本次信息之后,解除當前線程與用戶信息的綁定
* @param request
* @param response
* @param handler
* @param ex
* @throws Exception
*/
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
ThreadHolder.remove();
}
}
3.將攔截器加入到SpringMvc中并設置攔截規(guī)則文章來源:http://www.zghlxwxcb.cn/news/detail-814116.html
package com.duhong.config;
import com.duhong.filter.LoginTicketInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.Arrays;
import java.util.List;
@Configuration
public class InterceptorRoll implements WebMvcConfigurer {
@Autowired
LoginTicketInterceptor loginTicketInterceptor;
//配置文件中配置配置需要過濾的路徑形式為:路徑,路徑,...
@Value("${allow.pages}")
String allowPages;
@Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration interceptorRegistration = registry.addInterceptor(loginTicketInterceptor);
interceptorRegistration.addPathPatterns("/**");
String[] split = allowPages.split(",");
for (String allowpage : split) {
System.out.println(allowpage);
//忽略指定頁面
interceptorRegistration.excludePathPatterns(allowpage);
}
//忽略靜態(tài)資源
interceptorRegistration.excludePathPatterns("/css/**","/img/**","/js/**");
}
}
如有收獲,就點個贊吧!文章來源地址http://www.zghlxwxcb.cn/news/detail-814116.html
到了這里,關于SpringMvc中攔截器的配置及應用的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!