第1关:自定义拦截器
任务描述
本关任务:自定义拦截器完成 URI 的拦截
相关知识
为了完成本关任务,你需要掌握:如何自定义拦截器
拦截器(Interceptor)
拦截器(Interceptor)是 AOP 的一种实现,它能对 Controller 层的方法前后进行拦截处理。
简单地来说就是对一些请求进行拦截,比如说:用户主页这个页面必须在用户登录之后才能进行访问的,如果我们不使用拦截器的话,那么用户就能进行访问到用户页面,在实际情况下,用户访问的页面都是有限的,为什么这么说呢?
因为用户访问的页面是跟用户的权限直接挂钩的,比如说用户A是管理员、用户B是普通用户,他两货访问的页面范围是不同的,用户A除了可以访问用户B能访问的页面还能访问只属于管理员能访问的页面。这个页面访问的权限控制就可以通过拦截器来实现。
上面介绍了什么是拦截器,接下来就是怎么使用拦截器了?
拦截器的使用步骤有两个步骤
-
定义拦截器组件,就是创建一个类实现 HandlerInterceptor 接口
-
注册拦截器,就是创建一个配置类实现 WebMvcConfigurer 接口,然后将拦截器组件与 InterceptorRegistry 进行绑定,设置拦截范围
案例代码如下:
拦截器组件
@Component
public class Step1Interceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("进入controller层之前拦截请求");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("处理请求完成后视图渲染之前的处理操作");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("视图渲染之后的操作");
}
}
拦截器配置类
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Resource
Step1Interceptor step1Interceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 自定义拦截器,添加拦截路径和排除拦截路径
registry.addInterceptor(step1Interceptor).addPathPatterns("/**");
}
}
Controller类
@Controller
public class MainController {
@RequestMapping("/index")
@ResponseBody
public String index() {
System.out.println("Controller 处理逻辑");
return "INDEX";
}
}
浏览器访问:localhost:8080/index
控制台输出
进入controller层之前拦截请求
Controller 处理逻辑
处理请求完成后视图渲染之前的处理操作
视图渲染之后的操作
HandlerInterceptor 类详解
boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception;
void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)throws Exception;
void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)throws Exception;
-
preHandle:进入controller层之前拦截请求,返回 true 进行下一步处理,返回 false 不进行下一步处理(也就是说拦截了)。预处理,可以进行编码、安全控制、权限校验等处理;
-
postHandle:处理请求完成后视图渲染之前的处理操作。后处理(调用了Service并返回ModelAndView,但未进行页面渲染),有机会修改ModelAndView;
-
afterCompletion:视图渲染之后的操作,可用于清理资源等。返回处理(已经渲染了页面);
编程要求
根据提示,在右侧编辑器补充代码,完成以下需求:
测试说明
平台会对你编写的代码进行测试,会通过发起 HTTP 请求,访问以下 URL 来判断是否拦截成功
-
localhost:8080/JD/index
-
localhost:8080/JD/home
-
localhost:8080/taobao/index
-
localhost:8080/taobao/home
开始你的任务吧,祝你成功!
demo/src/main/java/net/educoder/conf/Step1Interceptor.java
package net.educoder.conf;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class Step1Interceptor implements HandlerInterceptor {
/**
* 需求:过滤掉 URI 为 /taobao/* 的所有请求
* <p>
* 例如:
* 浏览器访问 localhost:8080/taobao/index --> 过滤掉
* 浏览器访问 localhost:8080/taobao/home --> 过滤掉
*/
/********** begin **********/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String uri = request.getRequestURI();
if (uri.startsWith("/taobao/")) {
// 如果请求URI以/taobao/开头,拦截请求
return false;
}
// 允许请求通过
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
/********** end **********/
}
demo/src/main/java/net/educoder/conf/WebConfig.java
package net.educoder.conf;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private Step1Interceptor step1Interceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(step1Interceptor).addPathPatterns("/**");
}
}
加油,相信自己,也能和我一样写出属于自己的代码!
第2关:token 认证拦截器
任务描述
本关任务:编写一个 token 认证拦截器
编程要求
根据提示,在右侧编辑器补充代码,完成以下需求:
拦截 URI 为 /home
的请求,如果符合以下要求则放行
-
放行要求: 请求头中包含
user-token
并且请求头的user-token
的值在tokenList
中 -
不符合要求:通过
response
将页面重定向到/login
页面
测试说明
平台会对你编写的代码进行测试,会通过发起 HTTP 请求,访问以下 URL 来判断是否拦截成功
localhost:8080/home
查看效果页面默认的路由为 /home
开始你的任务吧,祝你成功!
demo2/src/main/java/net/educoder/conf/Step2Interceptor.java
package net.educoder.conf;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
@Component
public class Step2Interceptor implements HandlerInterceptor {
private List<String> tokenList = Arrays.asList("22854D7A00FDB48AC4130380AE67B2F7", "11354E7A00FDB48AC4130380AE67B2F7");
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String userToken = request.getHeader("user-token");
if (userToken != null && tokenList.contains(userToken)) {
return true;
} else {
response.sendRedirect("/login");
return false;
}
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// This method is intentionally left blank
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
// This method is intentionally left blank
}
}
demo2/src/main/java/net/educoder/conf/WebConfig.java
package net.educoder.conf;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private Step2Interceptor step2Interceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(step2Interceptor)
.addPathPatterns("/home");
}
}