Spring Security(一):RESTful API的拦截之过滤器、拦截器、切片介绍

Spring Security框架使用过程中会有很多Restful API的拦截操作,像各种过滤器拦截器以及Spring AOP的使用,所以在学习Spring Security之前很有必要对他们进行一个简单介绍。

过滤器(Filter)

简介

  • JavaWeb三大组件(Servlet、Filter、Listener)之一,Web开发人员通过Filter技术,对web服务器管理的所有web资源(例如Jsp、Servlet、静态图片文件或静态html文件等)进行拦截,从而实现一些特殊的功能。

使用场景

  • 主要用于对用户请求进行预处理,也可以对HttpServletResponse进行后处理
  • 使用Filter的完整流程:Filter对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。

简单演示

/**
 * 过滤器演示:直接定义一个类实现Filter接口,记得需要配置该过滤器,或者直接加@Component自动配置
 *
 * @author HuaDong
 * @date 2020/4/11 18:38
 */
@Component
public class TimeFilter implements Filter {

    /**
     * 容器销毁的时候调用
     */
    @Override
    public void destroy() {
        System.out.println("time filter destroy");
    }

    /**
     * Web服务器每次在调用Web资源之前,都会先调用filter的doFilter方法
     */
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        System.out.println("time filter start");
        long start = System.currentTimeMillis();
        chain.doFilter(request, response);
        System.out.println("time filter 耗时:" + (System.currentTimeMillis() - start));
        System.out.println("time filter finish");
    }

    /**
     * 容器启动时候调用
     */
    @Override
    public void init(FilterConfig arg0) throws ServletException {
        System.out.println("time filter init");
    }
}

拦截器(Interceptor)

简介

  • Java 里的拦截器是动态拦截 action 调用的对象,它提供了一种机制可以使开发者可以定义在一个 action 执行的前后执行的代码,也可以在一个 action 执行前阻止其执行,同时也提供了一种可以提取 action 中可重用部分的方式。通俗来说就是可以拦截一个请求,对请求进行Controller方法的调用之前之后或者抛出异常时的一个自定义的操作。

使用场景

  • 可以对请求进行一个登录凭证的校验
  • 可以对请求响应之后加上一些统一的响应字段等。

简单演示

  • 声明拦截器
/**
 * 拦截器演示:定义一个类实现HandlerInterceptor接口
 *
 * @author HuaDong
 * @date 2020/4/11 19:21
 */
@Component
public class TimeInterceptor implements HandlerInterceptor {

    /**
     * 请求Controller方法之前:返回false表示被拦截不再往下执行,即不再调用Controller方法
     */
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("preHandle");
		
		System.out.println(((HandlerMethod)handler).getBean().getClass().getName());
		System.out.println(((HandlerMethod)handler).getMethod().getName());
		
		request.setAttribute("startTime", System.currentTimeMillis());
		return true;
	}

    /**
     * 请求Controller方法之后
     */
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("postHandle");
		Long start = (Long) request.getAttribute("startTime");
		System.out.println("time interceptor 耗时:"+ (System.currentTimeMillis() - start));
	}

	/**
     * 抛出异常之后 postHandle 方法不会被调用,无论是否抛出异常 afterCompletion 方法都会被调用
     */
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		System.out.println("afterCompletion");
		Long start = (Long) request.getAttribute("startTime");
		System.out.println("time interceptor 耗时:"+ (System.currentTimeMillis() - start));
		System.out.println("ex is "+ex);
	}
}
  • 注册拦截器
/**
 * 注册拦截器:创建一个config类,继承WebMvcConfigurerAdapter,将我们上面定义的拦截器注册到InterceptorRegistry中
 * 
 * @author HuaDong
 * @date 2020/4/11 19:32
 */
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
	
	@Autowired
	private TimeInterceptor timeInterceptor;
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(timeInterceptor);
	}
}

缺点

  • preHandle方法无法通过handler拿到一些封装之后的请求参数,因为封装参数的方法是在preHandle之后进行的。
  • 查看源码:org.springframework.web.servlet.DispatcherServlet#doService --> doDispatch
	// 实际 preHandler 的调用
	if (!mappedHandler.applyPreHandle(processedRequest, response)) {
	    return;
	}
	
	// 参数封装处理逻辑
	mv = ha.handle(processedRequest, response, mappedHandler.getHandler());
	if (asyncManager.isConcurrentHandlingStarted()) {
	    return;
	}

切片(Aspect)

简介

  • AOP,面向切面编程,采用一种称为“横切”的技术,将涉及多业务流程的通用功能抽取并单独封装,形成独立的切面,在合适的时机将这些切面横向切入到业务流程指定的位置中。

使用场景

  • 权限控制
  • 缓存控制
  • 事务控制
  • 审计日志
  • 性能监控
  • 分布式追踪
  • 异常处理

简单演示


发布了117 篇原创文章 · 获赞 309 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/qq_36221788/article/details/105457350