1. 程式人生 > >可單例開發、典型的教科書式的mvc構架----springmvc----day02(六)

可單例開發、典型的教科書式的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>