从零开始学 Java - Spring AOP 拦截器的基本实现

wahlmzr 3年前
   <h2>一个程序猿在梦中解决的 Bug</h2>    <p>没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感。不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过。</p>    <h2>什么是 AOP ?</h2>    <p>AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP 是 OOP 的延续,是软件开发中的一个热点,也是 Spring 框架中的一个重要内容,是函数式编程的一种衍生范型。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。</p>    <p>以上内容引用自百度百科</p>    <p>翻译为人能听懂的话来说就是: AOP 可以理解为在方法执行前后可以去完成相同的业务逻辑,而不需要你去改业务代码。举个例子吧:现在有一个需求,要在项目中的每一个方法前面都输出一句:开始执行啦! 需求很明确了,常规的解决方式就是在每个具体的方法最前面加一句 system.out.print("开始执行啦!"); ,冒出这个想法的程序员是普通程序猿,当然,这是开个玩笑啦!这样的代码,如果一两个方法用这样的方式没有任何问题完全可行,如果几十个、几百个这样的方法呢?</p>    <p>这时候,我们就可以使用 AOP 来完成以上逻辑了,不需要改动任何一个方法,无侵入的方式来完成这个需求。</p>    <p>AOP 在实际项目中运用的场景主要有 权限管理(Authority Management)、事务管理(Transaction Management)、安全管理(Security)、日志管理(Logging)和调试管理(Debugging) 等。就是这些与业务逻辑不是很关联密切的公共方法,我们就可以使用AOP。</p>    <h2>Spring AOP 和 MVC 拦截器 又是什么?</h2>    <p>通过上面的解释,我是知道了,AOP 其实就是可以算一种设计模式,或者说一种编程思想,而 Spring AOP 就是 Spring框架 对 AOP 这种思想进行了一系列技术实现和封装,让我们只需要配置一下就可以达到这个模式,在配置文件中使用 <aop:config> 元素。那 MVC 拦截器 又是什么鬼呢?可以理解为是 Spring MVC 框架对 AOP 的一种实现方式,在配置文件中使用 <mvc:interceptors> 元素进行配置。这两种方式就是实现了 AOP 的编程思想,我们只需要进行一定的配置就可以了。现在好多人也都把 Spring AOP 和 MVC 拦截器看成是一种相同的方式,都叫拦截器或AOP。</p>    <h2>开始撸一下代码</h2>    <p>1.新建一个 TestInterceptor 类继承于 HandlerInterceptorAdapter 。</p>    <p><img src="https://simg.open-open.com/show/f07f1f53d1cd680e08aa055e6d3336ed.jpg"></p>    <p>具体代码:</p>    <pre>  <code class="language-java">package cn.mayongfa.interceptor;    import javax.servlet.http.HttpServletRequest;  import javax.servlet.http.HttpServletResponse;    import org.springframework.web.servlet.ModelAndView;  import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;    public class TestInterceptor extends HandlerInterceptorAdapter {      @Override      public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {              // 请求处理完成之后              System.out.println("请求处理完成啦!");              super.afterCompletion(request, response, handler, ex);      }        @Override      public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {              // 处理器执行完毕之后              System.out.println("处理器执行完毕啦!");              super.postHandle(request, response, handler, modelAndView);      }        @Override      public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {              // 处理器实际执行之前              System.out.println("处理器执行之前!");              return super.preHandle(request, response, handler);      }  }</code></pre>    <ul>     <li>preHandle(..):它在处理器实际执行 之前 会被执行;</li>     <li>postHandle(..),它在处理器执行 完毕 以后被执行;</li>     <li>afterCompletion(..),它在 整个请求处理完成 之后被执行。<br> 这三个方法为各种类型的前处理和后处理需求提供了足够的灵活性。</li>    </ul>    <p>2.配置一下 /WebContent/WEB-INF/springMVC-servlet.xml 中的 <mvc:interceptors> 元素就可以拦截请求了。</p>    <pre>  <code class="language-java"><mvc:interceptors>      <!-- 直接定义在mvc:interceptors根下面的Interceptor将拦截所有的请求 -->      <mvc:interceptor>          <!-- 定义在mvc:interceptor下面的表示是对特定的请求才进行拦截的 -->          <mvc:mapping path="/api/**"/>          <bean class="cn.mayongfa.interceptor.TestInterceptor">          </bean>      </mvc:interceptor>  </mvc:interceptors></code></pre>    <p>当然,你可以根据你的需求进行拦截,我这里拦截的是api路径下面的所有请求。</p>    <p>3.测试一下</p>    <p>我的项目中有个 /api/user/getlist 请求,在浏览器输入试一下。</p>    <p><img src="https://simg.open-open.com/show/bf49660cf432d5acfe432a94c892aa09.jpg"></p>    <p>请求数据成功,看一下控制台输出:</p>    <p><img src="https://simg.open-open.com/show/86cc48d9a41e6312190b107773a80a28.jpg"></p>    <p>看到我们在 TestInterceptor 类中输出已经打印出来,这就是 Spring AOP 拦截器的基本实现 。到这里,你应该明白了如何使用 AOP 来进行一些与业务逻辑无关且必须在代码前后执行的一些通用方法了,这就是我理解 AOP 的作用吧。具体代码请访问GitHub:</p>    <p> </p>    <p> </p>    <p>来自:http://blog.mayongfa.cn/86.html</p>    <p> </p>