1.拦截器的定义
SpringMVC中的拦截器,类似于Servlet中的过滤器(Filter),它主要用于拦截用户请求并做相应的处理.例如,通过拦截器可以进行权限验证,记录请求信息的日志,判断用户是否登录等
通常拦截器类可以通过两种方式来定义,一种是通过实现HandlerInterceptor接口,或继承HandlerInterceptor接口的实现类HandlerInterceptorAdapter另一种是通过实现WebRequestInterceptor接口,或继承WebRequestInterceptor接口的实现类来定义
demo:实现HandlerInterceptor接口
public class CustomInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throws Exception{
return false;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView)throws Exception{
}
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception{
}
}
- preHandle():该方法会在控制器方法前执行,其返回值表示是否中断后续操作,当返回值为true时,表示继续向下执行;当返回值为false时,会中断后续的所有操作(包括调用下一个拦截器和控制器类中的方法执行等)
- postHandle():该方法会在控制器方法调用之后,解析视图之前执行,可以通过此方法对请求域中的模型和视图作出进一步的修改
- afterCompletion()方法:该方法会在整个请求完成,即视图渲染结束之后执行,可以通过此方法实现一些资源清理,记录日志信息等工作.
2.拦截器的配置
<!--配置拦截器-->
<mvc:interceptors>
<!--使用bean直接定义在<mvc:interceptors>下面的Interceptor将拦截所有请求-->
<bean class="com.itcast.interceptor.CustomInterceptor"/>
<!--拦截器1-->
<mvc:interceptor>
<!--配置拦截器作用的路径-->
<mvc:mapping path="/**"/>
<!--配置不需要拦截器作用的路径-->
<mvc:exclude-mapping path=""/>
<!--定义在<mvc:interceptor>下面的,表示对匹配路径的请求进行拦截-->
<bean class="com.itcast.interceptor.Interceptor1"/>
</mvc:interceptor>
<!--拦截器2-->
<mvc:interceptor>
<mvc:mapping path="/hello"/>
<bean class="com.itcast.interceptor.Interceptor2"/>
</mvc:interceptor>
...
</mvc:interceptors>
3.单个拦截器的执行流程
demo:
(1)创建chapter15的web项目,导入相关jar包
(2)在web.xml中,配置SpringMVC的前端过滤器和初始化加载配置文件等信息
(3)HelloController
@Controller
public class HelloController{
/*
页面跳转
*/
@RequestMapping("/hello")
public String Hello(){}
System.out.println("Hello!");
return "success";
}
(4)创建拦截器类CustomInterceptor
/*
实现了HandlerInterceptor接口的自定义拦截器类
*/
public class CustomInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throws Exception{
System.out.println("CustomInterceptor...preHandle");
//对拦截的请求进行放行处理
return true;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView)throws Exception{
System.out.println("CustomInterceptor...postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception{
System.out.println("CustomInterceptor...afterCompletion");
}
}
(5)SpringMVC.xml
<!--定义组件扫描器,指定需要扫描的包-->
<context:component-scan base-package="com.itcast.controller"/>
<!--定义视图解析器-->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!--设置前缀-->
<property name="prefix" value="/WEB-INF/jsp/"/>
<!--设置后缀-->
<property name="suffix" value=".jsp"/>
</bean>
<!--配置拦截器-->
<mvc:interceptors>
<!--使用bean直接定义在<mvc:interceptors>下面的拦截器将拦截所有请求-->
<bean class="com.itcast.interceptor.CustomInterceptor"/>
</mvc:interceptors>
</beans>
4.多个拦截器的执行流程
(1)定义两个拦截器类
Interceptor1
/*
以实现接口的方式定义拦截器
*/
public class Interceptor1 implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throws Exception{
System.out.println("Intercepter1...preHandle");
//对拦截的请求进行放行处理
return true;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView)throws Exception{
System.out.println("Intercepter1...postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception{
System.out.println("Intercepter1...afterCompletion");
}
}
Interceptor2
/*
以实现接口的方式定义拦截器
*/
public class Interceptor2 implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throws Exception{
System.out.println("Intercepter2...preHandle");
//对拦截的请求进行放行处理
return true;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView)throws Exception{
System.out.println("Intercepter2...postHandle");
}
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception{
System.out.println("Intercepter2...afterCompletion");
}
}
(3)springmvc-config.xml中,定义两个拦截器
<!--配置拦截器1-->
<mvc:interceptor>
<!--配置拦截器作用的路径-->
<mvc:mapping path="/**">
<!--使用bean直接定义在<mvc:interceptors>下面的拦截器将拦截所有请求-->
<bean class="com.itcast.interceptor.Interceptor1"/>
</mvc:interceptor>
<!--拦截器2-->
<mvc:interceptor>
<mvc:mapping path="/hello">
<bean class="com.itcast.interceptor.Interceptor2"/>
</mvc:interceptor>
5.应用案例:实现用户登录权限验证
只有登录后的用户才能访问系统中的主页面,如果没有登录系统而直接访问主页面,则拦截器会将请求拦截,并转发到登录页面,同时在登录页面中给出提示信息.如果用户名或密码错误,也会在登录页面给出相应的提示信息,当已登录的用户在系统主页中单击"退出"按钮时,系统同样会回到登录页面
(1)User类
(2)UserController
@Controller
public class UserController{
/*
向用户登录页面跳转
*/
@RequestMapping(value="/login",method=RequestMethod.GET)
public String toLogin(){
return "login";
}
/*
用户登录
*/
@RequestMapping(value="/login",method=RequestMethod.POST)
public String login(User user,Model model,HttpSession session){
//获取用户名和密码
String username=user.getUsername();
String password=user.getPassword();
//此处模拟从数据库中获取用户名和密码后进行判断
if(username!=null&&username.equals("xiaoxue")&&password!=null&&password.equals("123456")){
//将用户对象添加到session
session.setAttribute("USER_SESSION",user);
//重定向到主页面的跳转方法
return "redirect:main";
}
model.addAttribute("msg","用户名或密码错误,请重新登录!");
return "login";
}
/*
向用户主页面跳转
*/
@RequestMapping(value="/main")
public String toMain(){
return "main";
}
/*
退出登录
*/
@RequestMapping(value="/logout")
public String logout(HttpSession session){
//清除session
session.invalidate();
//重定向到登录页面的跳转方法
return"redirect:login";
}
}
(3)创建登录拦截器类LoginInterceptor
/*
登录拦截器
*/
public class LoginInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throws Exception{
//获取请求的URL
String url=request.getRequestURI();
//url:除了login.jsp是可以公开访问的,其他的URL都进行拦截控制
if(url.indexOf("/login")>=0){
return true;
}
//获取session
HttpSession sessio=request.getSession();
User user=(User)session.getAttribute("USER_SESSION");
//判断session中是否有数据,如果有,则返回true,继续向下执行
if(user!=null){
return true;
}
//不符合条件的给出提示信息,并转发到登录页面
request.setAttribute("msg","您还没有登录,请先登录!");
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request,response);
return false;
}
@Override
public void postHandle(HttpServletRequest request,HttpServletResponse response,Object handler,ModelAndView)throws Exception{
}
@Override
public void afterCompletion(HttpServletRequest request,HttpServletResponse response,Object handler,Exception ex)throws Exception{
}
}
(4)在配置文件<mvc:interceptors>元素中,配置自定义的拦截器信息
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.itcast.interceptor.LoginInterceptor"/>
</mvc:interceptor>
(5)在WEB-INF目录下的jsp文件夹中,创建一个系统主页面main.jsp.在该页面中,使用EL表达式获取用户信息,并且通过一个超链接来实现"退出"功能
<title>系统主页</title>
<body>
当前用户:${USER_SESSION.username}
<a href="${pageContext.request.contextpath}/logout">退出</a>
</body>
(6)login.jsp
<title>用户登录</title>
<body>
${msg}
<form action="${pageContext.request.contextpath}/login" method="POST">
用户名:<input type="text" name="username" id="username"><br/>
密 码:
<input type="password" name="password" id="password"><br/>
<input type="submit" value="登录" />
</form>
</body>