五
本篇是本人記錄對于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
OK我們看到,這次請求未被攔截,順利執行了
這是因為我們在攔截器鍊中指定了隻對**helloInterceptor()**的通路進行攔截
第二次請求
:helloInterceptor
OK我們看到,這次的請求被攔截了,因為我們沒有按要求帶上指定的參數
第三次請求:
helloInterceptor?a=a
好的我們可以看到,當我們按照要求帶上指定的參數後,那麼請求是可以正确到達我們的目标方法的
通過上面的測試,可以看到,上面的方法雖然可以對通路請求進行攔截,但是當我們項目中的接口很多的時候,往往需要我們對大量的通路請求的進行攔截指定
那麼接下來,再來看一下,如何通過注解,來實作對通路請求的攔截
首先,我們定義一個自定義的注解
@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());
}
}
現在,我們的配置類将會對所有方法進行攔截,接下來我們看一下不同的通路結果
很顯然,通路的結果和之前的三次通路結果一模一樣,但是不同的是,當我們現在通路sayHello是,控制台輸出了一句話:通路的方法無需攔截
以上就是本人對于Spring攔截器的簡單實作以及通過自定義注解實作通路攔截的test記錄,其中的核心分别是Spring的
HandlerInterceptor接口
及其 public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) 方法
和Spring的
WebMvcConfigurer接口
及其 public void addInterceptors(InterceptorRegistry registry) 方法