1.簡介
preHandle方法是進行處理器攔截用的,顧名思義,該方法將在Controller處理之前進行調用。
SpringMVC中的Interceptor攔截器是鏈式的,可以同時存在多個Interceptor,然後SpringMVC會根據聲明的前後順序一個接一個的執行,而且所有的Interceptor中的preHandle方法都會在Controller方法調用之前調用。
(SpringMVC的這種Interceptor鏈式結構也是可以進行中斷的,這種中斷方式是令preHandle的返回值爲false,當preHandle的返回值爲false的時候整個請求就結束了。)
重寫preHandle方法,在請求發生前執行。
2.問題
我們先來看看尼特社區的原始代碼:
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//設置廣告
for (AdPosEnum adPos : AdPosEnum.values()) {
request.getServletContext().setAttribute(adPos.name(), adService.list(adPos.name()));
}
Cookie[] cookies = request.getCookies();
if(cookies!=null&&cookies.length!=0){
for (Cookie cookie : cookies) {
if(cookie.getName().equals("token")){
String token=cookie.getValue();
UserExample userExample = new UserExample();
userExample.createCriteria()
.andTokenEqualTo(token);
List<User> users = userMapper.selectByExample(userExample);
if(users.size()!=0){
User user = users.get(0);
UserAccountExample userAccountExample = new UserAccountExample();
userAccountExample.createCriteria().andUserIdEqualTo(user.getId());
List<UserAccount> userAccounts = userAccountMapper.selectByExample(userAccountExample);
UserAccount userAccount = userAccounts.get(0);
request.getSession().setAttribute("user",user);
request.getSession().setAttribute("userAccount",userAccount);
Long unreadCount = notificationService.unreadCount(users.get(0).getId());
request.getSession().setAttribute("unreadCount", unreadCount);
System.out.println("用戶組ID:"+userAccount.getGroupId());
}
break;
}
}
}
return true;
}
我們在調試中,打印登錄用戶的用戶組ID,發現用戶每次訪問一個頁面,preHandle()方法都會執行24次之多。在大訪問量下,這對服務器和數據庫都會造成極大的壓力,從而影響到性能。
3.解決方法
我們發現攔截器會對頁面用到的外部CSS,js,圖片文件等靜態資源也會進行攔截,所以我們只需要過濾掉隊靜態資源的攔截即可。我們在preHandle()方法的最前部加入以下一行代碼:
if (handler instanceof ResourceHttpRequestHandler)
return true;
再調試一次,發現只打印一次了。問題解決!
原文地址:https://niter.cn/p/100
歡迎訪問我的開源社區:https://niter.cn/