拦截器小结

拦截器会拦截指定的请求,并执行其中的方法。从例子和源码上看拦截器的运行和作用。

先创建个拦截器类 MyInterceptor :

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class MyInterceptor implements HandlerInterceptor {

	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		System.out.println("preHandle");
		return true;
	}

	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		System.out.println("postHandle");
	}

	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, 
			Exception ex) throws Exception {
		System.out.println("afterCompletion");
	}
}

将拦截器内的三个方法都添加一条输出方法名字的语句,并将 preHandle 方法的返回值设为true;之后在 application.xml 中配置拦截器;有两种配置:

拦截所有请求;

<mvc:interceptors>
	<bean class="com.jd.interceptor.MyInterceptor"></bean>
</mvc:interceptors>

这么配置拦截器将拦截所有请求进行处理,其中 bean 中 class 是我们拦截器类的路径;一般不推荐这种配置,比较耗费资源;

拦截指定请求:

<mvc:interceptors>
	<mvc:interceptor>
		<mvc:mapping path="/userinfo/*"/>
		<bean class="com.jd.interceptor.MyInterceptor"></bean>
	</mvc:interceptor>
</mvc:interceptors>

该配置仅会拦截 mvc:mapping 标签中所给路径的请求;如下图,这将会拦截所有请求访问 userinfo 文件夹下所有 jsp 文件的请求;

再看 Controller 的代码;

import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class UserInfoController {

	@RequestMapping("userinfo/div.do")
	public String div(int i) {
		System.out.println("div");
		return "userinfo/div";
	}
}

然后从源代码中看拦截器的执行过程(Debug模式):

请求的具体执行过程我之前的博客已有介绍,因此这里直接从 

这个代码截图暂且称之为图1(下文会多次提到);执行到数字 1 时,mappedHandler (我们的 Handler 处理器,如下图鼠标浮到 mappedHandler 上)会执行 applyPreHandle 方法;

我们再看 applyPreHandle 方法的代码:

该方法会对所有的拦截器进行遍历,并找到我们需要的那个拦截器,这里显然是我们自己编写的 MyInterceptor 拦截器,并执行其方法:

即是我们 MyInterceptor 类中的 perHandler方法,并输出字符串,返回  true;层层返回回到图1,if 语句判定 !true 为 false,不执行方法 return,继续往下执行; mv = ha.handle(processedRequest, response, mappedHandler.getHandler()); 获取 mv 数据,然后执行 2 代码;进去 applyPostHandle 方法,代码如下:

同上,依旧对拦截器进行遍历找到需要的拦截器并执行相应的 postHandle 方法;这时控制台便会有 postHandle 语句输出;然后执行 3 代码进入 processDispatchResult 方法,代码如下;

执行到 4,完成请求响应和转发,继续执行到 5 进入 triggerAfterCompletion 方,代码如下:

同样也是找到需要的拦截器并执行相应的 afterCompletion 方法,这时控制台会输出语句 afterCompletion ;执行完程序(后续没有断相关拦截器的了);控制台显示以下输出:

至此,我们可以发现,拦截器中:

  • perHandle 方法是在方法执行之前执行,这里我们可以先对请求进行处理,阻挡非法访问;
  • postHandler 方法是在方法执行之后执行,这里我们可以先对后台服务器需要的数据进行相应的处理,比如添加 UUID 的自动编码等;
  • afterCompletion 方法是在请求转发之后执行,常用来释放资源,类似于 try-catch-fianlly 中的 finally 作用。
发布了99 篇原创文章 · 获赞 3 · 访问量 1199

猜你喜欢

转载自blog.csdn.net/qq_44971038/article/details/104571889