天天看點

Spring攔截器的實作以及通過注解實作攔截

本篇是本人記錄對于Spring的攔截器簡單的使用記錄,以及通過自定義注解的方式實作其攔截目的

首先看一下簡單的實作

第一步:定義一個測試類,用于向背景發送請求

@RestController
public class Hello {

    @RequestMapping("/sayHello")
    public String sayHello(){
        return "Hello,World!";
    }
    
    @RequestMapping("/helloInterceptor")
    public String helloInterceptor(){
        return "通路helloInterceptor";
    }

}
           

第二步:定義一個自己的攔截器,需要實作Spring提供的HandlerInterceptor接口

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
    	Object handler) throws Exception {
    		response.setContentType("application/json; charset=utf-8");
            String a = request.getParameter("a");
            if(null != a && a.equals("a"){
                return true;
            }else {
                response.getWriter().print("你通路的資源需要登入");
                return false;
            }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, 
    	Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
    	Object handler, Exception ex) throws Exception {

    }
}
           

這一步中,我們要求所有請求都需要帶上指定的參數a,參數的值也是a,如果向背景發送到請求沒有加上這個參數值的話,那麼就會被攔截,反之則不會;

第三步:将上面的攔截器添加到攔截器鍊中,這裡需要定義一個實作了WebMvcConfigurer接口的配置類

@Configuration
public class MyInterceptorConfigurer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    	//這種方式會攔截所有請求
    	//registry.addInterceptor(new MyInterceptor());
    	//這種方式會攔截指定的請求
        registry.addInterceptor(new MyInterceptor()).addPathPatterns("/helloInterceptor");
    }
}
           

好了,以上三部完成後,一個簡單的web請求攔截器就已經可以使用了

接下來,啟動項目,并在浏覽器中進行通路

第一次請求

:sayHello

Spring攔截器的實作以及通過注解實作攔截

OK我們看到,這次請求未被攔截,順利執行了

這是因為我們在攔截器鍊中指定了隻對**helloInterceptor()**的通路進行攔截

第二次請求

:helloInterceptor

Spring攔截器的實作以及通過注解實作攔截

OK我們看到,這次的請求被攔截了,因為我們沒有按要求帶上指定的參數

第三次請求:

helloInterceptor?a=a

Spring攔截器的實作以及通過注解實作攔截

好的我們可以看到,當我們按照要求帶上指定的參數後,那麼請求是可以正确到達我們的目标方法的

通過上面的測試,可以看到,上面的方法雖然可以對通路請求進行攔截,但是當我們項目中的接口很多的時候,往往需要我們對大量的通路請求的進行攔截指定

那麼接下來,再來看一下,如何通過注解,來實作對通路請求的攔截

首先,我們定義一個自定義的注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LoginIntercept {

}

           

自定義注解的各個參數這裡就不進行過多的描述了,這并不是本篇的重點;

自定義注解定義好了之後,我們首先想修改一下我們的測試類

@RestController
public class Hello {

    @RequestMapping("/sayHello")
    public String sayHello(){
        return "Hello,World!";
    }

    @LoginIntercept
    @RequestMapping("/helloInterceptor")
    public String helloInterceptor(){
        return "通路helloInterceptor";
    }

}
           

注意,我們在 /helloInterceptor方法的上面,加上了我們自定義的注解,而**/sayHello**方法上面并沒有加

然後對原先的攔截器方法進行修改

public class MyInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, 
    	Object handler) throws Exception {
    	//擷取方法處理器
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        LoginIntercept loginIntercept = 
        	handlerMethod.getMethod()//這一步是擷取到我們要通路的方法
        	//然後根據我們制定的自定義注解的Class對象來擷取到對應的注解
        	.getAnnotation(LoginIntercept.class);
        	
        //如果要通路的方法上沒有加這個注解,那麼就說明這個方法不需要攔截,否則就需要進行攔截
        if(null == loginIntercept){
            System.out.println("通路的方法無需攔截");
            return true;
        }else {
        response.setContentType("application/json; charset=utf-8");
        String a = request.getParameter("a");
        if(null != a && a.equals("a")){
                return true;
            }else {
                response.getWriter().print("請求被攔截");
                return false;
            }
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, 
    	Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, 
    	Object handler, Exception ex) throws Exception {

    }
}
           

最後修改一下我們的配置類

@Configuration
public class MyInterceptorConfigurer implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MyInterceptor());
    }
}
           

現在,我們的配置類将會對所有方法進行攔截,接下來我們看一下不同的通路結果

Spring攔截器的實作以及通過注解實作攔截
Spring攔截器的實作以及通過注解實作攔截
Spring攔截器的實作以及通過注解實作攔截

很顯然,通路的結果和之前的三次通路結果一模一樣,但是不同的是,當我們現在通路sayHello是,控制台輸出了一句話:通路的方法無需攔截

以上就是本人對于Spring攔截器的簡單實作以及通過自定義注解實作通路攔截的test記錄,其中的核心分别是Spring的

HandlerInterceptor接口

及其 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 方法

和Spring的

WebMvcConfigurer接口

及其 public void addInterceptors(InterceptorRegistry registry) 方法

繼續閱讀