很多同学搞不懂拦截器和过滤器的区别,我们先说一下他们的区别:
- 过滤器和拦截器非常相似,但是它们有很大的区别
- 最简单明了的区别就是过滤器可以修改request,而拦截器不能
- 过滤器需要在servlet容器中实现,拦截器可以适用于javaEE,javaSE等各种环境
- 拦截器可以调用IOC容器中的各种依赖,而过滤器不能
- 过滤器只能在请求的前后使用,而拦截器可以详细到每个方法
通俗的说过滤器就是筛选出你要的东西,比如requeset中你要的那部分
拦截器在做安全方面用的比较多,比如终止一些流程。
接下来我们举个简单的例子:
首先是pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<!--thymeleaf-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>1.9.22</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
application.properties
主要配置下thymeleaf
spring.thymeleaf.cache=false
spring.thymeleaf.mode=LEGACYHTML5
login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:http="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<!--<link rel="stylesheet" href="test.css" type="text/css" />-->
<form action="/user/loginUser" method="post">
请输入用户名--:<input type="text" name="userName" id="userName"/><br>
请你输入密码--:<input type="password" name="password" id="password"/><br>
<input type="submit" value="Login"/>
<a href="/user/toRegister">--注册--</a>
</form>
</body>
</html>
welcome.html(登陆成功页面,测试拦截功能,没有登陆前不允许查看此页面)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
注册或登录后才能看到的界面
<a href="/user/outUser">退出登录</a>
</body>
</html>
controller下新建一个LoginController.java,没有连接数据库,
package com.liqiang.demo.controller;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.liqiang.demo.entity.User;
/**
* @Author:liqiang
* @Date: 2019-7-1 10:33
*/
@Controller
@RequestMapping("/user")
public class LoginController {
//跳转首页(登录页)
@RequestMapping("/toIndex")
public String show(){
return "login";
}
//登录操作
@ResponseBody
@RequestMapping("/loginUser")
public String login(User user, HttpServletRequest request){
String userName = user.getUserName();
String password = user.getPassword();
if (userName.equals("aaa") && password.equals("123")){
request.getSession().setAttribute("session_user",user);
//登录成功后将用户放入session中,用于拦截
return "登录成功";
}else{
return "用户名或密码错误";
}
}
//测试未登陆拦截页面
@RequestMapping("/welcome")
public String welcome(){
return "welcome";
}
//退出登录
@RequestMapping("/outUser")
public void outUser(HttpServletRequest request, HttpServletResponse response) throws IOException {
request.getSession().removeAttribute("session_user");
response.sendRedirect("/user/toIndex");
}
}
接下来讲讲实现拦截器功能(敲黑板,本章的重点)
首先在com.liqiang.demo.interceptor下新建intercetor包,然后新建UserIntercetor.java实现HandlerInterceptor接口并重写方法,
package com.liqiang.demo.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.liqiang.demo.entity.User;
/**
* @Author:liqiang
* @Date: 2019-7-1 10:33
*/
public class UserInterceptor implements HandlerInterceptor {
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
System.out.println("执行到了afterCompletion方法");
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
System.out.println("执行了postHandle方法");
}
/*
* 进入controller层之前拦截请求
* 返回值:表示是否将当前的请求拦截下来 false:拦截请求,请求别终止。true:请求不被拦截,继续执行
* Object obj:表示被拦的请求的目标对象(controller中方法)
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("执行到了preHandle方法");
System.out.println(handler);
User user = (User) request.getSession().getAttribute("session_user");
if (user==null){
response.sendRedirect(request.getContextPath()+"/user/toIndex");
//拦截后跳转的方法
System.out.println("已成功拦截并转发跳转");
return false;
}
System.out.println("不需要拦截,放行");
return true;
}
}
新建类SessionInterceptor实现WebMvcConfigurer接口来注册拦截器
SessionInterceptor.java(类里的注释说明也很详细)
package com.liqiang.demo.interceptor;
import java.util.ArrayList;
import java.util.List;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Author:liqiang
* @Date: 2019-7-1 10:33
*/
@Configuration
public class SessionInterceptor implements WebMvcConfigurer {
/**
* 自定义拦截器,添加拦截路径和排除拦截路径
* addPathPatterns():添加需要拦截的路径
* excludePathPatterns():添加不需要拦截的路径
*/
//注册拦截器
@Override
public void addInterceptors(InterceptorRegistry registry) {
List list = new ArrayList();
list.add("/user/toIndex");
list.add("/user/loginUser");
registry.addInterceptor(new UserInterceptor()).addPathPatterns("/**").excludePathPatterns(list);
}
}
这个类中我放行了四个请求,一共写了五个请求,还有一个 "/user/welcome" 请求没有放行,就是用于测试拦截器效果。
在没有登陆前无法查看welcome页面,所有对welcome页面的请求全部拦截,并跳转到登陆界面