英文:
What is the recommended way to pass state information to an HTTP interceptor?
问题
我正尝试对我的应用程序执行所有HTTP出站请求的日志记录。然而,我需要使HTTP拦截器能够访问HTTP调用的一些元数据。这些数据是针对应用逻辑中每种单独类型的HTTP调用手动设置的。目前,我已经找到了两种将这些数据传递给拦截器的方法:
- 在临时HTTP标头中包含此元数据,在拦截调用时记录它,然后删除标头,进行调用。
- 将数据存储在静态的ThreadLocal变量中,在拦截器中检索它,并清除ThreadLocal存储。
虽然这两种方法都能很好地工作,但我对这两种方法都有一些保留意见。对于第一种方法,直接修改HTTP请求本身似乎是不明智的,因为如果拦截器不起作用/未被使用,元数据将传递给远程服务器。对于第二种方法,使用ThreadLocal会涉及到堆内存管理问题,因为太多线程可能会消耗堆空间。
是否有任何其他标准/推荐的方法来解决这个问题?如果没有,上述提到的方法中哪种更适合解决这个问题?
英文:
I am trying to perform logging of all HTTP outbound requests from my application. However, I need the HTTP interceptor to have access to some meta-data of the HTTP calls. This data is set manually for each separate type of HTTP call in the app logic itself. Now, there are two apporaches I have found so far to pass this data on to the interceptor:
- Include this metadata in a temporary HTTP header, log it when the call is intercepted, remove the header, make the call
- Store the data in a static ThreadLocal variable, retrieve it in the interceptor and clear the ThreadLocal storage
Although both these methods work fine, there are some reservations I have regarding both methods. For the first method, it seems unwise to alter the HTTP request itself as, in case, the interceptor is not working/not being used, the metadata will be passed on to the remote server. For the second method, the use of ThreadLocal comes associated with problems of heap memory management as too many threads might eat up heap space.
Is there any other standard/recommended method to approach this problem? If not, which of the above mentioned methods would be better suited at addressing this problem statement?
答案1
得分: 1
在Spring中的另一种方法是使用作用域设置为“Request”的Bean。尽管单例作用域的Bean不是线程安全的,但使用请求作用域,Bean仅在单个HTTP请求的上下文中建立。这样的Bean在HTTP请求开始时被实例化,并且其状态在整个HTTP请求的持续时间内保持不变。其语法如下:
@Bean
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public HelloMessageGenerator requestScopedBean() {
return new HelloMessageGenerator();
}
或者,同样代码的较短版本:
@Bean
@RequestScope
public ScopedBeanClass requestScopedBean() {
return new ScopedBeanClass();
}
现在可以使用ScopedBeanClass
以线程安全的方式在单个HTTP请求的整个生命周期内设置和读取值,之后该Bean会在下一个请求中被清除/重置(可能来自并发线程)。
请求作用域是可用的4种与Web相关的作用域之一。其他作用域包括:会话作用域、应用程序作用域和WebSocket作用域。有关这些作用域的更多信息,请参见这里。
英文:
An alternative method in Spring is to have a Bean with bean-scope set as "Request". Singleton scope beans are not thread-safe, however, with a Request scope, a Bean is established only within the context of a single HTTP-Request and as such. Such a Bean is instanitated at the start of an HTTP request and its state persists the entire duration of just that HTTP request. The syntax for this is:
@Bean
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public HelloMessageGenerator requestScopedBean() {
return new HelloMessageGenerator();
}
or, alternatively, a shorter version of the same code:
@Bean
@RequestScope
public ScopedBeanClass requestScopedBean() {
return new ScopedBeanClass();
}
The ScopedBeanClass
may now be used to set and read values in a thread safe manner at any point during the lifetime of a single HTTP Request after which the Bean is cleared/reset in the next request (possibly from a concurrent Thread)
Request scope is one of 4 web-aware scopes that can be used. The other scopes are: Session Scope, Application Scope and WebSocket Scope
More info on these scopes is present here
答案2
得分: 0
请尝试使用Spring Cloud Zuul。在其Zuul过滤器中,您可以记录每个请求,然后重新分派请求到目标。Spring Cloud Gateway具有相同的效果。
英文:
Please try spring cloud zuul. In its zuulFilter, you can log every request, then re-dispatch request to target. The spring cloud gateway has same effect.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论