拦截器 应用详解--SpringMVC

在实际项目中,拦截器的使用是非常普遍的,例如在购物网站中通过拦截器可以拦截未登录的用户,禁止其购买商品,或者使用它来验证已登录用户是否有相应的操作权限等,Spring MVC提供了拦截器功能,通过配置即可对请求进行拦截处理。

 

拦截器的定义:

要使用Spring MVC中的拦截器,就需要对拦截器类进行定义和配置。通常拦截器类可以通过两种方式来定义。一种是通过实现HandlerInterceptor接口,或继承HandlerInterceptor接口的实现类(如HandlerInterceptorAdapter)来定义;另一种是通过实现WebRequestInterceptor接口,或继承WebRequestInterceptor接口的实现类来定义。

以实现HandlerInterceptor接口的定义方式为例,自定义拦截器类的代码如下所示:

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {    
        
    }

    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {

    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        return false;
    }
}

 

关于这三个方法的具体描述如下:

(1)preHandler()方法:该方法会在控制器方法前执行,其返回值表示是否中断后续操作。当其返回值为true时,表示继续向下执行;当其返回值为false时,会中断后续的所有操作(包括调用下一个拦截器和控制器类中的方法执行等)。

(2)postHandle()方法:该方法会在控制器方法调用之后,其解析试图之前执行。可以通过此方法对请求域中的模型和试图做出进一步的修改。

(3)afterCompletion()方法:该方法会在整个请求完成,即视图渲染结束之后执行。可以通过次方法实现一些资料清理、记录日志信息等工作。

 

拦截器的配置:

要使自定义的拦截器类生效,还需要在Spring MVC的配置文件中进行配置,配置代码如下:

<!-- 配置拦截器 -->
<mvc:interceptors>
    <!-- 使用bean直接定义在<mvc:interceptors>下面的Interceptor将拦截所有请求 -->
    <bean class="com.neuedu.interceptor.LoginInterceptor" />
    <!-- 拦截器1 -->
    <mvc:interceptor>
        <!-- 配置拦截器作用的路径 -->
        <mvc:mapping path="/**" />
        <!-- 配置不需要拦截器作用的路径 -->
        <mvc:exclude-mapping path="" />
        <!-- 定义在<mvc:interceptor>下面的,表示对匹配路径的请求才进行拦截 -->
        <bean class="com.neuedu.interceptor.interceptor1" />
    </mvc:interceptor>
    <!-- 拦截器2 -->
    <mvc:interceptor>
        <mvc:mapping path="/hello" />
        <bean class="com.neuedu.interceptor.interceptor2" />
    </mvc:interceptor>
</mvc:interceptors>

在上述代码中,<mvc:interceptors>元素用于配置一组拦截器,其子元素<bean>中定义是全局拦截器,它会拦截所有的请求;而<mvc:interceptor>元素中定义的是指定路径的拦截器,它会对指定路径下的请求生效。<mvc:interceptor>元素的子元素<mvc:mapping>用于配置拦截器作用的路径,该路径在其属性path中定义。如上述代码path的属性值“/**”表示拦截所有路径,“/hello”表示拦截所有以“/hello”结尾的路径。如果在请求路径中包含不需要拦截的内容,还可以通过<mvc:exclude-mapping>元素进行配置。

需要注意的是,<mvc:interceptor>中的子元素必须按照上述代码的配置顺序进行编写,即<mvc:mapping> -> <mvc:exclude-mapping> -> <bean>的顺序,否则文件会报错。

 

单个拦截器的执行流程如下:

程序首先会执行拦截器类中的preHandle()方法,如果该方法的返回值为true,则程序会继续向下执行处理器中的方法,否则将不再向下执行;在业务处理器(即控制器Controller类)处理完请求后,会执行postHandle()方法,然后会通过DispatcherServlet向客户端返回响应;在DispatcherServlet处理完请求后,才会执行afterCompletion()方法。

 

多个拦截器的执行流程:

当多个拦截器同时工作时,它们的preHandle()方法会按照配置文件中拦截器的配置顺序执行,而它们的postHandle()方法和afterCompletion()方法则会按照配置顺序的反序执行。

假设有两个拦截器Interceptor1和interceptor2,并且在配置文件中,Interceptor1拦截器配置在前。

 

 

 

接下来我们通过拦截器来完成一个用户登录权限验证的案例。

本案例中,只有登陆后的用户才能访问系统中的主页面,如果没有登录系统而直接访问主页面,则拦截器会将请求拦截,并转发到登录页面,同时在登录页面中给出提示信息。如果用户名或密码错误,也会在登录页面给出相应的提示信息。当已登录的用户在系统主页中单击“退出”链接时,系统同样会回到登录页面。

(1)在eclipse中新建一个动态web项目,在lib目录下导入相关Sping MVC的JAE包,搭建Spring MVC的环境。

(2)在src目录下,创建一个com.neuedu.pojo包,并在包中创建User类。在User类中,代码如下:

package com.neuedu.pojo;

public class User {
    private Integer id;//id
    private String username;//用户名
    private String password;//密码
    public Integer getId() {
        return id;
    }
    public void setId(Integer id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getPassword() {
        return password;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

 

(3)在src目录下,新建com.neuedu.controller包,创建控制器类UserController,并在该类中定义向主页跳转、向登录页面跳转、执行用户登录等操作的方法,代码如下:

package com.neuedu.controller;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.neuedu.pojo.User;

@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("wangyifei")
                && password != null && password.equals("123456")) {
            //将用户对象添加到Session
            session.setAttribute("USER_SESSION", user);
            //向主页面跳转
            return "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 "login";
    }
    
}

 

(4)在src目录下,新建com.neuedu.interceptor包,创建拦截器类LoginInterceptor,代码如下:

package com.neuedu.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;

import com.neuedu.pojo.User;

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
            throws Exception {    
        
    }

    @Override
    public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
            throws Exception {

    }

    @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 session = 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;
    }
}

 

(5)配置文件springmvc-config.xml代码如下所示:

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
                http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
                http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <!-- 定义组件扫描器,指定需要扫描的包 -->
    <context:component-scan base-package="com.neuedu.controller"/>
    <!-- 配置注解驱动 -->
    <mvc:annotation-driven />
    <!-- 定义视图解析器 -->
    <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>
        <mvc:interceptor>
            <mvc:mapping path="/**" />
            <bean class="com.neuedu.interceptor.LoginInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>
    
</beans>

 

(6)在WEB-INF目录下新建jsp文件夹中,创建一个系统主页面main.jsp,代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>

    当前用户:${USER_SESSION.username }
    <a href="${pageContext.request.contextPath }/logout">退出</a>
    
</body>
</html>

 

(7)在jsp文件夹创建一个login.jsp,在页面中编写一个用于实现登录操作的form表单,代码如下:

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    ${msg }
    <form action="${pageContext.request.contextPath }/login.action" method="POST">
        用户名:<input type="text" name="username" /><br />&nbsp;&nbsp;&nbsp;码:
        <input type="password" name="password" /><br />
        <input type="submit" value="登录" />
    </form>
</body>
</html>

 

(8)web.xml文件配置代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
  <display-name>interceptor</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  
  <!-- 配置 DispatcherServlet 前端控制器 -->
    <servlet>
        <servlet-name>hello</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    
        <!-- 在此处调用 springmvc.xml 文件 -->
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:springmvc-config.xml</param-value>
        </init-param>

        <!-- 在 tomcat 服务器启动的时候,最先加载它 -->
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>hello</servlet-name>
        <url-pattern>*.action</url-pattern>
    </servlet-mapping>
  
</web-app>

 

(9)整个项目目录结构如下:

 

(10)将项目发布到Tomcat服务器并启动,在浏览器中访问地址 http://localhost:8080/interceptor/main.action,效果如下:

 

未登录,不能直接访问主页面!

 

输入错误用户名“java”和密码“123456”,给出提示!

 

 

输入正确用户名“wangyifei”和密码“123456”,成功进入主页面!

 

 

 

转载请标明出处,谢谢~

posted @ 2018-08-24 14:59  一飞要上天  阅读(1765)  评论(0编辑  收藏  举报