java里的拦截器是动态拦截Action调用的对象。它提供了一种机制可以使开发者可以定义在一个action执行的前后执行的代码,也可以在一个action执行前阻止其执行,同时也提供了一种可以提取action中可重用部分的方式。在AOP(Aspect-Oriented Programming)中拦截器用于在某个方法或字段被访问之前,进行拦截然后在之前或之后加入某些操作。

<The rest of contents | 余下全文>

HandlerInterceptor 接口介绍:

在HandlerInterceptor 中有三个方法:

1
2
3
4
5
6
7
8
9
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}

default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}

default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}

preHandle: 预处理方法,实现处理器的预处理(例如登录状态),handler参数为相应的处理器,返回值:true表示继续流程,false表示流程中断,我们需要通过reponse来产生响应.

postHandle:后处理回调方法,实现处理器的后处理(但在渲染视图之前),此时我们可以通过modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView也可能为null。

afterCompletion:整个请求处理完毕回调方法,即在视图渲染完毕时回调,如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于try-catch-finally中的finally,但仅调用处理器执行链中preHandle返回true的拦截器的afterCompletion。

配置拦截器:

创建拦截器类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package caicai.springbootinterceptor1.interceptor;

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

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

/**
* @author liu
* @title: LoginInterceptor
* @projectName spring-boot-interceptor1
* @description: TODO
* @date 2019/4/1216:31
*/
public class LoginInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
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.............................");
}
}

创建拦截器配置类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package caicai.springbootinterceptor1.config;

import caicai.springbootinterceptor1.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
* @author liu
* @title: LoginInterceptorConfig
* @projectName spring-boot-interceptor1
* @description: TODO
* @date 2019/4/1216:33
*/
@Configuration
public class LoginInterceptorConfig implements WebMvcConfigurer{
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/login");

}
}

addPathPatterns(“/**”):表示拦截所有的url请求;

excludePathPatterns(“/login”):表示排除login

完成了拦截器配置后,在启动springboot项目的时候,除了login以外,其他所有的请求都会经过拦截器处理,我们可以使用preHandle来完成一个登录验证的功能

登录验证实现:

效果:

1.有两个界面: 登录界面, 主界面

2:登录界面和主界面都可以通过相应请求跳转到,但是主界面只有登录之后才能查看,否则就跳回登录界面

项目目录:

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login">
<span>用户名:</span> <input type="text" name="username">
<span>密码:</span> <input type="text" name="password">
<button>提交</button>
</form>
</body>
</html>

main.html

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"><head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>这里是主页面</h1>
当前登录用户:<span th:text="${session.username}"></span>
</body>
</html>

如果登录的话 ${session.username}会获取到存贮在session中的用户名

Logininterceptor.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package caicai.springbootinterceptor1.interceptor;

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

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

/**
* @author liu
* @title: LoginInterceptor
* @projectName spring-boot-interceptor1
* @description: TODO
* @date 2019/4/1216:31
*/
public class LoginInterceptor implements HandlerInterceptor{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
/**
通过session中的用户名来判断是否登录,因为一旦登录了就会在session中存储用户名
**/
if(request.getSession().getAttribute("username")!=null){
System.out.println("登录了");
return true;
}else{
System.out.println("未登录");
response.sendRedirect(request.getContextPath()+"/index");

return false;
}

}

@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.............................");
}
}

LoginController

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
package caicai.springbootinterceptor1.controller;

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

import javax.servlet.http.HttpServletRequest;

/**
* @author liu
* @title: LoginController
* @projectName spring-boot-interceptor1
* @description: TODO
* @date 2019/4/1216:22
*/
@Controller
public class LoginController {

/**
登录界面的url映射
**/
@RequestMapping("/index")
public String index(){
return "index";
}
/**
登录,此处直接用字符串是否是admin的方式来模拟数据库查询登录
若账号密码正确则跳转到main界面若账号密码错误则继续跳转到登录界面
**/
@RequestMapping("/login")
public String login(String username, String password, HttpServletRequest request){
if (username.equals("admin")&& password.equals("admin")){
request.getSession().setAttribute("username",username);
return "main";
}else {
return "login";
}
}
/**
主界面的url映射 为了测试不登陆直接进主页面被拦截
**/
@RequestMapping("/main")
public String main(){
return "main";
}

}

LoginInterceptorConfig.java:

配置文件,配置了拦截器和拦截路径

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package caicai.springbootinterceptor1.config;

import caicai.springbootinterceptor1.interceptor.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
* @author liu
* @title: LoginInterceptorConfig
* @projectName spring-boot-interceptor1
* @description: TODO
* @date 2019/4/1216:33
*/
@Configuration
public class LoginInterceptorConfig implements WebMvcConfigurer{
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/login").excludePathPatterns("/index");

}
}

本实例只是粗略的完成了登录拦截的功能,对于一些细节没有完善,例如错误提示等.