因此,我们有一个请求拦截器(伪装),它检查autowired
HttpServletRequest
是否有标头,然后将其传播/复制到传出请求中。我们的拦截器的工作是将标头从微服务传播到微服务,以便即使图中的最后一个微服务也具有有关谁发起请求的信息(例如租户)。
有时我们由于HTTP请求线程而称其为伪装,有时我们在启动时或从预定线程中调用它。
对于调度线程,我们希望能够在不进行尝试/捕获的情况下检测是否存在请求。在这种情况下,我们是发起方,我们不需要复制任何内容。
我原以为以下内容可以工作,但是我们得到了一个引发异常的代理对象:
以下检查失败,因为this.request不为null:
this.request!=null && this.request.getHeader("X-Application")
出现以下错误:
No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
我了解错误。我想避免采取明显的解决方法,例如:
//TODO: Review this
boolean requestExists = true;
try{
request.getHeader(APPLICATION_HEADER);
}catch (IllegalStateException e ){
requestExists = false;
}
public class ServiceNameFeignInterceptor implements RequestInterceptor {
private static final Logger log = LoggerFactory.getLogger(ServiceNameFeignInterceptor.class);
final TenantIdResolver tenantResolver;
final ApplicationNameResolver appResolver;
private final String APPLICATION_HEADER = "X-Application";
private final String TENANT_ID = "X-Tenant-Id";
...
@Autowired
HttpServletRequest request;
public void apply(RequestTemplate requestTemplate) {
...
if (this.request!=null && this.request.getHeader("X-Application") != null) {
log.info("Application header found in the request !!!");
requestTemplate.header("X-Application", new String[]{this.request.getHeader("X-Application")});
requestTemplate.header("X-Tenant-Id", new String[]{this.request.getHeader("X-Tenant-Id")});
} else {
log.info("Setting {} as {} for URL {} ", new Object[]{"X-Application", appName, requestTemplate.url()});
requestTemplate.header("X-Application", new String[]{appName});
requestTemplate.header("X-Tenant-Id", new String[]{appName});
}
}
请注意以下几点,如果可能,请提出更好的选择。
我目前有三个选择:
使用try / catch解决方案(最不推荐)
检查线程局部变量是否存在请求
传递我们自己的附加线程局部变量,该变量将是一个标志(我们不在请求上下文中)。
问题
我不喜欢1,因为捕获异常的代价很高,并且因为它们可能掩盖任何实际的错误。
我不喜欢2,因为如果spring的实现改变了,那么实现的细节可能会改变(例如键),而我们在启动器中的实现会中断。但是无论如何,无论何时升级Spring Boot,都需要修复各种次要或主要问题。
我喜欢选项3,因为在致电我们的假客户之前设置标志是一种有意识的行动。因此,不会有错误被忽视的风险。
其中一位团队成员建议我们使用:new NamedThreadLocal("Request attributes");
他们建议这样做的原因是:
所以我们将使用类似:
ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal("Request attributes"); RequestAttributes attributes = (RequestAttributes)requestAttributesHolder.get(); boolean requestExists = attributes != null;
但是这完全取决于spring的内部原理,它们继续使用“请求属性”。
问题,所以我们有一个请求拦截器(伪装),它检查自动连接的HttpServletRequest中的标头,然后将其传播/复制到传出的请求中。我们的拦截器的工作是...
我有类似的问题,我使用RequestContextHolder
检查请求是否绑定到线程。根据doc,如果没有任何RequestAttributes绑定到线程,则getRequestAttributes
返回null。