Spring-拦截器
** 先炒个栗子:你背着包去坐火车,进站之前,首先,会有人查你的票(这里相当于一层拦截器,拦截的目的是看你有没有进站的凭证)。OK,你的票通过了,然后你往里继续走,因为你背着包,所以还要过安检(这里是又一层拦截器,拦截的目的是看你有没有携带危险物品)。 **
** 上面的例子里,车站就相当于我们的spring应用,背着包要进车站的你就相当于用户请求,查票的拦截器,相当于察看用户凭证,映射到实际应用中就是,看你有没有登录,你没登陆(没有票)凭什么让你进入应用(车站)呢。而安检那里呢,就相当于拦截一些危险行为,比如,你在请求的参数里注入了一段清空数据表的sql(你的包里背了一个炸弹),那么肯定不能让你的请求进入应用! **
** 下面的例子里,我们建立一个拦截器,放行所有视图渲染请求,拦截所有其它请求 **
1.添加拦截器配置
** 在\src\main\resources\spring
目录下添加applicationContext-hi.xml
文件: **
1 |
|
** 建立完成后,需要在applicationContext.xml
引用该配置,使其生效: **applicationContext.xml
:
1 |
|
2.在\src\main\java\com\spring\common
目录下建立类handlerInterceptor.java
** 前面提到过common目录是工具类目录,我们在这里把拦截器看作工具类 **
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.spring.common;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
//定义的拦截器需要实现 spring HandlerInterceptor 接口
public class handlerInterceptor implements HandlerInterceptor{
/**
* 这个方法将请求拦截在进入控制器之前,你可以用此方法,验证用户身份、权限等
* @param request
* @param response
* @param handler
* @return boolean 此方法如果返回为 true 则将请求发往控制器继续执行,如果返回 false 则拦截请求,结束该请求的生命周期
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
System.out.println("进入拦截器");
String url = request.getRequestURI();
return url.contains("display");
}
//这个方法将在视图渲染前进行拦截。
public void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("视图渲染前的拦截动作,要渲染的视图为:" + modelAndView.getViewName());
}
//这个方法,视图编译完成后执行(所谓编译完成,是指jsp文件、html文件等已经读取替换完成,等待返回前台渲染。)。可以在这里,执行一些统一的处理,例如日志写入等。
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("视图编译完成后执行的拦截动作");
}
}
3.在\src\main\java\com\spring\controller
目录下,建立控制器文件
1 | package com.spring.common; |
** 在这里,我们建立两个控制器文件,一个是用于视图渲染的\view\viewController.java
另一个是用于返回数据的\api\apiController.java
**viewController.java
:
1 | package com.spring.controller.view; |
apiController.java
:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.spring.controller.api;
import net.sf.json.JSONObject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
/**
*
* @author hsoft
*/
public class apiController {
public String testData(){
return new JSONObject().accumulate("key", "中文").toString();
}
}
4.运行
1 | package com.spring.controller.api; |
** 在SpringMVC目录下执行下面命令: **
1 | mvn clean |
访问http://localhost:8080/SpringMVC/display/index时,将会渲染index.jsp文件的内容到浏览器,并且,tomcat控制台打印以下内容:
1 | 进入拦截器 |
从打印结果可以看出,请求是先进入拦截器的。并且,按照我们在preHandle
中指定的规则,url中存在“display”关键字,我们认为这个一个视图渲染请求,将请求发送到控制器执行。
访问http://localhost:8080/SpringMVC/api/testData时,浏览器会一片空白,并且,tomcat控制台只打印以下内容:
1 | 进入拦截器 |
因为我们的请求的url中,不存在“display”关键字,我们定义拦截器时,要求把这种请求拦截,因此,该请求并没有进入控制器,到拦截器就结束了它的生命周期。
至于拦截的实现,关键语句在于preHandle
方法的返回值:return url.contains("display");
,可以看出如果url存在“display”关键字会返回true,否则返回false。