问题描述.
萌新在线踩坑....
我需要在切面中获取当前用户的请求信息,比如请求头信息.
但是不能像mvc一样通过以下方式实现.
@Autowired
private HttpServletRequest request;
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
// 获取 request
HttpServletRequest request = requestAttributes.getRequest();
问题出现的环境背景及自己尝试过哪些方法
我尝试过自己创建一个ReactiveRequestContextHolder来获取
https://segmentfault.com/a/1190000018766412
但是返回是null.
之后
根据官方文档
https://projectreactor.io/docs/core/release/reference/#context
和reactor相关的文章
https://www.jianshu.com/p/1be25b134ced
发现reactor的context有 自底向上 的特性.所以我懵逼了.不知道该怎么实现了.
相关代码
我参考了以上的文章的代码.
以下是我的代码(我可能哪里理解错误了).
// 拦截器
// 把request对象放入Mono上下文中,key为一个class对象
@Configuration
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public class ReactiveRequestContextFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
return chain.filter(exchange)
.subscriberContext(ctx -> ctx.put(ReactiveRequestContextHolder.CONTEXT_KEY, request));
}
}
// 上下文
// 从Mono中获取上下文,key为一个class对象
public class ReactiveRequestContextHolder {
public static final Class<ServerHttpRequest> CONTEXT_KEY = ServerHttpRequest.class;
public static Mono<ServerHttpRequest> getRequest() {
return Mono.subscriberContext()
// TODO 报错了 reactor.core.Exceptions$ErrorCallbackNotImplemented: java.util.NoSuchElementException: Context is empty
.map(ctx -> ctx.get(CONTEXT_KEY));
}
}
// TODO 未完成 切面bean
// 过滤含有@test注解的控制层方法,取出名为testHeader的请求头信息并打印.
@Slf4j
@Aspect
@Component
@AllArgsConstructor
public class SecurityInnerAspect {
// test 的内容被调用后进入切面
@Around("@annotation(test)")
// 不用JoinPoint 用 ProceedingJoinPoint,因为ProceedingJoinPoint可以拦截请求
public Object around(ProceedingJoinPoint point, Inner inner) throws Throwable {
ReactiveRequestContextHolder.getRequest().subscribe(serverHttpRequest -> {
String header = Objects.requireNonNull(serverHttpRequest.getHeaders().get("testHeaderStr")).get(0);
log.info("print testHeader: {}", header);
});
return point.proceed();
}
}
期待的结果
我期待能在切面中取出用户request对象进行操作.
或能有其他解决方案.
感谢!!
实际看到的错误信息
本以为会通过spring的依赖反转拿到request对象,但是他没有和mvc一样的把当前用户的request对象注册成bean.也没有放到当前线程中.
且其他方式不太会用.
so,目前没有办法在切面bean中取出request信息
解决方案
控制层添加ServerWebExchange参数,由框架自动注入.
ServerWebExchange封装了request和response.
在控制层是能取到该request参数的.
然后切面通过JoinPoint获取该方法的参数.
就可以取到request了.如果有更好更优雅更没有侵入性的方式的欢迎留言哦.