拦截器(interceptor)的作用
Spring MVC的拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理。
就相当于是在访问之前可以进行业务逻辑的判断,判断出到底能不能访问。
拦截器的详细使用:
拦截器( Interceptor)是 SpringMVC框架自己的,只有使用了SpringMVC 框架的工程才能用
在<mvc:mapping path=“”/>中配置了/**之后,也可以多所有资源进行拦截,但是可以通过<mvc:exclude-mapping path=“”/>标签排除不需要拦截的资源。
写拦截器的三个步骤:
第一步:创建拦截器类实现Handlerlnterceptor接口
第二步:配置拦截器
第三步:测试拦截器的拦截效果
代码实现:
准备工作:
首先写一个类来做实验:
@Controller
public class TargetController {
@RequestMapping("/target")
public ModelAndView show(){
System.out.println("目标资源正在执行");
ModelAndView modelAndView=new ModelAndView();
modelAndView.addObject("name","outlier");
modelAndView.setViewName("index");
return modelAndView;
}
}
然后在springMVC的配置文件中进行配置:
<!-- 配置注解驱动-->
<mvc:annotation-driven/>
<!-- 配置视图解析器-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 静态资源权限开放-->
<mvc:default-servlet-handler/>
<!-- 组件扫描,扫描Controller-->
<context:component-scan base-package="com.outlier.controller"/>
然后还要有一个JSP页面
<%@ page isELIgnored="false"%>
<html>
<body>
<h2>Hello World! ${name}</h2>
</body>
</html>
这里重点强调一下,如果这里利用el表达式去取modelandview里面的值,如果没取成功,el表达式原样输出,就是因为jsp是自动屏蔽了el表达是的,需要加上上面的代码,把它改为false
<%@ page isELIgnored="false"%>就可以了。
接下来我们就开始配置拦截器:
第一步:创建拦截器类实现Handlerlnterceptor接口(在这里我们实现的时候,我们什么都没写它也不会报错,因为在源码中,里面的方法都是default关键词修饰的,在这里我们需要重写它的三个发方法,让我们了解拦截器的工作原理)
public class MyInterceptor1 implements HandlerInterceptor {
//这个方法是在目标方法执行之前执行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle.....");
return false;
}
//这个方法在目标方法执行之后,视图对象返回之前执行
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle...");
}
//在整个流程都执行完后执行。
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion...");
}
}
第二步:配置拦截器(在springmvc的配置文件中)
<!-- 配置拦截器-->
<mvc:interceptors>
<mvc:interceptor>
<!-- 这个表示对那些资源进行拦截操作-->
<mvc:mapping path="/**"/>
<bean class="com.outlier.interceptor.MyInterceptor1"/>
</mvc:interceptor>
</mvc:interceptors>
在这里对配置文件进行解释一下:
首先外层是interceptors代表内部可以写多个interceptor。然后在interceptor内部的mapping path表示对那些资源进行拦截。/**表示的是对所有的都进行拦截。然后内部的bean表示的是哪个拦截器起作用。
第三步:测试:
在这里我们发现它并没有发生视图跳转。但在控制台中我们发现打印了
说明了拦截器起作用了,那怎么起的作用,是因为在拦截器的preHandle方法它的返回值是一个false。如果改为了true就相当于打开了开关,全部都可以执行。
现在我们把返回值修改为true再运行
控制台也打印了:
顺序也是我们前面注释中写的顺序。
然后在这里我们就可以发现可以在prehandle里面写业务逻辑代码,比如来点if判断,来选择返回true或者false就形成了拦截。在prehandle里面的参数也有request和response等,就可以从客户端获取值,以及响应。
接下来我们简单的写一下:(在prehandle里面写)
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle.....");
//从前端获取参数
String param = request.getParameter("param");
if ("yes".equals(param)){
return true;
}else {
//没有从前端获取到对应的参数就返回到其他的页面,并且返回false,让后面无法执行
request.getRequestDispatcher("error.jsp").forward(request,response);
return false;
}
}
这样写,我们在访问的时候不带参数或者没带对应的参数它都会跳转到error页面。
控制台的打印也只有prehandle的执行。
带正确的参数就会全部执行并显示出页面:
控制台:
接下来我们再好好的了解一下postHandle方法什么叫在目标方法执行之后,视图对象返回之前执行
原本我们在页面显示的是outlier。我们可以在视图返回之前进行修改
在postHandle中写如下代码:
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
modelAndView.addObject("name","security");
System.out.println("postHandle...");
}
效果:
我们就在视图返回之前把里面额model给修改了。
当有多个拦截器的时候,谁先写在前面就先执行谁。