feat: 新增 sa-token-spring-boot4-starter 集成包

This commit is contained in:
click33
2026-02-26 01:19:41 +08:00
parent f6c5131ad2
commit 2d671dc783
15 changed files with 784 additions and 1 deletions

View File

@@ -24,6 +24,7 @@ cd sa-token-demo-solon & call mvn clean & cd ..
cd sa-token-demo-solon-redisson & call mvn clean & cd ..
cd sa-token-demo-springboot & call mvn clean & cd ..
cd sa-token-demo-springboot3-redis & call mvn clean & cd ..
cd sa-token-demo-springboot4-redis & call mvn clean & cd ..
cd sa-token-demo-springboot-low-version & call mvn clean & cd ..
cd sa-token-demo-springboot-redis & call mvn clean & cd ..
cd sa-token-demo-springboot-redisson & call mvn clean & cd ..

View File

@@ -81,6 +81,11 @@
<artifactId>sa-token-spring-boot3-starter</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot4-starter</artifactId>
<version>${revision}</version>
</dependency>
<!-- endregion-->
<!-- region sa-token-plugin -->

View File

@@ -17,11 +17,12 @@
<!-- 统一定义依赖版本号 -->
<springboot.version>2.7.18</springboot.version>
<springboot3.version>3.4.3</springboot3.version>
<springboot4.version>4.0.3</springboot4.version>
<spring-web.low.version>5.3.39</spring-web.low.version>
<reactor-core.version>3.7.4</reactor-core.version>
<jackson-databind.version>2.13.4.1</jackson-databind.version>
<jackson-datatype-jsr310.version>2.11.2</jackson-datatype-jsr310.version>
<jackson3-databind.version>3.0.0</jackson3-databind.version>
<jackson3-databind.version>3.1.0</jackson3-databind.version>
<servlet-api.version>3.1.0</servlet-api.version>
<jakarta-servlet-api.version>6.0.0</jakarta-servlet-api.version>
<thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
@@ -70,6 +71,13 @@
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- spring-boot-starter-webmvc (Spring Boot 4) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
<version>${springboot4.version}</version>
</dependency>
<!-- spring-boot-starter -->
<dependency>

View File

@@ -23,6 +23,7 @@
<module>sa-token-spring-boot-autoconfig</module>
<module>sa-token-spring-boot-starter</module>
<module>sa-token-spring-boot3-starter</module>
<module>sa-token-spring-boot4-starter</module>
<module>sa-token-reactor-spring-boot-starter</module>
<module>sa-token-reactor-spring-boot3-starter</module>
<module>sa-token-solon-plugin</module>

View File

@@ -0,0 +1,101 @@
<?xml version='1.0' encoding='utf-8'?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-starter</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<packaging>jar</packaging>
<name>sa-token-spring-boot4-starter</name>
<artifactId>sa-token-spring-boot4-starter</artifactId>
<description>springboot4 integrate sa-token</description>
<properties>
<springboot4.version>4.0.3</springboot4.version>
</properties>
<dependencies>
<!-- spring-boot-starter-webmvc (Spring Boot 4 recommended, replaces deprecated starter-web) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<!-- config (optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- sa-token-jakarta-servlet -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jakarta-servlet</artifactId>
</dependency>
<!-- sa-token-spring-boot-autoconfig (exclude sa-token-jackson, use sa-token-jackson3 for Spring Boot 4) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-autoconfig</artifactId>
<exclusions>
<exclusion>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jackson</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- sa-token-jackson3: JSON serialization for Spring Boot 4 (Jackson 3) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jackson3</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- spring-boot-starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${springboot4.version}</version>
</dependency>
<!-- spring-boot-starter-webmvc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
<version>${springboot4.version}</version>
</dependency>
<!-- config (optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${springboot4.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.filter;
import cn.dev33.satoken.exception.BackResultException;
import cn.dev33.satoken.exception.FirewallCheckException;
import cn.dev33.satoken.exception.StopMatchException;
import cn.dev33.satoken.servlet.model.SaRequestForServlet;
import cn.dev33.satoken.servlet.model.SaResponseForServlet;
import cn.dev33.satoken.servlet.util.SaJakartaServletOperateUtil;
import cn.dev33.satoken.strategy.SaFirewallStrategy;
import cn.dev33.satoken.util.SaTokenConsts;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.annotation.Order;
import java.io.IOException;
/**
* 防火墙校验过滤器 (基于 Jakarta-Servlet)
*
* @author click33
* @since 1.37.0
*/
@Order(SaTokenConsts.FIREWALL_CHECK_FILTER_ORDER)
public class SaFirewallCheckFilterForJakartaServlet implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
SaRequestForServlet saRequest = new SaRequestForServlet(req);
SaResponseForServlet saResponse = new SaResponseForServlet(res);
try {
SaFirewallStrategy.instance.check.execute(saRequest, saResponse, null);
}
catch (StopMatchException ignored) {}
catch (BackResultException e) {
SaJakartaServletOperateUtil.writeResult(response, e.getMessage());
return;
}
catch (FirewallCheckException e) {
if(SaFirewallStrategy.instance.checkFailHandle == null) {
SaJakartaServletOperateUtil.writeResult(response, e.getMessage());
} else {
SaFirewallStrategy.instance.checkFailHandle.run(e, saRequest, saResponse, null);
}
return;
}
// 更多异常则不处理,交由 Web 框架处理
// 向内执行
chain.doFilter(request, response);
}
}

View File

@@ -0,0 +1,146 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.filter;
import cn.dev33.satoken.exception.BackResultException;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.exception.StopMatchException;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.servlet.util.SaJakartaServletOperateUtil;
import cn.dev33.satoken.util.SaTokenConsts;
import jakarta.servlet.*;
import org.springframework.core.annotation.Order;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 全局鉴权过滤器 (基于 Jakarta-Servlet)
* <p>
* 默认优先级为 -100尽量保证在其它过滤器之前执行
* </p>
*
* @author click33
* @since 1.34.0
*/
@Order(SaTokenConsts.ASSEMBLY_ORDER)
public class SaServletFilter implements SaFilter, Filter {
// ------------------------ 设置此过滤器 拦截 & 放行 的路由
/**
* 拦截路由
*/
public List<String> includeList = new ArrayList<>();
/**
* 放行路由
*/
public List<String> excludeList = new ArrayList<>();
@Override
public SaServletFilter addInclude(String... paths) {
includeList.addAll(Arrays.asList(paths));
return this;
}
@Override
public SaServletFilter addExclude(String... paths) {
excludeList.addAll(Arrays.asList(paths));
return this;
}
@Override
public SaServletFilter setIncludeList(List<String> pathList) {
includeList = pathList;
return this;
}
@Override
public SaServletFilter setExcludeList(List<String> pathList) {
excludeList = pathList;
return this;
}
// ------------------------ 钩子函数
/**
* 认证函数:每次请求执行
*/
public SaFilterAuthStrategy auth = r -> {};
/**
* 异常处理函数:每次[认证函数]发生异常时执行此函数
*/
public SaFilterErrorStrategy error = e -> {
throw new SaTokenException(e);
};
/**
* 前置函数:在每次[认证函数]之前执行
* <b>注意点:前置认证函数将不受 includeList 与 excludeList 的限制,所有路由的请求都会进入 beforeAuth</b>
*/
public SaFilterAuthStrategy beforeAuth = r -> {};
@Override
public SaServletFilter setAuth(SaFilterAuthStrategy auth) {
this.auth = auth;
return this;
}
@Override
public SaServletFilter setError(SaFilterErrorStrategy error) {
this.error = error;
return this;
}
@Override
public SaServletFilter setBeforeAuth(SaFilterAuthStrategy beforeAuth) {
this.beforeAuth = beforeAuth;
return this;
}
// ------------------------ doFilter
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
// 执行全局过滤器
beforeAuth.run(null);
SaRouter.match(includeList).notMatch(excludeList).check(r -> {
auth.run(null);
});
}
catch (StopMatchException ignored) {}
catch (BackResultException e) {
SaJakartaServletOperateUtil.writeResult(response, e.getMessage());
return;
}
catch (Throwable e) {
SaJakartaServletOperateUtil.writeResult(response, String.valueOf(error.run(e)));
return;
}
// 执行
chain.doFilter(request, response);
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.filter;
import cn.dev33.satoken.servlet.util.SaTokenContextJakartaServletUtil;
import cn.dev33.satoken.util.SaTokenConsts;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.annotation.Order;
import java.io.IOException;
/**
* SaTokenContext 上下文初始化过滤器 (基于 Jakarta-Servlet)
*
* @author click33
* @since 1.42.0
*/
@Order(SaTokenConsts.SA_TOKEN_CONTEXT_FILTER_ORDER)
public class SaTokenContextFilterForJakartaServlet implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
SaTokenContextJakartaServletUtil.setContext((HttpServletRequest) request, (HttpServletResponse) response);
chain.doFilter(request, response);
} finally {
SaTokenContextJakartaServletUtil.clearContext();
}
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.filter;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaTokenContextModelBox;
import cn.dev33.satoken.exception.BackResultException;
import cn.dev33.satoken.exception.StopMatchException;
import cn.dev33.satoken.servlet.util.SaJakartaServletOperateUtil;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaTokenConsts;
import jakarta.servlet.*;
import org.springframework.core.annotation.Order;
import java.io.IOException;
/**
* CORS 跨域策略过滤器 (基于 Jakarta-Servlet)
*
* @author click33
* @since 1.42.0
*/
@Order(SaTokenConsts.CORS_FILTER_ORDER)
public class SaTokenCorsFilterForJakartaServlet implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
SaTokenContextModelBox box = SaHolder.getContext().getModelBox();
SaStrategy.instance.corsHandle.execute(box.getRequest(), box.getResponse(), box.getStorage());
}
catch (StopMatchException ignored) {}
catch (BackResultException e) {
SaJakartaServletOperateUtil.writeResult(response, e.getMessage());
return;
}
chain.doFilter(request, response);
}
}

View File

@@ -0,0 +1,122 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.interceptor;
import cn.dev33.satoken.exception.BackResultException;
import cn.dev33.satoken.exception.StopMatchException;
import cn.dev33.satoken.fun.SaParamFunction;
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import java.lang.reflect.Method;
/**
* Sa-Token 综合拦截器,提供注解鉴权和路由拦截鉴权能力
*
* @author click33
* @since 1.34.0
*/
public class SaInterceptor implements HandlerInterceptor {
/**
* 是否打开注解鉴权
*/
public boolean isAnnotation = true;
/**
* 认证函数:每次请求执行
* <p> 参数:路由处理函数指针
*/
public SaParamFunction<Object> auth = handler -> {};
/**
* 创建一个 Sa-Token 综合拦截器,默认带有注解鉴权能力
*/
public SaInterceptor() {
}
/**
* 创建一个 Sa-Token 综合拦截器,默认带有注解鉴权能力
* @param auth 认证函数,每次请求执行
*/
public SaInterceptor(SaParamFunction<Object> auth) {
this.auth = auth;
}
/**
* 设置是否打开注解鉴权
* @param isAnnotation /
* @return 对象自身
*/
public SaInterceptor isAnnotation(boolean isAnnotation) {
this.isAnnotation = isAnnotation;
return this;
}
/**
* 写入[认证函数]: 每次请求执行
* @param auth /
* @return 对象自身
*/
public SaInterceptor setAuth(SaParamFunction<Object> auth) {
this.auth = auth;
return this;
}
// ----------------- 验证方法 -----------------
/**
* 每次请求之前触发的方法
*/
@Override
@SuppressWarnings("all")
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
try {
// 这里必须确保 handler 是 HandlerMethod 类型时,才能进行注解鉴权
if(isAnnotation && handler instanceof HandlerMethod) {
Method method = ((HandlerMethod) handler).getMethod();
SaAnnotationStrategy.instance.checkMethodAnnotation.accept(method);
}
// Auth 校验
auth.run(handler);
} catch (StopMatchException e) {
// StopMatchException 异常代表停止匹配进入Controller
} catch (BackResultException e) {
// BackResultException 异常代表:停止匹配,向前端输出结果
// 请注意此处默认 Content-Type 为 text/plain如果需要返回 JSON 信息,需要在 back 前自行设置 Content-Type 为 application/json
// 例如SaHolder.getResponse().setHeader("Content-Type", "application/json;charset=UTF-8");
if(response.getContentType() == null) {
response.setContentType("text/plain; charset=utf-8");
}
response.getWriter().print(e.getMessage());
return false;
}
// 通过验证
return true;
}
}

View File

@@ -0,0 +1,19 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Sa-Token 集成 SpringBoot4 的各个组件
*/
package cn.dev33.satoken;

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.spring;
import cn.dev33.satoken.context.SaTokenContextForReadOnly;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.context.model.SaStorage;
import cn.dev33.satoken.servlet.model.SaRequestForServlet;
import cn.dev33.satoken.servlet.model.SaResponseForServlet;
import cn.dev33.satoken.servlet.model.SaStorageForServlet;
/**
* <h2> 此为低版本(<1.42.0) 的上下文处理方案,基于 Spring 内部工具类 RequestContextHolder 读写上下文,仅做留档,如无必要请勿使用 </h2>
*
* Sa-Token 上下文处理器 [ SpringBoot4 Jakarta Servlet 版 ],在 SpringBoot4 中使用 Sa-Token 时,必须注入此实现类,否则会出现上下文无效异常
*
* @author click33
* @since 1.34.0
*/
public class SaTokenContextForSpringInJakartaServlet implements SaTokenContextForReadOnly {
/**
* 获取当前请求的 Request 包装对象
*/
@Override
public SaRequest getRequest() {
return new SaRequestForServlet(SpringMVCUtil.getRequest());
}
/**
* 获取当前请求的 Response 包装对象
*/
@Override
public SaResponse getResponse() {
return new SaResponseForServlet(SpringMVCUtil.getResponse());
}
/**
* 获取当前请求的 Storage 包装对象
*/
@Override
public SaStorage getStorage() {
return new SaStorageForServlet(SpringMVCUtil.getRequest());
}
/**
* 判断:在本次请求中,此上下文是否可用。
*/
@Override
public boolean isValid() {
return SpringMVCUtil.isWeb();
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.spring;
import cn.dev33.satoken.filter.SaFirewallCheckFilterForJakartaServlet;
import cn.dev33.satoken.filter.SaTokenContextFilterForJakartaServlet;
import cn.dev33.satoken.filter.SaTokenCorsFilterForJakartaServlet;
import cn.dev33.satoken.spring.pathmatch.SaPathPatternParserUtil;
import cn.dev33.satoken.strategy.SaStrategy;
import org.springframework.context.annotation.Bean;
/**
* 注册 Sa-Token 框架所需要的 Bean
*
* @author click33
* @since 1.34.0
*/
public class SaTokenContextRegister {
public SaTokenContextRegister() {
// 重写路由匹配算法
SaStrategy.instance.routeMatcher = (pattern, path) -> {
return SaPathPatternParserUtil.match(pattern, path);
};
}
/**
* 上下文过滤器
*
* @return /
*/
@Bean
public SaTokenContextFilterForJakartaServlet saTokenContextFilterForServlet() {
return new SaTokenContextFilterForJakartaServlet();
}
/**
* CORS 跨域策略过滤器
*
* @return /
*/
@Bean
public SaTokenCorsFilterForJakartaServlet saTokenCorsFilterForJakartaServlet() {
return new SaTokenCorsFilterForJakartaServlet();
}
/**
* 防火墙过滤器
*
* @return /
*/
@Bean
public SaFirewallCheckFilterForJakartaServlet saFirewallCheckFilterForJakartaServlet() {
return new SaFirewallCheckFilterForJakartaServlet();
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2020-2099 sa-token.cc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package cn.dev33.satoken.spring;
import cn.dev33.satoken.exception.NotWebContextException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* SpringMVC 相关操作工具类,快速获取当前会话的 HttpServletRequest、HttpServletResponse 对象
*
* @author click33
* @since 1.34.0
*/
public class SpringMVCUtil {
private SpringMVCUtil() {
}
/**
* 获取当前会话的 request
* @return request
*/
public static HttpServletRequest getRequest() {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if(servletRequestAttributes == null) {
throw new NotWebContextException("非 web 上下文无法获取 HttpServletRequest");
}
return servletRequestAttributes.getRequest();
}
/**
* 获取当前会话的 response
* @return response
*/
public static HttpServletResponse getResponse() {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if(servletRequestAttributes == null) {
throw new NotWebContextException("非 web 上下文无法获取 HttpServletRequest");
}
return servletRequestAttributes.getResponse();
}
/**
* 判断当前是否处于 Web 上下文中
* @return request
*/
public static boolean isWeb() {
return RequestContextHolder.getRequestAttributes() != null;
}
}