springmvc拦截器的实现

1、定义

SpringwebMVC的处理器拦截器类似于Servlet开发中的过滤器Filter,用于对处理器进行预处理和后处理

2、拦截器的定义

定义拦截器,实现HandlerInterceptor接口,如下:

拦截器1:

package com.sky.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
 * @author sk
 *
 */
public class HandlerInterceptor1 implements HandlerInterceptor{

	//执行Handler完成后执行此方法
	//应用场景:统一的异常处理,统一的日志处理
	@Override
	public void afterCompletion(HttpServletRequest arg0,
			HttpServletResponse arg1, Object handler, Exception arg3)
			throws Exception {
		System.out.println("HandlerInterceptor1......afterCompletion");
	}

	//进入Handler方法之后,在返回ModelAndView之前执行
	//应用场景从modelAndView对象出发:将公用的模型数据(比如菜单的导航)在这里传到视图,也可以在这里面来统一指定视图
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object handler, ModelAndView modelAndView) throws Exception {
		System.out.println("HandlerInterceptor1......postHandle");
	}
	
	//在进入Handler方法之前执行
	//用于身份认证、身份授权、
	//比如身份认证,如果认证不通过表示当前用户没有登录,需要此方法拦截不再向下执行
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object handler) throws Exception {
		System.out.println("HandlerInterceptor1......preHandle");
		//return false表示拦截住,不向下执行
		//return true 表示放行
		return true;
	}:
}
拦截器2:

package com.sky.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
 * @author sk
 *
 */
public class HandlerInterceptor2 implements HandlerInterceptor{

	//执行Handler完成后执行此方法
	//应用场景:统一的异常处理,统一的日志处理
	@Override
	public void afterCompletion(HttpServletRequest arg0,
			HttpServletResponse arg1, Object handler, Exception arg3)
			throws Exception {
		System.out.println("HandlerInterceptor2......afterCompletion");
	}

	//进入Handler方法之后,在返回ModelAndView之前执行
	//应用场景从modelAndView对象出发:将公用的模型数据(比如菜单的导航)在这里传到视图,也可以在这里面来统一指定视图
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object handler, ModelAndView modelAndView) throws Exception {
		System.out.println("HandlerInterceptor2......postHandle");
	}
	
	//在进入Handler方法之前执行
	//用于身份认证、身份授权、
	//比如身份认证,如果认证不通过表示当前用户没有登录,需要此方法拦截不再向下执行
	@Override
	public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1,
			Object handler) throws Exception {
		System.out.println("HandlerInterceptor2......preHandle");
		//return false表示拦截住,不向下执行
		//return true 表示放行
		return true;
	}

}

3、拦截器的配置,在springmvc.xml中进行配置

3.1、 针对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 name="handlerInterceptor1" class="com.sky.ssm.interceptor.HandlerInterceptor1"/>
<bean name="handlerInterceptor2" class="com.sky.ssm.interceptor.HandlerInterceptor2"/>
</beans>

这种方式一般不推荐使用

3.2 、类似全局的拦截器

Springmvc可以配置类似于全局的拦截器,springmvc框架将配置的类似全局的拦截器注入到每个HandlerMapping

<!-- 类似于全局的拦截器的配置 -->
<mvc:interceptors>
<!-- 多个拦截器,顺序执行 -->
<mvc:interceptor>
<!-- /**:表示拦截所有的url包括子url路径 -->
<!-- /*:表示只拦截最根上的url,不包括子url -->
<mvc:mapping path="/**"/>
<bean class="com.sky.ssm.interceptor.HandlerInterceptor1"/>
</mvc:interceptor>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<bean class="com.sky.ssm.interceptor.HandlerInterceptor2"/>
</mvc:interceptor>
</mvc:interceptors>

4、拦截器的测试

测试需求:

测试多个拦截器各个方法执行的时机。

 

测试一:烂机器1放行,拦截器2放行

HandlerInterceptor1......preHandle

HandlerInterceptor2......preHandle

 

HandlerInterceptor2......postHandle

HandlerInterceptor1......postHandle

 

HandlerInterceptor2......afterCompletion

HandlerInterceptor1......afterCompletion

 

总结:

preHandle方法按顺序执行

postHandleafterCompletion按拦截器配置的逆向顺序执行。

 

测试二:拦截器1放行,拦截器2不放行

HandlerInterceptor1......preHandle

HandlerInterceptor2......preHandle

HandlerInterceptor1......afterCompletion

总结:拦截器1放行,拦截器2preHandle才会执行

   拦截器2 preHandle不放行,拦截器2postHandleafterCompletion不会执行

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

测试三: 拦截器1不放行,拦截器2不放行

HandlerInterceptor1......preHandle

总结:拦截器1不放行,postHandleafterCompletion不会执行

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

 

5、小结

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

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

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

 

6、拦截器应用(实现登录认证)

6.1、需求

1、用户请求url

2、拦截器进行拦截校验

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

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

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

6.2、登录认证拦截器的实现

1、登录的controller方法

LoginController.java

package com.sky.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{
		//调用service进行用户身份验证
		
		//在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";
	}
}

2、interceptor代码实现

 LoginInterceptor.java

package com.sky.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;
/**
 * 登录认证的拦截器
 * @author sk
 *
 */
public class LoginInterceptor implements HandlerInterceptor{

	//执行Handler完成后执行此方法
	//应用场景:统一的异常处理,统一的日志处理
	@Override
	public void afterCompletion(HttpServletRequest arg0,
			HttpServletResponse arg1, Object handler, Exception arg3)
			throws Exception {
		System.out.println("HandlerInterceptor1......afterCompletion");
	}

	//进入Handler方法之后,在返回ModelAndView之前执行
	//应用场景从modelAndView对象出发:将公用的模型数据(比如菜单的导航)在这里传到视图,也可以在这里面来统一指定视图
	@Override
	public void postHandle(HttpServletRequest arg0, HttpServletResponse response,
			Object handler, ModelAndView modelAndView) throws Exception {
		System.out.println("HandlerInterceptor1......postHandle");
	}
	
	//在进入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;
	}

}

3、配置拦截器

	<!-- 类似于全局的拦截器的配置 -->
	<mvc:interceptors>
		<!-- 多个拦截器,顺序执行 -->
		<!-- 登录认证拦截器 -->
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<bean class="com.sky.ssm.interceptor.LoginInterceptor"/>
		</mvc:interceptor>
		<mvc:interceptor>
			<!-- /**:表示拦截所有的url包括子url路径 -->
			<!-- /*:表示只拦截最根上的url,不包括子url -->
			<mvc:mapping path="/**"/>
			<bean class="com.sky.ssm.interceptor.HandlerInterceptor1"/>
		</mvc:interceptor>
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<bean class="com.sky.ssm.interceptor.HandlerInterceptor2"/>
		</mvc:interceptor>
	</mvc:interceptors>

4、登录页面的编写

login.jsp

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>用户登录</title>
</head>
<body>
	<form action="${pageContext.request.contextPath }/login.action" method="post">
		用户账号:<input type="text" name="username"/>
		用户密码:<input type="password" name="password"/><br />
		<input type="submit" value="登录"/>
	</form>
</body>
</html>
项目结构



至此:springmvc的架构入门基本完成,源码可以在我的资源中下载: SpringmvcAddMybatisProjects

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值