Spring Cloud Gateway中ServerHttpRequest与HttpServletRequest能否互相转换
问题结论
ServerHttpRequest和HttpServletRequest无法直接互相转换。
两者属于完全不同技术栈的请求抽象:
- Spring Cloud Gateway基于响应式WebFlux技术栈,
org.springframework.http.server.ServerHttpRequest是响应式环境下的请求对象,不依赖Servlet API javax.servlet.http.HttpServletRequest是传统Servlet技术栈的标准请求接口,两者底层实现没有任何继承或关联,不存在直接转换的可行性
最优解决方案(不需要写两套业务逻辑)
你现有逻辑的核心是校验登录状态,本质只依赖请求头中的业务字段,不需要绑定特定请求对象,直接抽离公共逻辑+增加适配层即可,改动量极小:
- 首先抽离核心通用逻辑,不绑定任何请求类型
// 核心公共逻辑,仅依赖业务参数 public static void handleLoginCheck(AutoHeaderInfoRequest autoHeaderInfoRequest) { if (autoHeaderInfoRequest.getAccessToken() == null) { throw ServiceException.NOT_LOGGED_IN_EXCEPTION; } if (!AuthUtil.verifyAccessToken(autoHeaderInfoRequest.getAccessToken())) { throw GlobalException.ACCESS_TOKEN_INVALID_EXCEPTION; } setRequestGlobalHeader(autoHeaderInfoRequest); }
- 保留原有Servlet场景的重载方法,原有业务方完全无感知不需要修改
// 兼容原有Servlet调用场景的适配方法 public static void handleLoginCheck(HttpServletRequest httpServletRequest) { AutoHeaderInfoRequest autoHeaderInfoRequest = AuthUtil.getAutoHeaderInfoRequest(httpServletRequest); handleLoginCheck(autoHeaderInfoRequest); }
- 新增Spring Cloud Gateway场景的适配方法,直接在Gateway过滤器中调用即可
// 适配Gateway响应式场景的适配方法 public static void handleLoginCheck(ServerHttpRequest serverHttpRequest) { AutoHeaderInfoRequest autoHeaderInfoRequest = new AutoHeaderInfoRequest(); // 从ServerHttpRequest的header中取出对应字段赋值 autoHeaderInfoRequest.setAccessToken(serverHttpRequest.getHeaders().getFirst("Access-Token")); // 其他需要填充的header字段按同样方式取值即可 handleLoginCheck(autoHeaderInfoRequest); }
替代方案(不改公共库代码的临时方案)
如果无法修改公共库代码,可以在Gateway侧手动构造MockHttpServletRequest对象,把ServerHttpRequest的header等参数填充进去后传入原有方法,需要引入spring-test依赖的MockHttpServletRequest类,可直接在生产环境使用,但不如上述方案优雅。
内容的提问来源于stack exchange,提问作者Dolphin
相关产品推荐
相关产品推荐

