博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring Security构建Rest服务-0400-使用切片拦截rest服务
阅读量:4351 次
发布时间:2019-06-07

本文共 7782 字,大约阅读时间需要 25 分钟。

Restful API的拦截:

  1,过滤器(Filter)

  2,拦截器(Interceptor)

  3,切片(Aspect)

1,过滤器

和传统javaweb一鸟样,例,记录controller执行时间过滤器,会过滤所有url:

/** * 记录执行时间过滤器 * ClassName: TimeFilter  * @Description: TODO * @author lihaoyang * @date 2018年2月26日 */@Component //声明为spring组件,springboot项目没有web.xml直接声明为组件public class TimeFilter implements Filter {    @Override    public void destroy() {        System.err.println("time filter destory...");    }    @Override    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)            throws IOException, ServletException {        System.err.println("time filter start");        long startTime = new Date().getTime();        chain.doFilter(request, response); //执行其他过滤器链        System.err.println("time filter 耗时:"+(new Date().getTime()-startTime));        System.err.println("time filter end");    }    @Override    public void init(FilterConfig arg0) throws ServletException {        System.err.println("time filter init...");    }}

在传统javaweb我们需要在web.xml配置过滤器,springboot没有web.xml,只需要在类上加上@Component注解告诉spring这是一个组件即可。如果我们需要引入第三方的一些过滤器,是没办法加注解的,此时就需要使用java来代替配置文件了:

假设自定义的TimeFilter即为第三方Filter,注释掉@Component注解

只需加上一个配置类,相当于xml配置即可:

package com.imooc.web.config;import java.util.ArrayList;import java.util.List;import org.springframework.boot.web.servlet.FilterRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import com.imooc.web.filter.TimeFilter;@Configurationpublic class WebConfig {    @Bean    public FilterRegistrationBean timeFilter(){        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();                TimeFilter timeFilter = new TimeFilter();        filterRegistrationBean.setFilter(timeFilter);        //指定要过滤的url        List
urls = new ArrayList<>(); urls.add("/*"); filterRegistrationBean.setUrlPatterns(urls); return filterRegistrationBean; }}

filter只能对request和response进行操作,因为他是J2EE的规范,所以这个请求最终是哪一个controller的哪个方法来处理的是不知道的。因为controller是spring的概念。如果需要知道这些信息,就需要用拦截器。

2,拦截器

自定义拦截器,加上@Component 声明为spring组件,记录调用耗时:

package com.imooc.web.interceptor;import java.util.Date;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.stereotype.Component;import org.springframework.web.method.HandlerMethod;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;/** * 记录调用耗时的拦截器 * ClassName: TimeInterceptor  * @Description: TODO * @author lihaoyang * @date 2018年2月26日 */@Component //声明为spring组件public class TimeInterceptor implements HandlerInterceptor{    //进入controller之前执行    @Override    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {        System.err.println("preHandle...");                System.err.println(((HandlerMethod)handler).getBean().getClass().getName());//哪个类        System.err.println(((HandlerMethod)handler).getMethod()); //哪个方法        request.setAttribute("startTime", new Date().getTime());//调用开始计时        return true;    }    //进入controller之中执行    @Override    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)            throws Exception {        System.err.println("postHandle...");        Long start = (Long) request.getAttribute("startTime");        System.err.println("time interceptor 耗时:"+(new Date().getTime()-start));    }    //controller执行完之后执行    @Override    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)            throws Exception {                System.err.println("afterCompletion...");        Long start = (Long) request.getAttribute("startTime");        System.err.println("time interceptor 耗时:"+(new Date().getTime()-start));        //如果调用有异常,这个Exception会有信息        System.err.println("exception:"+ex);    }}

java配置,继承WebMvcConfigurerAdapter类重写addInterceptors方法,定义自己的拦截器

package com.imooc.web.config;import java.util.ArrayList;import java.util.List;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.web.servlet.FilterRegistrationBean;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.InterceptorRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;import com.imooc.web.filter.TimeFilter;import com.imooc.web.interceptor.TimeInterceptor;@Configurationpublic class WebConfig extends WebMvcConfigurerAdapter{    //由于TimeInterceptor声明为了spring组件,直接注入进来    @Autowired    private TimeInterceptor timeInterceptor;    /**     * 实现WebMvcConfigurerAdapter,重写addInterceptors方法添加拦截器     */    @Override    public void addInterceptors(InterceptorRegistry registry) {        registry.addInterceptor(timeInterceptor);    }    @Bean    public FilterRegistrationBean timeFilter(){        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();                TimeFilter timeFilter = new TimeFilter();        filterRegistrationBean.setFilter(timeFilter);        //指定要过滤的url        List
urls = new ArrayList<>(); urls.add("/*"); filterRegistrationBean.setUrlPatterns(urls); return filterRegistrationBean; }}

调用http://localhost:8080/user/1

 

可以看到能获取到所调用的Controller以及哪个方法:

time filter start

preHandle...
com.imooc.web.controller.UserController
public com.imooc.dto.User com.imooc.web.controller.UserController.getInfo(java.lang.String)
afterCompletion...
time interceptor 耗时:34
exception:null
time filter 耗时:50
time filter end
time filter start
time filter 耗时:15
time filter end

 注意,如果是抛出了自定义异常,做过了处理,afterCompletion里就不会打印异常信息了。

拦截器能获取到所要处理的控制器类和方法,但是没办法获取到具体要处理的参数,查看DispatcherServlet源码的doDispatch方法就可以看到,执行拦截器的时候,还没有组装参数,把请求的参数映射成为contrller里的参数,所以取不到具体的参数值,如果想获取参数值,就需要用到第三个拦截机制spring的AOP,自定义切面

3,切片

TimeAspect切面类:

package com.imooc.web.aspect;import java.util.Date;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.springframework.stereotype.Component;/** * 调用耗时切片 * ClassName: TimeAspect  * @Description: TODO * @author lihaoyang * @date 2018年2月26日 */@Aspect@Componentpublic class TimeAspect {    /**     *      */    @Around("execution(* com.imooc.web.controller.UserController.*(..))")    public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable{        System.err.println(">>>> 进入  TimeAspect start  >>>>>");                Object[] args = pjp.getArgs();        if(args.length > 0){            for (Object arg : args) {                System.err.println("arg is "+arg);            }        }        long start = new Date().getTime();                Object object = pjp.proceed();        System.err.println("TimeAspect 调用耗时:"+(new Date().getTime()-start));        System.err.println(">>>>   TimeAspect 结束  >>>>>");                return object;    }}

访问:http://localhost:8080/user/1可以看到能够取到参数1

=======time filter start======

++++++ 进入 preHandle...+++++++
com.imooc.web.controller.UserController$$EnhancerBySpringCGLIB$$533f819c
public com.imooc.dto.User com.imooc.web.controller.UserController.getInfo(java.lang.String)
>>>> 进入 TimeAspect start >>>>>
arg is 1
>>>>>>进入User Controller --> getInfo 方法
1
TimeAspect 调用耗时:0
>>>> TimeAspect 结束 >>>>>
postHandle...
time interceptor 耗时:1
time interceptor 耗时:1
exception:null
+++++ afterCompletion +++++++
time filter 耗时:5
=======time filter end=======
=======time filter start======
time filter 耗时:2
=======time filter end=======

三者调用顺序:

 代码github:

转载于:https://www.cnblogs.com/lihaoyang/p/8472374.html

你可能感兴趣的文章
4.1 分解条件式
查看>>
关于C++ const成员的一些细节
查看>>
《代码大全》学习摘要(五)软件构建中的设计(下)
查看>>
C#检测驱动是否安装的问题
查看>>
web-4. 装饰页面的图像
查看>>
微信测试账户
查看>>
算法练习题
查看>>
学习使用Django一 安装虚拟环境
查看>>
Hibernate视频学习笔记(8)Lazy策略
查看>>
CSS3 结构性伪类选择器(1)
查看>>
IOS 杂笔-14(被人遗忘的owner)
查看>>
前端基础之BOM和DOM
查看>>
[T-ARA/筷子兄弟][Little Apple]
查看>>
编译Libgdiplus遇到的问题
查看>>
【NOIP 模拟赛】Evensgn 剪树枝 树形dp
查看>>
java学习笔记④MySql数据库--01/02 database table 数据的增删改
查看>>
程序员最想得到的十大证件,你最想得到哪个?
查看>>
jQueru中数据交换格式XML和JSON对比
查看>>
form表单序列化后的数据转json对象
查看>>
一般处理程序在VS2012中打开问题
查看>>