Spring MVC 第五章:拦截器 Interceptor和拦截器适配器的使用

一.区别: 我们的Filter 是依赖于servlet容器的的,所以在实现的过程中基于函数的回调。而拦截器是依赖于Spring web框架。实现的过程是基于反射机制的。而且过滤器的函数只能在初始化的时候调用一次,而拦截器可以在容器的生命周期中调用多次。

二.应用场景:比如我们直接输入一个URL,但是你没有进行登录账号,那么拦截器会拦截你,进行跳转到登录界面,先登录。

 

拦截器 Interceptor功能:

第一步:配置pom.xml也就是maven的相关包的依赖

注意:还需要添加一下插件,我的版本配置JDK1.8 , xml版本3.1

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.interceptor</groupId>
  <artifactId>SpringMVC-InterceptorProject</artifactId>
  <packaging>war</packaging>
  <version>0.0.1-SNAPSHOT</version>
  <name>SpringMVC-InterceptorProject Maven Webapp</name>
  <url>http://maven.apache.org</url>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-webmvc</artifactId>
    	<version>4.1.2.RELEASE</version>
    </dependency>
  </dependencies>
  <build>
    <finalName>SpringMVC-InterceptorProject</finalName>
    <plugins>
    	<plugin>
    		<groupId>org.apache.maven.plugins</groupId>
    		<artifactId>maven-compiler-plugin</artifactId>
    		<version>3.1</version>
    		<configuration>
    			<source>13</source>
    			<target>13</target>
    		</configuration>
    	</plugin>
    </plugins>
  </build>
</project>

第二步:配置web.xml , 只需要一些基本吧配置就可以。


<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>Archetype Created Web Application</display-name>
  <!-- The front controller of this Spring Web application, responsible for handling all application requests -->
	<servlet>
		<servlet-name>springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<init-param>
			<param-name>contextConfigLocation</param-name>
			<param-value>classpath:springmvc-servlet.xml</param-value>
		</init-param>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- Map all requests to the DispatcherServlet for handling -->
	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	
	<filter>
		<filter-name>characterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>characterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

</web-app>

 

第三步:配置springmvc-servlet.xml的配置,这里需要配置下mvc里的 拦截器 , 所以需要mvc标签。

 

		<!-- 配置拦截器 -->
	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<mvc:exclude-mapping path="/login"/>
			<bean class="com.interceptor.interceptors.LoginInterceptor"></bean>
		</mvc:interceptor>
	</mvc:interceptors>

上述 配置解读:

<mvc:mapping path="/**"/>   解读: 拦截所有路径下的URL

<mvc:exclude-mapping path="/login"/>  解读 : 不拦截login路径的URL

<bean class="com.interceptor.interceptors.LoginInterceptor"></bean>  解读: 配置加载一个LoginInterceptor 拦截器,该拦截器的功能可以自己定义,这个类是由自己创建的。需要实现HandlerInterceptor接口

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:context="http://www.springframework.org/schema/context"
	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/mvc
	http://www.springframework.org/schema/mvc/spring-mvc.xsd">
	<!-- 配置扫描的包 -->
	<context:component-scan base-package="com.interceptor"/>
	
	<!-- 配置视图解析器 -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/pages/"></property>
		<property name="suffix" value=".jsp"></property>
	</bean>
	
		<!-- 配置拦截器 -->
	<mvc:interceptors>
		<mvc:interceptor>
			<mvc:mapping path="/**"/>
			<mvc:exclude-mapping path="/login"/>
			<bean class="com.interceptor.interceptors.LoginInterceptor"></bean>
		</mvc:interceptor>
	</mvc:interceptors>
	
</beans>

第四步:

创建一个AccountController.java 逻辑不用去实现,我们只需要页面拦截就可以

HttpSession 解读: 如果你想直接登录用户界面,那么你的用户信息是会保存在session里的,如果有用户信息则不需要再次登录。

addObject 解读: 用户信息会一直保存在session中,直到一定时间或者用户退出,才会清除。所以需要把登录的用户信息保存到account界面

setViewName 解读: 设置返回的页面

package com.interceptor.controller;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("account")
public class AccountController {
	@RequestMapping("info")
	public ModelAndView showAccount(HttpSession session) {
		ModelAndView modelAndView = new ModelAndView();
		//先获取session中的信息,
		modelAndView.addObject("name",session.getAttribute("name"));
		//页面名字 = account.jsp
		modelAndView.setViewName("account");
		return modelAndView;
	}
}

 

第五步:

先建一个account的账户界面,显示用户信息。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Add User</title>
<style type="text/css">

</style>
</head>
<body>
	<h2> Account TEST</h2>
	the name is ${name}
</body>
<script type="text/javascript">

</script>
</html>

 

第六步:

登录的控制器:LoginController

    首先会有两个方法,一个是强行登陆用户界面,被拦截到登录界面。需要保存上个页面account.jsp
    当登录成功后会跳转到用户界面.也需要保存上一个界面account.jsp
    一般我们的显示登录界面就不需要在写一个映射路径,表单提交是用post

package com.interceptor.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 org.springframework.web.bind.annotation.RequestParam;

@Controller
@RequestMapping("login")
public class LoginController {
	//首先会有两个方法,一个是强行登陆用户界面,被拦截到登录界面。需要保存上个页面account.jsp
	//当登录成功后会跳转到用户界面.也需要保存上一个界面
	//一般我们的显示登录界面就不需要在写一个映射路径,表单提交是用post
	@RequestMapping(method = RequestMethod.GET)
	public String showLogin(@RequestParam("next") String next, Model model) {
		//当被拦截后,我们需要记录你想登录的界面是哪个? 被拦截后跳转到哪个界面了。
		model.addAttribute("next", next);
		System.out.println("next jsp: "+next);
		return "login";
	}
	
	//这里为什么不用Model对象呢? 因为就用户和密码两项,就不需要在去额外创建一个账户对象,直接接受参数就可以
	@RequestMapping(method=RequestMethod.POST)
	public String submitLogin(@RequestParam("next") String next, 
			@RequestParam("username") String username,
			@RequestParam("password") String password,
			Model model, HttpSession session) {
		System.out.println("next jsp: "+next);
		session.setAttribute("name", username);
		// redirect重定向
		return "redirect:".concat(next);
	}
	
}

配套的login.jsp提交登录的用户信息

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Add User</title>
<style type="text/css">

</style>
</head>
<body>
	<h2> Add TEST</h2>
	<form action="login" method="POST">
		ID:<input type="text" name="username"><br>
		Password:<input type="password" name="password"><br>
		<input type="hidden" name="next" value="${next }">
		<input type="submit" value="Login">
		
	</form>
</body>
<script type="text/javascript">

</script>
</html>

 

第六步:设置拦截器

实现拦截器接口,实现预处理的功能,把这个类加载到springmvc-servlet.xml中,会拦截所有url。

package com.interceptor.interceptors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class LoginInterceptor implements HandlerInterceptor {

	//预处理的一个回调方法,是在执行Controller之前会调用这个方法进行拦截判定
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// 即执行accountController之前调用此方法
		String name = (String)request.getSession().getAttribute("name");
		System.out.println("name = " + name);
		if(name!=null&&!name.equals("")) {
			return true;
		}
		
		String url = request.getRequestURI();
		System.out.println("url = " + url);
		response.sendRedirect("/SpringMVC-InterceptorProject/login?next=".concat(url.substring(29, url.length())));
		return false;
	}

	//是在视图渲染之前 进行调用,可以在modelAndView进行视图修改
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// 即执行accountController之后调用此方法,才会进行主视图的渲染

	}

	// 这个就是相当于try..catch中的finally作用,在执行完最后才执行这个,一定会执行的
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {

	}

}

 

开始测试,

1.我们在浏览器中输入:http://localhost:8080/SpringMVC-InterceptorProject/account/info进行强行登录。

在没有登录账户的情况下,强行进入account.jsp 首先会被拦截器检测到account中的name=null;

所以会触发重定向,跳转到了登录界面:http://localhost:8080/SpringMVC-InterceptorProject/login?next=/account/info,并且保存了上一个界面的映射路径/account/info

2.此时会触发了loginController的映射,会自动调用“showLogin()”方法:并且保存了上一个界面的映射路径/account/info

我们会将 映射路径/account/info 保存到 login.jsp中

3.当我输入账户密码验证

点击登录!不会触发拦截器,因为设置了不拦截login的URL

会进入到 LoginController 中的submitLogin()方法 : 并且取出 jsp=/account/info

4.登录成功,并且显示用户名:

 

 

也有一种更简单的拦截器,叫做拦截器适配器,可以根据自己的需求进行设定拦截器。

通过继承HandlerInterceptorAdapter类,实现的功能是一样,只是不用同时实现三个方法,可以实现其中的某一个拦截器方法。

package com.interceptor.interceptors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class LoginInterceptorAdaptor extends HandlerInterceptorAdapter {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		String name = (String)request.getSession().getAttribute("name");
		if(name!=null&&!name.equals("")) {
			return true;
		}
		
		String url = request.getRequestURI();
		response.sendRedirect("/SpringMVC-InterceptorProject/login?next=".concat(url.substring(29, url.length())));
		return false;
	}
	
}

然后在springmvc-servlet.xml中配置下就可以了。原理是一样的。

<bean class="com.interceptor.interceptors.LoginInterceptorAdaptor"></bean>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逼哥很疯狂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值