0%

interceptor

Interceptor


Why not Filter

Filter是Servlet提供的组件

Spring创建的Filter是普通的Bean,Servlet并不知道Filter的存在,也无法去调用

Servlet创建的Filter不是Spring的Bean,无法注入

使用Filter需要配置web.xml创建代理类,使用DelegatingFilterProxy

特点

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
47
48
49
50
51
52
53
54
55
package eternal.fire;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

@Order(2)
@Component
public class AuthInterceptor implements HandlerInterceptor {
final Logger logger = LoggerFactory.getLogger(getClass());

final
UserService userService;

public AuthInterceptor(UserService userService) {
this.userService = userService;
}

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.info("preAuthenticate {}...", request.getRequestURI());
authenticateByHeader(request);
return true;
}

private void authenticateByHeader(HttpServletRequest request) {
String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Basic ")) {
logger.info("try to authenticate by Authorization Header");
String up = new String(Base64.getDecoder().decode(authHeader.substring(6)), StandardCharsets.UTF_8);
int pos = up.indexOf(':');
if (pos > 0) {
String email = URLDecoder.decode(up.substring(0, pos), StandardCharsets.UTF_8);
String password = URLDecoder.decode(up.substring(pos + 1), StandardCharsets.UTF_8);
User user = userService.signin(email, password);
request.getSession().setAttribute(UserController.KEY_USER, user);
logger.info("user {} have logged in by Authentication Header", email);
} else {
logger.info("try to authenticate by Authorization Header FAILED!");
}
} else {
logger.info("try to authenticate by Authorization Header FAILED!");
}
}

}

Interceptor是由SpringMVC提供的,注入很方便

Interceptor拦截的是Controller,而Filter拦截的是DispatcherServlet

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
         │   ▲
▼ │
┌───────┐
│Filter1│
└───────┘
│ ▲
▼ │
┌───────┐
┌ ─ ─ ─│Filter2│─ ─ ─ ─ ─ ─ ─ ─ ┐
└───────┘
│ │ ▲ │
▼ │
│ ┌─────────────────┐ │
│DispatcherServlet│<───┐
│ └─────────────────┘ │ │
│ ┌────────────┐
│ │ │ModelAndView││
│ └────────────┘
│ │ ▲ │
│ ┌───────────┐ │
│ ├───>│Controller1│────┤ │
│ └───────────┘ │
│ │ │ │
│ ┌───────────┐ │
│ └───>│Controller2│────┘ │
└───────────┘
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
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
       │   ▲
▼ │
┌───────┐
│Filter1│
└───────┘
│ ▲
▼ │
┌───────┐
│Filter2│
└───────┘
│ ▲
▼ │
┌─────────────────┐
│DispatcherServlet│<───┐
└─────────────────┘ │
│ ┌────────────┐
│ │ModelAndView│
│ └────────────┘
│ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ┐ ▲
│ ┌───────────┐ │
├─┼─>│Controller1│──┼─┤
│ └───────────┘ │
│ │ │ │
│ ┌───────────┐ │
└─┼─>│Controller2│──┼─┘
└───────────┘
└ ─ ─ ─ ─ ─ ─ ─ ─ ┘

可以通过Order指定顺序

特殊的Interceptor:ExceptionHandler

1
2
3
4
@ExceptionHandler(RuntimeException.class)
public ModelAndView handleUnknownException(Exception e) {
return new ModelAndView("500.html", Map.of("error", e.getClass().getSimpleName(), "message", e.getMessage()));
}

作用于所有的Controller

发生异常时,会执行有@ExceptionHandler注解的方法