可單例開發、典型的教科書式的mvc構架----springmvc----day02(六)
10.攔截器
10.1定義攔截器,實現HandlerInterceptor介面,介面中提供三個方法。
public class HandlerInterceptor1 implements HandlerInterceptor {
// 執行Handler完成執行此方法
// 應用場景:統一的異常處理,統一日誌處理
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception exception) throws Exception {
System.out.println("HandlerInterceptor1.......afterComletion");
}
// 進入Handler方法之後,再返回modelAndView之前執行
// 應用場景表示從modelAndView出發:將公用的模型資料(選單導航)在這裡傳到檢視,也可也在這裡指定檢視
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("HandlerInterceptor1.......postHandle");
}
// 進入Handler方法之前執行
// 使用者身份認證、身份授權
// 比如身份認證,如果認證通過表示當前使用者沒有登入,需要此方法攔截不再向下執行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// return false表示攔截,不再向下執行
// return trueb表示方向
System.out.println("HandlerInterceptor1.......preHandle");
return true;
}
}
10.2攔截器配置
10.2.1針對HandlerMapping配置
springmvc攔截器針對HandlerMapping進行攔截設定,如果在某個HandlerMapping中配置攔截,經過該HandlerMapping對映成功的handler最終使用該攔截器。
<bean
class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="handlerInterceptor1"/>
<ref bean="handlerInterceptor2"/>
</list>
</property>
</bean>
<bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/>
<bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>
一般不推薦使用
10.2.2類似全域性的攔截器
springmvc配置類似全域性的攔截器,springmvc框架將配置的類似全域性的攔截器注入到每個HandlerMapping中。
<!-- 攔截器 -->
<mvc:interceptors>
<!-- 多個攔截器,順序執行 -->
<!-- 登入認證攔截器 -->
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.changemax.ssm.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
<mvc:interceptor>
<!-- /**表示所有url路徑包括子路徑 -->
<mvc:mapping path="/**" />
<bean class="com.changemax.ssm.interceptor.HandlerInterceptor1"></bean>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.changemax.ssm.interceptor.HandlerInterceptor2"></bean>
</mvc:interceptor>
</mvc:interceptors>
10.3攔截測試
10.3.1測試需求
測試多個攔截器各個方法執行時機。
10.3.2編寫兩個攔截
10.3.3兩個攔截器都放行
總結:
preHandler方法按順序執行,
postHandler和afterCompletion按攔截器配置的逆向順序執行。
10.3.4攔截器1放行,攔截器2不放行
總結:
攔截器1放行,攔截器2preHandler才會執行。
攔截器2preHandler不放行,攔截器2postHandle和afterCompletion不會執行。
只要有一個攔截器不放行,postHandle不會執行
10.3.5小結
根據測試結果,對攔截器應用。
比如:統一日誌處理攔截器,需要該 攔截器preHandle一定要放行,且將它放在攔截器連結中第一個位置。
比如:登陸認證攔截器,放在攔截器連結中第一個位置。許可權校驗攔截器,放在登陸認證攔截器之後。(因為登陸通過後才校驗許可權)
10.4 攔截器應用(實現登陸認證)
10.4.1需求:
1.使用者請求url
2.攔截器進行攔截校驗
如果請求的url是公開地址(無需登入即可訪問的url),讓放行
如果使用者session不存在跳轉的登入頁面
如果使用者session存在放行,繼續操作。
10.4.2登入controller方法
@Controller
public class LoginController{
// 登入
@RequestMapping("/login")
public String login(HttpSession session, String username, String password) throws Exception {
// 呼叫service進行使用者身份驗證
// ..
// 在session中儲存使用者身份資訊
session.setAttribute("username", username);
return "redirect:/items/queryItems.action";
}
// 退出
@RequestMapping("/logout")
public String logout(HttpSession session) throws Exception {
// 呼叫service進行使用者身份驗證
// ..
// 在session中儲存使用者身份資訊
session.invalidate();
return "redirect:/items/queryItems.action";
}
}
10.4.3登陸認證攔截實現
10.4.3.1程式碼實現
public class LoginInterceptor implements HandlerInterceptor {
// 執行Handler完成執行此方法
// 應用場景:統一的異常處理,統一日誌處理
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception exception) throws Exception {
System.out.println("HandlerInterceptor1.......afterComletion");
}
// 進入Handler方法之後,再返回modelAndView之前執行
// 應用場景表示從modelAndView出發:將公用的模型資料(選單導航)在這裡傳到檢視,也可也在這裡指定檢視
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("HandlerInterceptor1.......postHandle");
}
// 進入Handler方法之前執行
// 使用者身份認證、身份授權
// 比如身份認證,如果認證通過表示當前使用者沒有登入,需要此方法攔截不再向下執行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 獲取請求的url
String url = request.getRequestURL().toString();
// 判斷url是否為公開地址(實際使用時公開地址配置配置檔案中)
if (url.indexOf("login.action") >= 0) {
// 如果進行登入提交,就放行
return true;
}
// 判斷session
HttpSession session = request.getSession();
// 從session取出使用者的身份資訊
String username = (String) session.getAttribute("username");
if (username != null) {
return true;
}
//表示使用者身份需要認證
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
// return false表示攔截,不再向下執行
// return trueb表示方向
System.out.println("HandlerInterceptor1.......preHandle");
return false;
}
}
10.4.3.2攔截器配置
<!-- 攔截器 -->
<mvc:interceptors>
<!-- 多個攔截器,順序執行 -->
<!-- 登入認證攔截器 -->
<mvc:interceptor>
<!-- /**表示所有url路徑包括子路徑 -->
<mvc:mapping path="/**" />
<bean class="com.changemax.mas.interceptor.AdminInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>