SpringBoot * 的配置使用介绍
作者:刘婉晴 发布时间:2021-06-20 07:25:54
1. 配置 *
具体步骤:
编写一自定义 * 类实现接口 HandlerInterceptor
HandlerInterceptor 接口: 可在三处进行拦截——目标方法执行之前、目标方法执行完成、页面渲染以后拦截
public interface HandlerInterceptor {
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 {
}
}
将 * 注册到容器中,实现 WebMvcConfigurer 中的 addInteraptor,然后将自定义 * 注册到 * 中
指定 * 规则 —— 拦截所有 '/**'
,静态资源也会被拦截
解决静态资源同时被拦截问题:
在
addPathPatterns
中精确指定精确需要拦截资源在
excludePathPatterns
中指定排除静态资源
可在 application.properties 文件中指定静态资源统一前缀,方便排除静态资源
spring.mvc.static-path-pattern=/static/**
2. 一个小 Demo
实现未登录用户不能访问除登录页外其他页面的小Demo
1. 自定义 * 类—LoginInterceptor
自定义登录 * ,实现检测到用户未登录,则拦截用户对其他资源的访问,并返回到登录页面
package com.wanqing.admin.interceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.Session;
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;
import javax.servlet.http.HttpSession;
/*
登录检查
*/
@Slf4j // lombok 提供的功能
public class LoginInterceptor implements HandlerInterceptor {
// 目标方法执行之前
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("拦截的路径是{}", request.getRequestURI());
// 登录检查逻辑
HttpSession session = request.getSession();
Object loginUser = session.getAttribute("loginUser");
if(loginUser != null){
return true; // 放行
}
// 拦截住,重定向到登录页面
request.setAttribute("msg", "未登录不允许访问");
request.getRequestDispatcher("/").forward(request, response); // 转发到当前请求
return false;
}
// 目标方法执行之后
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
// 页面渲染完成之后
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
2. 将 * 注册到容器中
通过下列方法,将 * 注册到容器中,并配置好要拦截的路径和要放行的路径。本次 demo 中若未登录则所有路径都拦截,只放行登录页面
package com.wanqing.admin.config;
import com.wanqing.admin.interceptor.LoginInterceptor;
import lombok.extern.slf4j.Slf4j;
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 AdminWebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 在 * 的注册中心里,添加 Login *
registry.addInterceptor(new LoginInterceptor())
.addPathPatterns("/**") //所有请求都被拦截,静态资源也被拦截
.excludePathPatterns("/","/login","/css/**","/fonts/**","/images/**","/js/**"); // 放行的请求
}
}
3. 原理分析
1. 根据当前请求,找到HandlerExecutionChainand,即得到可以处理请求的 Handler,以及 Handler 的所有 *
处理器执行链 :
2. 先顺序执行所有 * 的preHandle
方法
如果返回为true执行下一个 * 的
preHandle
;若为 false,直接倒叙执行所有已经执行了的 * 的
afterCompletion
方法
Step into:
if (!mappedHandler.applyPreHandle(processedRequest, response)) {
return;
}
* 方法执行 源码分析:
HandlerExecutionChain.class
—— 顺序执行所有 * 的preHandle
方法
for(int i = 0; i < this.interceptorList.size(); this.interceptorIndex = i++) {
HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
if (!interceptor.preHandle(request, response, this.handler)) {
this.triggerAfterCompletion(request, response, (Exception)null);
return false;
}
}
—— 倒叙执行所有已经执行了的 * 的 afterCompletion
方法
void triggerAfterCompletion(HttpServletRequest request, HttpServletResponse response, @Nullable Exception ex) {
for(int i = this.interceptorIndex; i >= 0; --i) {
HandlerInterceptor interceptor = (HandlerInterceptor)this.interceptorList.get(i);
try {
interceptor.afterCompletion(request, response, this.handler, ex);
} catch (Throwable var7) {
logger.error("HandlerInterceptor.afterCompletion threw exception", var7);
}
}
}
3. 如果任何一个 * 返回 false,直接跳出不执行目标方法
4. 所有 * 都返回 true,执行目标方法
5. 目标方法执行后,倒叙执行所有 * 的 postHandle 方法
6. 前面的步骤有任何异常都会直接触发 afterCompletion 方法
7. 页面成果渲染完成之后,也会倒叙触发 afterCompletion 方法
图解:
来源:https://blog.csdn.net/liuwanqing233333/article/details/127235421


猜你喜欢
- 1.控制屏幕常亮首先导入模块import brightness from '@system.brightness';接下来在
- 下面一段代码给大家介绍了android 自定义顶部导航栏控件功能,具体代码如下所示:class HeaderBar @JvmOverload
- 背景相信大家对Android Studio已经不陌生了,Android Studio是Google于2013 I/O大会针对Android开
- 一、如何实现TCP通信要实现TCP通信需要创建一个服务器端程序和一个客户端程序,为了保证数据传输的安全性,首先需要实现服务器端程序,然后在编
- 近期工作内容需要涉及到相机开发,其中一个功能点就是实现一个相机预览页底部的滑动指示器,现在整理出来供大家讨论参考。先上一张图看下效果:主要实
- 1. 源起:仍然是模块化编程所引发的需求。产品经理难伺候,女产品经理更甚之~:p纯属戏谑,技术方案与产品经理无关,芋头莫怪!VCU10项目重
- 在我们对程序进行操作过程中,一般都需要有一个操作流程的记录显示。用C#进行编程时可以很容易实现这个功能。本经验提供案例仅供参考下面小编就来介
- 前言:本文主要介绍内容有:一个串行调用的例子(App首页信息查询)CompletionService实现并行调用抽取通用的并行调用方法代码思
- 代码很简单,这里就不多废话了,直接奉上代码using UnityEngine;using System.Collections;public
- 实际的项目开发当中,经常需要根据实际的需求来自定义AlertDialog。最近在开发一个WIFI连接的功能,点击WIFI需要弹出自定义密码输
- Java多态对象的类型转换这里所说的对象类型转换,是指存在继承关系的对象,不是任意类型的对象。当对不存在继承关系的对象进行强制类型转换时,j
- 1.Fragment概述在一个Activity中, Fragment代表UI的一个部分或者一个行为。一个Activity可以结合多个Frag
- 本文实例为大家分享了java将一个目录下的所有文件复制n次的具体代码,供大家参考,具体内容如下1. 文件复制示意图 2.java程
- 1.PDF文件简介PDF是可移植文档格式,是一种电子文件格式,具有许多其他电子文档格式无法相比的优点。PDF文件格式可以将文字、字型、格式、
- Android平台有三种网络接口可以使用,他们分别是:java.net.*(标准Java接口)、Org.apache接口和Android.n
- 目录Shiro简介Shiro快速入门SpringBoot-Shiro整合(最后会附上完整代码)附上最后的完整代码Shiro整合mybatis
- 最近的需求有一个自动发布的功能, 需要做到每次提交都要动态的添加一个定时任务代码结构1. 配置类package com.orion.ops.
- 本文实例为大家分享了java数字转汉字工具类的具体代码,供大家参考,具体内容如下/** * Created by 33303 on 2017
- 说明本文主要配置Jackson对Long、Date、LocalDate、LocalDateTime的序列化和反序列化。由于js中整数可精确表
- 一、系统介绍本系统实现扑克的分发,抢地主,电脑自动出牌等功能。二、系统展示1.扑克分发2.抢地主3.出牌4.游戏胜利三、系统实现Card.j