在 Struts2 框架中,拦截器是其重要的组成部分,Struts2 的很多功能(数据校验、对象类型转换、文件上传等)都是构建在拦截器之上的。
通常情况下,开发者通过 Struts2 内建的拦截器可以完成大部分的操作,只有在内建拦截器不能满足需求时,才会自己扩展。可以这么说,Struts2 框架的简单易用,与拦截器的作用是分不开的。
拦截器(Interceptor)是 Struts2 框架的核心组成部分,它类似于 Servlet 中的过滤器,是一种可以在请求之前或之后执行的 Struts2 的组件,也可以将其理解为动态拦截 Action 调用的对象。
在早期的 MVC 框架中,通常会将一些通用的操作(如类型转换、数据校验、解析上传的文件等)强制写在控制器中,而这些常用操作又不是所有的请求都需要实现的,这就导致了框架的灵活性不足、可扩展性低等问题。
在 Struts2 框架中,这些通用的核心功能都放到了拦截器中实现,而不是集中放在核心控制器中实现。
由于框架中各个功能对应的拦截器是分开定义的,每个拦截器都可以完成单个功能,并且可以自由选择、灵活组合,而需要哪些拦截器时,只要在 struts.xml 配置文件中指定即可,所以 Struts2 框架的使用十分灵活。同时,由于在 Struts2 框架中支持自定义拦截器,所以其扩展性十分强大。
当多个拦截器组合在一起时就形成了拦截器链(Interceptor Chain)或拦截器栈(Interceptor Stack)。
拦截器链就是指对应各个功能的拦截器按照一定的顺序排列在一起形成的链,而拦截器链组成的集合就是拦截器栈。当有适配连接器栈的访问请求进来时,这些拦截器就会按照之前定义的顺序被调用。
在通常情况下,拦截器都是以代理方式调用的,它在一个 Action 执行前后进行拦截,围绕着 Action 和 Result 的执行而执行,其工作方式如图 1 所示。
从图 1 中可以看出,Struts2 拦截器的实现原理与 Servlet 过滤器的实现原理类似,它以链式执行,对真正要执行的方法(execute())进行拦截。
图 1 Struts2 拦截器的工作方式
在执行 Action 的 execute() 方法之前会执行一次拦截,在 Action 和 Result 执行之后,拦截器会再次执行(与先前的调用顺序相反)。在此链式执行的过程中,每一个拦截器都可以直接返回,从而终止余下的拦截器、Action 及 Result 的执行。