问题描述
在之前的版本中一般为了能在任意地方都能获取到HttpServletRequest我们一般都会自己封装工具类从RequestContextHolder中获取到
public static HttpServletRequest getRequest() {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
assert servletRequestAttributes != null;
return servletRequestAttributes.getRequest();
}
但是在新版的SpringBoot3.3.0版本中这种方式获取到的ServletRequestAttributes是null。
解决方案
新增过滤器,在过滤器中设置,例如我项目中集成了SpringSecurity
package com.creatar.security.filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
/**
* 设置RequestAttributes
*
* @author: 张定辉
* @date: 2024/6/13 下午8:30
* @description: 设置RequestAttributes
*/
public class RequestAttributesFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
filterChain.doFilter(request,response);
}
}
最后将过滤器设置到SpringSecurity的过滤器链中,该过滤器最好是放在过滤器链的第一位
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorize -> authorize.requestMatchers("/modeler/**").anonymous().anyRequest().authenticated())
.logout(logout -> logout.logoutSuccessHandler(myLogoutSuccessHandler))
.exceptionHandling(ex -> ex.accessDeniedHandler(myAccessDeniedHandler).authenticationEntryPoint(myAuthenticationEntryPointHandler))
.sessionManagement(session -> session.maximumSessions(1).expiredSessionStrategy(mySessionInformationHandler))
.csrf(AbstractHttpConfigurer::disable)
.addFilterAt(userLoginFilter(), UsernamePasswordAuthenticationFilter.class)
//将设置Request的过滤器放在第一位
.addFilterBefore(new RequestAttributesFilter(),UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(tokenAuthFilter, UsernamePasswordAuthenticationFilter.class)
;
return http.build();
}