4.0 准备工作
建一个web 工程,在src/main/java下创建包com/zhanglei/controller,interceptor,在web 目录下创建 jsp 目录:
编写 index.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<form action="zhanglei" method="post">
姓名:<input type="text" name="name"/></br>
年龄:<input type="text" name="age"/></br>
<input type="submit" value="提交">
</form>
</body>
</html>
在 controller下创建一个控制器类:
package com.zhanglei.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller //要在springmvc配置文件中 配置注解扫描器
public class HelloController{
@RequestMapping("/zhanglei")
public String doController(HttpServletRequest h,String name,String age){
System.out.println("====控制器的doController方法执行====");
h.setAttribute("myname",name);
h.setAttribute("myage",age);
return "Hello";//要在springmvc配置文件中配 置视图解析器
}
}
目的跳转页面 Hello.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>跳转页面</title>
</head>
<body>
接收的参数为:</br>
name:${myname} </br>
age:${myage}
</body>
</html>
maven依赖pom.xml、web.xml、springmvc.xml 的配置
springmvc 常用配置 - ZhangLeiのWorld (zhangleistudy.com)
4.1 拦截器概述
拦截器时 springmvc 中的一种,需要实现 HandlerInterceptor 接口。
拦截器和过滤器类似,功能方向侧重点不同。过滤器是用来过滤请求参数,设置编码字符集等工作。拦截器时拦截用户的请求,对请求做判断处理的。
拦截器是全局的,可以对多个Controller 做拦截。一个项目可以有0个或者多个拦截器,他们在一起拦截用户的请求。
拦截器常用在:用户登录处理,权限检查
4.2 拦截器使用步骤
4.2.1 定义类实现 HandlerInterceptor 接口
定义一个类实现 HandlerInterceptor 接口,并重写接口的三个方法:
package com.zhanglei.interceptor;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("MyInterceptor 的 preHandle 方法");
//设置为tue 说明使他验证通过,请求交给处理器方法可以执行
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("MyInterceptor 的 postHandle 方法");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("MyInterceptor 的 afterCompletion 方法");
}
}
preHander 方法特点:(重点使用这个方法)
实在控制器方法(MyController 的doSome)之前先执行的。用户的请求首先到达此方法。preHander 方法有一个boolean 类型的返回值,true:请求通过了拦截器的验证,交给控制器处理,false:请求被拦截器拦截。
可以验证用户是否登录,验证用户是否有权限访问某个地址(url)。
如果验证失败,可以截断请求,请求不能被控制器处理;
如果验证成果,可以放行请求,此时控制器才能处理。
postHandler 方法特点:
postHandler 方法在控制器方法(MyController 的doSome)之后执行的
afterCompletion方法特点:
afterCompletion 方法在请求处理完之后执行的,就是在执行完forward 转发之后,就认为请求处理完成。
4.2.2 在 springmvc 配置文件中声明拦截器(如上)
在springmvc 配置文件中声明 注解扫描器,声明 拦截器并指定所拦截请求的 uri 地址。
4.3 拦截器演示
由于springmvc.xml 中拦截器的声明如下:
可以理解为,拦截器的 preHandler 方法就是门卫,controller 方法就是小区内,/**意思是只要人请求通过小区门,均会被 MyInterceptor 拦截器拦下检查健康码,这一步骤就是验证,如果验证通过了(即 preHandler 方法返回值是 true),那么放行该请求,请求交给 controller 处理;反之,拒绝该请求,请求就不会交给 controller 处理器处理(人进不了小区内)
未测试方便,在我自定义的拦截器 MyInterceptor 内,preHander 方法返回值 设为 true,意思是拦截下来的请求均通过拦截器验证,移交给 controller 控制器处理,实际可以写一些逻辑,如 if…return true; else…return false 。
4.3.1 验证拦截器(preHandler 方法返回值设为true)
集成 tomcat,启动tomcat,访问项目地址:
点击提交
此时看控制台!!!:
4.3.2 再验证拦截器(preHandler 方法返回值设为false)
preHandler 方法返回值设为false: 意思是先拦截所有请求( 因为mapping path="/"),然后拒绝所有请求,请求不会被移交给 controller 控制器处理。**
重新启动 tomcat,输入项目地址,到首页后输入值(跟上面一样):
点击提交:
由于在 Hello.jsp显示数据的代码实在 controller 控制器内实现的,如下:
但是拦截器 “门卫方法” preHandler 返回值为 false,因此,请求不会被controller 处理,因此这时Hello.jsp 数据为空;同时,控制台只有门卫方法执行了!!:
4.4 拦截器原理图示总结
补充拦截器和过滤器的区别:
1.过滤器是Servlet 中的对象 ,拦截器是框架中的对象
2.过滤器是实现 Filter 接口的对象,拦截器是实现 HandlerInterceptor
3.过滤器是用来设置 request,response的参数,属性的,侧重于对数据的过滤。而拦截器是用来验证请求的,能截断请求,也能放行请求。
4.过滤器在拦截器之前执行
5.过滤器只有一个执行时间点,而拦截器有三个执行时间点
6.过滤器可以处理jsp,js,html等等,而拦截器侧重拦截请求:使用拦截器的前提是,你的请求必须要被中央调度器 DispatcherServlet 接收,如果不被中央调度器接收,请求无意义,只会出现404错误。