RESTful API的拦截


title: RESTful API的拦截
tags: [Spring,restful,filter,aspect,interceptor]
date: 2018/5/12 23:46:25
categories:

  • 开发
  • java

总的来说拦截请求,我们在开发过程中会遇到以下3种方式

  • 自定义过滤器 Servlet Filter
  • Spring Mvc Interceptor
  • Aspect

自定义过滤器

特点和局限

  • 可以拿到原始的http请求和响应的信息

  • 但是拿不到真正处理请求的那个方法的信息,因为真正处理请求的方法信息不是由servlet提供的 ,一般是由mvc框架(如:spring mvc -> controller -> method() ) 提供的

关键代码

@Component
public class XXXFilter implements Filter{
 
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
			
        System.out.println("doFilter start");
		
		// 对request response 进行拦截处理
		
		// 放行给其它过滤器->处理业务
        chain.doFilter(request, response);
		
        System.out.println("doFilter finish");
    }

    ……
}

配置启用

  • xml(省略)

  • spring boot

    @Configuration
    public class WebConfig {
        @Bean
        public FilterRegistrationBean xxxFiler() {
            FilterRegistrationBean registrationBean = new FilterRegistrationBean();
            XXXFilter xxxFilter = new XXXFilter();
            registrationBean.setFilter(xxxFilter);
            List<String> urls = new ArrayList<>();
    		//url mapping 
            urls.add("/*");
            registrationBean.setUrlPatterns(urls);
            return registrationBean;
        }
    }
    

自定义拦截器

特点和局限

  • 既可以拿到原始的http请求和响应, 也可以拿到真正处理请求的方法的信息

  • 拿不到具体方法被调用时所传入的参数值

关键代码

@Component
public class XXXInterceptor implements HandlerInterceptor{

	// 该方法将在Controller处理之前进行调用
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        System.out.println("拦截 - 方法前置处理");

        System.out.println("处理类名:" + ((HandlerMethod)handler).getBean().getClass().getName());
        System.out.println("方法名:" +((HandlerMethod)handler).getMethod().getName());

		// true 表示放行调用处理方法 
        return true;
    }

	// 需要 preHandle 返回为true 
	// 当前请求进行处理之后,也就是Controller 方法调用之后执行,但是它会在DispatcherServlet 进行视图返回渲染之前被调用
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
            ModelAndView modelAndView) throws Exception {
        System.out.println("controller 方法处理完了");
		//我可以在这里对 modelAndView 做点什么  
    }
    // 需要 preHandle 返回为true 
	// 该方法将在整个请求结束之后,也就是在DispatcherServlet 渲染了对应的视图之后执行。这个方法的主要作用是用于进行资源清理工作
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
            throws Exception {
        System.out.println("拦截 - 请求后置处理");
        System.out.println("异常信息:" + ex);
    }

}

配置启用

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter{

    @Autowired
    private XXXInterceptor xxxInterceptor;
	
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
		// 注册拦截器
        registry.addInterceptor(xxxInterceptor);
    }

	/* ---------------------我是分隔线------------------------------ */
    @Bean
    public FilterRegistrationBean xxxFiler() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        XXXFilter xxxFilter = new XXXFilter();
        registrationBean.setFilter(xxxFilter);
        List<String> urls = new ArrayList<>();
		//url mapping 
        urls.add("/*");
        registrationBean.setUrlPatterns(urls);
        return registrationBean;
    }
}

Aspect增强

特点

  • 可以拿到方法被调用时传递进来的参数值
  • 拿不到原始的http请求和响应的对象

关键代码

// 定义一个切面并交给Spring容器管理
@Aspect
@Component
public class MyAspect {
	//定义切入点(1.在哪些方法上起作用 2.什么时候起作用)
    @Around("execution(* com.web.controller.UserController.*(..))")
    public Object handleControllerMethod(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("aspect into");
        //方法参数的数组
        Object[] args = pjp.getArgs();
		int i = 0;
        for (Object arg : args) {
            System.out.println("方法参数 "+(i++)+" : " + arg);
        }
        //执行实际方法
        Object object = pjp.proceed();
        System.out.println("aspect out");
        return object;
    }

}

3种方式的执行顺序

  • 假如同时存在这3种拦截,在整个请求响应中执行顺序如下:

    -> Filter -> Interceptor -> ControllerAdvice -> Aspect -> Controller

  • 如果发生异常

    检测异常的顺序就反过来了

    -> Controller -> Aspect -> ControllerAdvice -> Interceptor -> Filter -> tomcat

参考文章

CSDN_HCX's RESTful API的拦截

上一篇:SpringBoot学习9之注册三大组件


下一篇:springboot配置druid数据源及其监控