在开发一个网站时可能有这样的需求:某些页面只希望几个特定的用户浏览。对于这样的访问权限控制,应该如何实现呢?
Spring MVC的拦截器(Interceptor)与Java Servlet的过滤器(Filter)类似,它主要用于拦截用户的请求并作出相应的处理,通常应用在权限验证,记录请求信息的日志,判断用户是否登录等功能上。
github项目:https://github.com/chegy218/ssm-review/tree/master/interceptor
Spring MVC拦截器的使用
1,Spring MVC自定义拦截器
public class TestInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request,HttpServletResponse response,Object handler){
System.out.println("preHandle方法在控制器的处理请求方法前执行");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView)
throws Exception{
System.out.println("postHandle 方法在控制器的处理请求方法调用之后,解析视图之前执行");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex)
throws Exception{
System.out.println("afterCompletion 方法在控制器的处理请求方法执行完成后执行,即视图渲染结束之后执行");
}
}
2,拦截器的配置
在xml配置文件中配置拦截器,如下代码
<mvc:interceptors>
<!-- 配置一个全局拦截器,拦截所有请求 -->
<bean class="interceptor.interceptors.TestInterceptor"/>
<mvc:interceptor>
<!-- 配置拦截器作用的路径-,/** 表示拦截所有路径->
<mvc:mapping path="/**"/>
定义在<mvc:interceptor/>元素中,表示匹配指定路径的请求才能进行拦截
<bean class="interceptor.interceptors.Interceptor1"/>
</mvc:interceptor>
<mvc:interceptor>
<!-- 配置拦截器作用的路径,/gotoTest 拦截以/gotoTest结尾的路径-->
<mvc:mapping path="/gotoTest"/>
<!-- 定义在<mvc:interceptor/>元素中,表示匹配指定路径的请求才能进行拦截-->
<bean class="interceptor.interceptors.Interceptor2"/>
</mvc:interceptor>
</mvc:interceptors>
简述单个拦截器和多个拦截器的执行流程
1,单个拦截器
2,多个拦截器
应用案例——用户登录权限验证
需求分析:只有成功登录的用户才能访问系统的主页面main.jsp,如果没有成功登录而直接访问主页面,则拦截器将请求拦截,并转发到登录页面login.jsp。当成功登录的用户在系统主页面中点击“退出”链接时回到登录页面。
1,定义User类
public class User {
private String uname;
private String upwd;
//省略setter和getter方法
}
2,创建控制器类
@Controller
public class UserController {
/**
* 登录页面初始化
* @return
*/
@RequestMapping("/toLogin")
public String initLogin(){
return "login";
}
@RequestMapping("/login")
public String login(User user,Model model,HttpSession session){
System.out.println(user.getUname());
if("chenheng".equals(user.getUname()) &&
"123456".equals(user.getUpwd())){
//登录成功,将用户信息保存到session对象中
session.setAttribute("user", user);
//重定向到主页面的跳转页面
return "redirect:main";
}
model.addAttribute("msg","用户名或密码错误,请重新登录!");
return "login";
}
/**
* 跳转到主页面
* @return
*/
@RequestMapping("/main")
public String toMain(){
return "main";
}
/**
* 退出登录
* @param session
* @return
*/
@RequestMapping("/logout")
public String logout(HttpSession session){
//清除session
session.invalidate();
return "login";
}
}
3,创建拦截器类
public class LoginInterceptor implements HandlerInterceptor{
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception{
//获得请求的URL
String url = request.getRequestURI();
//login.jsp或登录请求放行,不拦截
if(url.indexOf("/toLogin")>=0 || url.indexOf("/login") >= 0){
return true;
}
//获取session
HttpSession session = request.getSession();
Object obj = session.getAttribute("user");
if(obj != null){
return true;
}
//没有登录且不是登录页面,转发到登录页面,并给出提示错误信息
request.setAttribute("msg", "还没有登录,请先登录!");
request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response);
return false;
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView)
throws Exception{
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex)
throws Exception{
}
}
4,配置拦截器
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<!-- 使用扫描机制扫描控制器类,控制器类都在包及其子包下 -->
<context:component-scan base-package="interceptor.controller"></context:component-scan>
<!-- 视图解析器 -->
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<!-- 前缀 -->
<property name="prefix" value="/WEB-INF/jsp/"></property>
<!-- 后缀 -->
<property name="suffix" value=".jsp"></property>
</bean>
<mvc:interceptors>
<!--应用案例-用户登录权限验证-->
<mvc:interceptor>
配置拦截器作用的路径
<mvc:mapping path="/**"/>
<bean class="interceptor.controller.LoginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
</beans>
5,创建视图JSP页面
login.jsp的代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>Insert title here</title>
</head>
<body>
${msg }
<form action="${pageContext.request.contextPath }/login" method="post">
用户名:<input type="text" name="uname"><br>
密码:<input type="password" name="upwd"><br>
<input type="submit" value="登录"/>
</form>
</body>
</html>
main.jsp代码如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!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=UTF-8">
<title>main.jsp</title>
</head>
<body>
当前用户:${user.uname }
<a href="${pageContext.request.contextPath }/logout">退出</a>
</body>
</html>
6,发布并测试
图一,没有登录直接访问主页面的效果
图二,成功登录的效果
图三,用户名或密码错误