008 RestFul API 拦截器

一:任务

1.任务

  过滤器Filter

  拦截器Interceptor

  切片Aspect

二:过滤器

1.新建包

  

2.自定义过滤器程序

  加了注解,这个过滤器在springboot中就起作用了

 1 package com.cao.web.filter;
 2 
 3 import java.io.IOException;
 4 import java.util.Date;
 5 
 6 import javax.servlet.Filter;
 7 import javax.servlet.FilterChain;
 8 import javax.servlet.FilterConfig;
 9 import javax.servlet.ServletException;
10 import javax.servlet.ServletRequest;
11 import javax.servlet.ServletResponse;
12 
13 import org.springframework.stereotype.Component;
14 
15 //使得过滤器起作用
16 @Component
17 public class TimeFilter implements Filter {
18 
19     @Override
20     public void init(FilterConfig filterConfig) throws ServletException {
21         System.out.println("time filter init");
22 
23     }
24 
25     @Override
26     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
27             throws IOException, ServletException {
28         System.out.println("time filter start");
29         //进行下一个调用链
30         long start=new Date().getTime();
31         chain.doFilter(request, response);
32         System.out.println("time filter 耗时: "+(new Date().getTime()-start));
33         System.out.println("time filter finish");
34 
35     }
36 
37     @Override
38     public void destroy() {
39         System.out.println("time filter destroy");
40 
41     }
42 
43 }

  将要访问的控制器

 1     @JsonView(User.UserDetailView.class)
 2     @GetMapping(value="/{id:\d+}")
 3     public User getInfo(@PathVariable(value="id") String idid){
 4         /**
 5          *  演示filter调用
 6          */
 7         System.out.println("进入getInfo服务");
 8         
 9         System.out.println("idtt="+idid);
10         User user=new User();
11         user.setUsername("tom");
12         return user;
13         /**
14          *  下面的主要是演示Spring booter异常的处理机制,现在先注释掉
15          */
16 //        throw new UserNotExistException(idid);
17         
18     }

3.效果

  先启动,这个时候,过滤器一样会被启动

  

  进行访问

  

  效果

  

4.引用第三方Filter,加到过滤器链上

  在Spring boot上没有web.xml。

  新建一个过滤器,用于表示第三方的过滤器

 1 package com.cao.web.filter;
 2 
 3 import java.io.IOException;
 4 import java.util.Date;
 5 
 6 import javax.servlet.Filter;
 7 import javax.servlet.FilterChain;
 8 import javax.servlet.FilterConfig;
 9 import javax.servlet.ServletException;
10 import javax.servlet.ServletRequest;
11 import javax.servlet.ServletResponse;
12 
13 import org.springframework.stereotype.Component;
14 
15 /**
16  * 假设这里是一个第三方的Filter,用来演示
17  * @author dell
18  *
19  */
20 public class TimeFilter2 implements Filter {
21 
22     @Override
23     public void init(FilterConfig filterConfig) throws ServletException {
24         System.out.println("time filter init2");
25 
26     }
27 
28     @Override
29     public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
30             throws IOException, ServletException {
31         System.out.println("time filter start2");
32         //进行下一个调用链
33         long start=new Date().getTime();
34         chain.doFilter(request, response);
35         System.out.println("time filter2 耗时: "+(new Date().getTime()-start));
36         System.out.println("time filter finish2");
37 
38     }
39 
40     @Override
41     public void destroy() {
42         System.out.println("time filter destroy2");
43 
44     }
45 
46 }

  新建一个包,为config

  新建一个类,为配置类

 1 package com.cao.web.config;
 2 
 3 
 4 import java.util.ArrayList;
 5 import java.util.List;
 6 
 7 import org.springframework.boot.web.servlet.FilterRegistrationBean;
 8 import org.springframework.context.annotation.Bean;
 9 import org.springframework.context.annotation.Configuration;
10 
11 import com.cao.web.filter.TimeFilter2;
12 
13 /**
14  *  这里相当于在配置web.xml
15  * @author dell
16  */
17 
18 //说明这是一个配置类
19 @Configuration
20 public class WebConfig {
21     @Bean
22     public FilterRegistrationBean timeFilter2() {
23         //加入Filter
24         FilterRegistrationBean registrationBean=new FilterRegistrationBean();
25         TimeFilter2 timeFilter2=new TimeFilter2();
26         registrationBean.setFilter(timeFilter2);
27         //起作用的url
28         List<String> url=new ArrayList<>();
29         url.add("/*");
30         registrationBean.setUrlPatterns(url);
31         //返回
32         return registrationBean;
33         
34     }
35 }

  启动

  

  访问

  

  发现,这里的服务只会走一次,外面包裹的是其过滤器的处理。

三:拦截器

1.过滤器的问题

  不知道是那个过滤器的哪个方法处理的。

  过滤器是Java EE提供的。

  拦截器是spring提供的。

  会拦截所有的控制器。

2.新建一个interception的包

  新建TimeInterception的程序

 1 package com.cao.web.config;
 2 
 3 
 4 import java.util.ArrayList;
 5 import java.util.List;
 6 
 7 import org.springframework.beans.factory.annotation.Autowired;
 8 import org.springframework.boot.web.servlet.FilterRegistrationBean;
 9 import org.springframework.context.annotation.Bean;
10 import org.springframework.context.annotation.Configuration;
11 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
12 import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
13 
14 import com.cao.web.filter.TimeFilter2;
15 import com.cao.web.interceptor.TimeInterceptor;
16 
17 /**
18  *  这里相当于在配置web.xml
19  * @author dell
20  */
21 
22 //说明这是一个配置类
23 @Configuration
24 public class WebConfig extends WebMvcConfigurerAdapter{
25     
26     //已经把TimeInterceptor变成了spring的一个组件了,现在需要autowired进来
27     @Autowired
28     private TimeInterceptor timeInterceptor;
29     
30     /**
31      * 这里是拦截器
32      */
33     @Override
34     public void addInterceptors(InterceptorRegistry registry) {
35         registry.addInterceptor(timeInterceptor);
36         super.addInterceptors(registry);
37     }
38     
39     /**
40      *   过滤器注册
41      * @return
42      */
43     @Bean
44     public FilterRegistrationBean timeFilter2() {
45         //加入Filter
46         FilterRegistrationBean registrationBean=new FilterRegistrationBean();
47         TimeFilter2 timeFilter2=new TimeFilter2();
48         registrationBean.setFilter(timeFilter2);
49         //起作用的url
50         List<String> url=new ArrayList<>();
51         url.add("/*");
52         registrationBean.setUrlPatterns(url);
53         //返回
54         return registrationBean;
55 //        return null;
56     }
57 }

  配置类

    因为只有一个Component的注解不能是的拦截器像过滤器一样可以工作

 1 package com.cao.web.interceptor;
 2 
 3 import java.util.Date;
 4 
 5 import javax.servlet.http.HttpServletRequest;
 6 import javax.servlet.http.HttpServletResponse;
 7 
 8 import org.springframework.stereotype.Component;
 9 import org.springframework.web.method.HandlerMethod;
10 import org.springframework.web.servlet.HandlerInterceptor;
11 import org.springframework.web.servlet.ModelAndView;
12 //使得成为Spring的组件
13 @Component
14 public class TimeInterceptor implements HandlerInterceptor {
15 
16     @Override
17     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
18             throws Exception {
19         System.out.println("preHandle init");
20         //比过滤器的优势,有第三个参数,handler
21         System.out.println("类:"+((HandlerMethod)handler).getBean().getClass().getName());
22         System.out.println("方法:"+((HandlerMethod)handler).getMethod().getName());
23         
24         //朝请求里添加属性
25         request.setAttribute("startTime", new Date().getTime());
26         return true;
27     }
28 
29     @Override
30     public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
31             ModelAndView modelAndView) throws Exception {
32         System.out.println("postHandle init");
33         //处理
34         Long start=(Long)request.getAttribute("startTime");
35         System.out.println("postHandle time interceptor 耗时: "+(new Date().getTime()-start));
36 
37     }
38 
39     @Override
40     public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
41             throws Exception {
42         System.out.println("afterCompletion init");
43     }
44 
45 }

  访问效果

  

四:切片

1.问题

  拦截器也有问题,不能拿到方法的具体参数。

  也是spring的核心功能之一,AOP

2.步骤

  

3.添加pom

1 <dependency>
2                 <groupId>org.springframework.boot</groupId>
3             <artifactId>spring-boot-starter-aop</artifactId>
4           </dependency>

4.新建包

  aspect包。

5.程序

  切片

 1 package com.cao.web.aspect;
 2 
 3 import java.util.Date;
 4 
 5 import org.aspectj.lang.ProceedingJoinPoint;
 6 import org.aspectj.lang.annotation.Around;
 7 import org.aspectj.lang.annotation.Aspect;
 8 import org.springframework.stereotype.Component;
 9 
10 //切片
11 @Aspect
12 //成为spring容器的一部分
13 @Component
14 public class TimeAcpect {
15     @Around("execution(* com.cao.web.controller.UserController.*(..))")
16     public Object handleControlledrMethod(ProceedingJoinPoint pjp) throws Throwable {
17         System.out.println("time aspect start");
18         Object[] args=pjp.getArgs();
19         for(Object arg : args) {
20             System.out.println("args is "+arg);
21         }
22         //
23         long start=new Date().getTime();
24         Object object=pjp.proceed();
25         System.out.println("time aspect 耗时: "+(new Date().getTime()-start));
26         //
27         System.out.println("time aspect end");
28         
29         return object;
30     }
31 }

  控制类

 1 @RequestMapping(value="/user/{id:\d+}",method=RequestMethod.GET)
 2     @JsonView(User.UserDetailView.class)
 3     @GetMapping(value="/{id:\d+}")
 4     public User getInfo(@PathVariable(value="id") String idid){
 5         /**
 6          *  演示filter调用
 7          */
 8         System.out.println("进入getInfo服务");
 9         
10         System.out.println("idtt="+idid);
11         User user=new User();
12         user.setUsername("tom");
13         return user;
14         /**
15          *  下面的主要是演示Spring booter异常的处理机制,现在先注释掉
16          */
17 //        throw new UserNotExistException(idid);
18         
19     }

6.效果

  访问

  

  控制台:

  

五:先后之行顺序

1.顺序

  上完上面的示例,应该没有问题了,这里使用一个图做一个总结。

  具体的文字就不再描述了,不懂的话,可以看上面的控制台效果

  

  

原文地址:https://www.cnblogs.com/juncaoit/p/9721378.html