您的位置:首页 > 编程语言 > Java开发

springmvc配置拦截器及测试详解

2017-05-19 09:52 351 查看
拦截器

1.拦截定义

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

[java] view
plain copy

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最终使用该拦截器。

[html] view
plain copy

<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中。

[html] view
plain copy

<!-- 拦截器 -->

<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:

[java] view
plain copy

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:

[java] view
plain copy

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,控制台打印一下结果:

[plain] view
plain copy

HandlerInterceptor1...preHandle

HandlerInterceptor2...preHandle

HandlerInterceptor2...postHandle

HandlerInterceptor1...postHandle

HandlerInterceptor2...afterCompletion

HandlerInterceptor1...afterCompletion

总结:

preHandle方法按顺序执行,

postHandle和afterCompletion按拦截器配置的逆向顺序执行。

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

[plain] view
plain copy

HandlerInterceptor1...preHandle

HandlerInterceptor2...preHandle

HandlerInterceptor1...afterCompletion

总结:

拦截器1放行,拦截器2 preHandle才会执行。

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

只要有一个拦截器不放行,postHandle不会执行。

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

[plain] view
plain copy

HandlerInterceptor1...preHandle

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

拦截器1 preHandle不放行,拦截器2不执行。

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

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

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

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

5.1需求

(1)用户请求url

(2)拦截器进行拦截校验

如果请求的url是公开地址(无需登陆即可访问的url),让放行

如果用户session 不存在跳转到登陆页面

如果用户session存在放行,继续操作。

5.2登陆controller方法

[java] view
plain copy

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";

}

}

登录页面:

[html] view
plain copy

<%@ 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>

在商品列表那里加入:

[html] view
plain copy

当前用户:${username }|

<c:if test="${username!=null }">

<a href="${pageContext.request.contextPath }/logout.action">退出</a>

</c:if>

5.3登陆认证拦截实现

5.3.1代码实现

[java] view
plain copy

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中配置:

[html] view
plain copy

<!-- 拦截器 -->

<mvc:interceptors>

<!-- 多个拦截器,顺序执行 -->

<!-- 登录认证拦截器 -->

<mvc:interceptor>

<mvc:mapping path="/**"/>

<bean class="cn.edu.hpu.ssm.interceptor.LoginInterceptor"/>

</mvc:interceptor>

</mvc:interceptors>

测试:

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



我们输入账号(王五)密码(随便),发现登录进去,并且看到了用户名



点击退出再次退回登录界面,再次输入商品列表的网址,结果发现依旧被拦截在登录界面,原因是session已经被清除。

转载请注明出处:http://blog.csdn.net/acmman/article/details/47680517
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: