SpringBoot-攔截器

  1. 介紹

    1. 見名知意,用於攔截controller請求,在進入controller以前進行一些處理,若是能夠,進入controller處理方法,若是不能夠,則不會進入controller處理方法。基本原理是採用AOP面相切面編程,基於動態代理,在所執行的controller方法先後添加代碼,這就是攔截器java

    2. 攔截器不依賴任何Servlet容器
    3. 攔截器只能對controller處理方法的url進行攔截,這裏提到過濾器則能夠對全部的請求進行過濾
    4. 在controller的生命週期中,攔截器能夠屢次被調用,而過濾器只能在容器初始化時被調用一次
  2. 實列(IDEA)

    1. 建立簡單的SpringBoot項目,原始的便可,不須要改動,就用內置的Tomcat就行
    2. 編寫POJO類
       1 @Data
       2 @AllArgsConstructor
       3 @RequiredArgsConstructor
       4 @NoArgsConstructor
       5 public class User implements Serializable {
       6                 private Integer id;
       7     @NonNull    private String name;
       8     @NonNull    private String sex;
       9                 private Integer age;
      10
      11 /* 12 * 類上面的註解是使用的lombok插件,不知道的朋友可自行查閱資料 13 * */ 14 }
    3. 建立UserController處理器類
       1 import org.springframework.web.bind.annotation.RequestMapping;
       2 import org.springframework.web.bind.annotation.RestController;
       3  
       4 import javax.servlet.http.HttpSession;
       5 import java.util.List;
       6 
       7 @RestController
       8 @RequestMapping("/user/")
       9 public class UserController {
      10     //模擬user的增刪改查操做,假設增刪改必須有用戶且已登陸纔可執行
      11     @RequestMapping("delete")
      12     public String delete(){
      13         return "delete操做";
      14     }
      15     @RequestMapping("insert")
      16     public String insert(){
      17         return "insert操做";
      18     }
      19     @RequestMapping("update")
      20     public String update(){
      21         return "update操做";
      22     }
      23     @RequestMapping("login")
      24     public String login(HttpSession session){
      25         //模擬登陸效果,不查詢數據庫
      26         User user = new User("admin","男");
      27         session.setAttribute("user",user);
      28         return "登陸成功";
      29     }
      30     @RequestMapping("logout")
      31     public String logout(HttpSession session){
      32         //登出
      33         session.removeAttribute("user");
      34         return "登出成功";
      35     }
      36 }
    4. 編寫LoginInterceptor攔截器類
      1. 可使用實現HandlerInterceptor接口,也可直接繼承HandlerInterceptorAdapter抽象類,由於這個類就是對HandlerInterceptor接口的一個空實現,看這邊源碼,注意方法上面的文檔註釋,若是選擇HandlerInterceptorAdapter,再次重寫這三個方法便可
        /*
         * Copyright 2002-2017 the original author or authors.
         *
         * Licensed under the Apache License, Version 2.0 (the "License");
         * you may not use this file except in compliance with the License.
         * You may obtain a copy of the License at
         *
         *      https://www.apache.org/licenses/LICENSE-2.0
         *
         * Unless required by applicable law or agreed to in writing, software
         * distributed under the License is distributed on an "AS IS" BASIS,
         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         * See the License for the specific language governing permissions and
         * limitations under the License.
         */
        
        package org.springframework.web.servlet.handler;
        
        import javax.servlet.http.HttpServletRequest;
        import javax.servlet.http.HttpServletResponse;
        
        import org.springframework.lang.Nullable;
        import org.springframework.web.servlet.AsyncHandlerInterceptor;
        import org.springframework.web.servlet.ModelAndView;
        
        /**
         * Abstract adapter class for the {@link AsyncHandlerInterceptor} interface,
         * for simplified implementation of pre-only/post-only interceptors.
         *
         * @author Juergen Hoeller
         * @since 05.12.2003
         */
        public abstract class HandlerInterceptorAdapter implements AsyncHandlerInterceptor {
        
            /**
             * This implementation always returns {@code true}.
             */
            @Override
            public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                    throws Exception {
        
                return true;
            }
        
            /**
             * This implementation is empty.
             */
            @Override
            public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                    @Nullable ModelAndView modelAndView) throws Exception {
            }
        
            /**
             * This implementation is empty.
             */
            @Override
            public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
                    @Nullable Exception ex) throws Exception {
            }
        
            /**
             * This implementation is empty.
             */
            @Override
            public void afterConcurrentHandlingStarted(HttpServletRequest request, HttpServletResponse response,
                    Object handler) throws Exception {
            }
        
        }
      2. 此處我選擇實現接口
         1 import org.springframework.web.servlet.HandlerInterceptor;
         2 import org.springframework.web.servlet.ModelAndView;
         3 
         4 import javax.servlet.http.HttpServletRequest;
         5 import javax.servlet.http.HttpServletResponse;
         6 import java.io.IOException;
         7 
         8 /**
         9  * 登陸驗證
        10  */
        11 public class LoginInterceptor implements HandlerInterceptor {
        12     @Override
        13     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
        14         //從session中取出user,若是取出的對象對空,向響應流中給出信息,而且返回false,再也不進入controller方法
        15         //                   若是取出的對象不爲空,表示用戶已經登陸,則返回true,繼續進入controller方法
        16         System.out.println("LoginInterceptor--preHandle");
        17         boolean hasAlready=false;
        18         Object user = request.getSession().getAttribute("user");
        19         if(user!=null) {
        20             hasAlready = true;
        21         }else {
        22             response.getWriter().write("<h1 style='color:red;'>not login</h1>");
        23         }
        24 
        25         return hasAlready;
        26     }
        27 
        28     @Override
        29     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
        30         System.out.println("LoginInterceptor--postHandle");
        31     }
        32 
        33     @Override
        34     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        35         System.out.println("LoginInterceptor--afterCompletion");
        36     }
        37 }
    5. 編寫MvcConfigurer類,代碼以下
       1 import cn.bdqn.ylm.sssmc.interceptor.LoginInterceptor;
       2 import org.springframework.context.annotation.Configuration;
       3 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
       4 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
       5 
       6 import java.util.ArrayList;
       7 import java.util.List;
       8 
       9 @Configuration
      10 public class MvcConfigurer implements WebMvcConfigurer {
      11     @Override
      12     public void addInterceptors(InterceptorRegistry registry) {
      13         LoginInterceptor li=new LoginInterceptor();
      14         List<String> pathPatterns=new ArrayList<>();
      15         List<String> excludePathPatterns=new ArrayList<>();
      16         pathPatterns.add("/**");
      17         excludePathPatterns.add("/user/log**");
      18 
      19         //pathPatterns表示全部的信息須要攔截的請求,這裏寫了/**,所有攔截
      20         //excludePathPatterns表示不攔截的請求,這裏除了用戶退出和登陸操做之外,其餘的都須要由用戶登陸才能夠操做
      21         registry.addInterceptor(li).addPathPatterns(pathPatterns).excludePathPatterns(excludePathPatterns);
      22 
      23     }
      24 }
    6. OK,能夠在瀏覽器訪問觀察結果了
      1. 首先訪問/user/logout,瀏覽器顯示登出成功即爲成功,由於攔截器中設置了不攔截/user/log**請求
      2. 瀏覽器訪問/user/增刪改,瀏覽器顯示not login便可成功,表示用戶沒有登陸,被攔截器攔下而且向響應流中寫出內容
      3. 瀏覽器訪問/user/login,瀏覽器顯示登陸成功,此時session已經存在user對象,再次訪問/user/增刪改,若是增刪改操做正常執行,而且頁面顯示對應的操做的成功提示即爲正常,表示攔截器正常獲取session中的對象判斷對象狀態放行攔截器
    7. 推薦進一步學習
      1. 攔截器的三個方法的執行時機、特徵等
      2. 攔截器鏈(簡單提一下:多攔截器會造成攔截器鏈,好比能夠先用一個攔截器驗證用戶是否登陸,若是登陸,下一個攔截器再次驗證權限問題)
      3. 過濾器、監聽器
      4. 攔截器與ServletAPI的過濾器、監聽器的不一樣
      5. 那麼這些知識點我在這裏並無詳細講,你們本身下去學習
相關文章
相關標籤/搜索