springmvc拦截器的定义和配置

拦截器
1.拦截定义

定义拦截器,实现HandlerInterceptor接口。接口中提供三个方法。

package cn.edu.hpu.ssm.interceptor;  
  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
  
import org.springframework.web.servlet.HandlerInterceptor;  
import org.springframework.web.servlet.ModelAndView;  
  
//测试拦截器1  
public class HandlerInterceptor1 implements HandlerInterceptor{  
  
  
    //执行Handler方法之前执行  
    //用于身份认证、身份授权  
    //比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,  
            Object handler) throws Exception {  
          
          
        //return false表示拦截,不向下执行  
        //return true表示放行          
        return false;  
    }  
      
    //进入Handler方法之后,返回modelAndView之前执行  
    //应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里  
    //传到视图,也可以在这里统一指定视图  
    @Override  
    public void postHandle(HttpServletRequest request, HttpServletResponse response,  
            Object handler, ModelAndView modelAndView) throws Exception {  
           
          
    }  
      
    //执行Handler完成执行此方法  
    //应用场景:统一异常处理,统一日志处理  
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,  
            Object handler, Exception ex)  
            throws Exception {  
           
          
    }  
}  
2.拦截器配置
2.1针对HandlerMapping配置

springmvc拦截器针对HandlerMapping进行拦截设置,如果在某个HandlerMapping中配置拦截,经过该 HandlerMapping映射成功的handler最终使用该拦截器。

<bean  
    class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">  
    <property name="interceptors">  
        <list>  
            <ref bean="handlerInterceptor1"/>  
            <ref bean="handlerInterceptor2"/>  
        </list>  
    </property>  
</bean>  
    <bean id="handlerInterceptor1" class="springmvc.intercapter.HandlerInterceptor1"/>  
    <bean id="handlerInterceptor2" class="springmvc.intercapter.HandlerInterceptor2"/>  
一般不推荐使用。

2.2类似全局的拦截器
springmvc配置类似全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping中。

<!-- 拦截器 -->  
<mvc:interceptors>  
    <!-- 多个拦截器,顺序执行 -->  
    <mvc:interceptor>  
        <!-- /**表示所有url包括子url路径 -->  
        <mvc:mapping path="/**"/>  
        <bean class="cn.edu.hpu.ssm.interceptor.HandlerInterceptor1"/>  
    </mvc:interceptor>  
    <mvc:interceptor>  
        <mvc:mapping path="/**"/>  
        <bean class="cn.edu.hpu.ssm.interceptor.HandlerInterceptor2"/>  
    </mvc:interceptor>  
</mvc:interceptors>  

3.拦截测试
3.1测试需求
测试多个拦截器各各方法执行时机。

3.2编写两个拦截
HandlerInterceptor1.java:
package cn.edu.hpu.ssm.interceptor;  
  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
  
import org.springframework.web.servlet.HandlerInterceptor;  
import org.springframework.web.servlet.ModelAndView;  
  
//测试拦截器1  
public class HandlerInterceptor1 implements HandlerInterceptor{  
  
  
    //执行Handler方法之前执行  
    //用于身份认证、身份授权  
    //比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,  
            Object handler) throws Exception {  
          
        System.out.println("HandlerInterceptor1......preHandle");  
          
        //return false表示拦截,不向下执行  
        //return true表示放行          
        return false;  
    }  
      
    //进入Handler方法之后,返回modelAndView之前执行  
    //应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里  
    //传到视图,也可以在这里统一指定视图  
    @Override  
    public void postHandle(HttpServletRequest request, HttpServletResponse response,  
            Object handler, ModelAndView modelAndView) throws Exception {  
          
        System.out.println("HandlerInterceptor1......postHandle");  
          
    }  
      
    //执行Handler完成执行此方法  
    //应用场景:统一异常处理,统一日志处理  
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,  
            Object handler, Exception ex)  
            throws Exception {  
          
        System.out.println("HandlerInterceptor1......afterHandle");  
          
    }  
}  
HandlerInterceptor2.java:
package cn.edu.hpu.ssm.interceptor;  
  
  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
  
  
import org.springframework.web.servlet.HandlerInterceptor;  
import org.springframework.web.servlet.ModelAndView;  
  
  
//测试拦截器2  
public class HandlerInterceptor2 implements HandlerInterceptor{  
  
  
    //执行Handler方法之前执行  
    //用于身份认证、身份授权  
    //比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,  
            Object handler) throws Exception {  
          
        System.out.println("HandlerInterceptor2......preHandle");  
          
        //return false表示拦截,不向下执行  
        //return true表示放行          
        return false;  
    }  
      
    //进入Handler方法之后,返回modelAndView之前执行  
    //应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里  
    //传到视图,也可以在这里统一指定视图  
    @Override  
    public void postHandle(HttpServletRequest request, HttpServletResponse response,  
            Object handler, ModelAndView modelAndView) throws Exception {  
          
        System.out.println("HandlerInterceptor2......postHandle");  
          
    }  
      
    //执行Handler完成执行此方法  
    //应用场景:统一异常处理,统一日志处理  
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,  
            Object handler, Exception ex)  
            throws Exception {  
          
        System.out.println("HandlerInterceptor2......afterHandle");  
          
    }  
}  

3.3两个拦截器都放行
将preHandle方法的返回值设为true,然后随便访问一个controller,控制台打印一下结果:

HandlerInterceptor1...preHandle  
HandlerInterceptor2...preHandle  
  
HandlerInterceptor2...postHandle  
HandlerInterceptor1...postHandle  
  
HandlerInterceptor2...afterCompletion  
HandlerInterceptor1...afterCompletion  
总结:
preHandle方法按顺序执行,
postHandle和afterCompletion按拦截器配置的逆向顺序执行。

3.4拦截器1放行,拦截器2不放行

HandlerInterceptor1...preHandle  
HandlerInterceptor2...preHandle  
HandlerInterceptor1...afterCompletion 

总结:
拦截器1放行,拦截器2 preHandle才会执行。
拦截器2 preHandle不放行,拦截器2 postHandle和afterCompletion不会执行。
只要有一个拦截器不放行,postHandle不会执行。
3.5拦截器1不放行,拦截器2不放行

HandlerInterceptor1...preHandle  
拦截器1 preHandle不放行,postHandle和afterCompletion不会执行。
拦截器1 preHandle不放行,拦截器2不执行。

4.根据测试结果,对拦截器应用。

比如:统一日志处理拦截器,需要该拦截器preHandle一定要放行,且将它放在拦截器链接中第一个位置。

比如:登陆认证拦截器,放在拦截器链接中第一个位置。权限校验拦截器,放在登陆认证拦截器之后。(因为登陆通过后才校验权限)

5拦截器应用(实现登陆认证)

5.1需求

(1)用户请求url
(2)拦截器进行拦截校验
如果请求的url是公开地址(无需登陆即可访问的url),让放行
如果用户session 不存在跳转到登陆页面
如果用户session存在放行,继续操作。

5.2登陆controller方法
package cn.edu.hpu.ssm.controller;  
  
import javax.servlet.http.HttpSession;  
  
import org.springframework.stereotype.Controller;  
import org.springframework.web.bind.annotation.RequestMapping;  
  
@Controller  
public class LoginController {  
      
    //登录  
    @RequestMapping("/login")  
    public String login(HttpSession session,String username,String password)throws Exception{  
        //调用serivce进行用户身份验证  
        //...  
          
        //在session中保存用户身份信息  
        session.setAttribute("username", username);  
        //重定向到商品列表界面  
        return "redirect:/items/queryItems.action";  
    }  
      
    //退出  
    @RequestMapping("/logout")  
    public String logout(HttpSession session)throws Exception{  
          
        //清除session  
        session.invalidate();  
          
        //重定向到商品列表界面  
        return "redirect:items/queryItems.action";  
    }  
}  
登录页面:
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%>  
<%  
String path = request.getContextPath();  
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
%>  
  
  
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
<html>  
  <head>  
    <base href="<%=basePath%>">  
      
    <title>系统登录</title>  
  
  
  </head>  
    
  <body>  
   <form action="${pageContext.request.contextPath }/login.action" method="post">  
    用户账号:<input type="text" name="username"/><br/>  
    用户密码:<input type="password" name="password"/><br/>  
    <input type="submit" value="登录"/>  
   </form>  
  </body>  
</html>  
在商品列表那里加入:
当前用户:${username }|  
<c:if test="${username!=null }">  
<a href="${pageContext.request.contextPath }/logout.action">退出</a>  
</c:if>  

5.3登陆认证拦截实现

5.3.1代码实现

package cn.edu.hpu.ssm.interceptor;  
  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import javax.servlet.http.HttpSession;  
  
import org.springframework.web.servlet.HandlerInterceptor;  
import org.springframework.web.servlet.ModelAndView;  
  
//登录认证的拦截器  
public class LoginInterceptor implements HandlerInterceptor{  
  
    //执行Handler方法之前执行  
    //用于身份认证、身份授权  
    //比如身份认证,如果认证通过表示当前用户没有登陆,需要此方法拦截不再向下执行  
    @Override  
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,  
            Object handler) throws Exception {  
          
        //获取请求的url  
        String url=request.getRequestURI();  
        //判断url是否是公开地址(实际使用时将公开地址配置到配置文件中)  
        if(url.indexOf("login.action")>=0){  
            //如果要进行登录提交,放行  
            return true;  
        }  
          
        //判断session  
        HttpSession session=request.getSession();  
        //从session中取出用户份信息  
        String username=(String)session.getAttribute("username");  
          
        if(username!=null){  
            //身份存在,放行  
            return true;  
        }  
          
        //执行这里表示用户身份需要验证,跳转到登录界面  
        request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);  
          
        //return false表示拦截,不向下执行  
        //return true表示放行          
        return false;  
    }  
      
    //进入Handler方法之后,返回modelAndView之前执行  
    //应用场景从modelAndView出发:将公用的模型数据(比如菜单导航)在这里  
    //传到视图,也可以在这里统一指定视图  
    @Override  
    public void postHandle(HttpServletRequest request, HttpServletResponse response,  
            Object handler, ModelAndView modelAndView) throws Exception {  
          
        System.out.println("HandlerInterceptor1......postHandle");  
          
    }  
      
    //执行Handler完成执行此方法  
    //应用场景:统一异常处理,统一日志处理  
    @Override  
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response,  
            Object handler, Exception ex)  
            throws Exception {  
          
        System.out.println("HandlerInterceptor1......afterHandle");  
          
    }  
}  
5.3.2拦截器配置
springmvc.xml中配置:

<!-- 拦截器 -->  
<mvc:interceptors>  
    <!-- 多个拦截器,顺序执行 -->  
    <!-- 登录认证拦截器 -->  
    <mvc:interceptor>  
        <mvc:mapping path="/**"/>  
        <bean class="cn.edu.hpu.ssm.interceptor.LoginInterceptor"/>  
    </mvc:interceptor>  
</mvc:interceptors>  

测试:
输入商品列表的网址,结果发现被拦截在登录界面(原因:拦截器没有检测到登录用户的session,所以判定用户没有登录,没有权限查看商品列表)


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值