gpt4 book ai didi

java - Spring Controller : Adding a response header parameter called Elapsed-Time

转载 作者:行者123 更新时间:2023-11-29 08:33:12 25 4
gpt4 key购买 nike

我想在每个 API REST 请求上添加一个 Elapsed-Time 响应 header 参数,即使是那些以错误结束的请求。

例如:

===>
GET /api/customer/123 HTTP/1.1
Accept: application/vnd.company.app.customer-v1+json

<===
HTTP/1.1 200 OK
Content-Type: application/vnd.company.app.customer-v1+json
Elapsed-Time: 12

{ id: 123, name: Jordi, age: 28 }

作为 Elapsed-Time 参数计算为 @RequestMapping 方法完成的瞬间与 @RequestMapping 方法开始的瞬间之间的毫秒差。

我一直在看 Spring4 HandlerInterceptorAdapter。 preHandle 和 postHandle 方法似乎非常适合这种情况(尽管执行链中每个拦截器的时间开销)。但是,不幸的是,在 postHandle 方法中更改响应 header 没有任何效果,因为响应已经构建。

Spring documentation状态:

Note that the postHandle method of HandlerInterceptor is not always ideally suited for use with @ResponseBody and ResponseEntity methods. In such cases an HttpMessageConverter writes to and commits the response before postHandle is called which makes it impossible to change the response, for example to add a header. Instead an application can implement ResponseBodyAdvice and either declare it as an @ControllerAdvice bean or configure it directly on RequestMappingHandlerAdapter.

您知道处理这种情况的任何可行的优雅解决方案吗?

我不认为这个案例是重复的Spring - Modifying headers for every request after processing (in postHandle)因为我需要捕获一个值为开始时间的变量(当申请到达应用程序时和@RequestMapping 方法开始之前),然后在@RequestMapping 方法完成后使用此变量来计算耗时。

最佳答案

您需要保留Handle Interceptor,但不要实现postHandle 方法,只实现preHandle 以便将startTime 保存为请求中的参数

public class ExecuterTimeInterceptor extends HandlerInterceptorAdapter {

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
long startTime = System.currentTimeMillis();
request.setAttribute("startTime", startTime);
return true;
}
}

当 Controller 完成并返回响应时,Controller Advice(实现 ResponseBodyAdvice 的类)将获取 Server Request 的 http servlet 请求部分,恢复 startTime 并获取耗时,如下所示:

@ControllerAdvice
public class GeneralControllerAdvice implements ResponseBodyAdvice<Object> {

@Override
public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
return true;
}

@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
ServletServerHttpRequest servletServerRequest = (ServletServerHttpRequest) request;
long startTime = (long) servletServerRequest.getServletRequest().getAttribute("startTime");
long timeElapsed = System.currentTimeMillis() - startTime;
response.getHeaders().add("Elapsed-Time", String.valueOf(timeElapsed));
return body;
}
}

最后,您将拦截器添加到主应用程序(/** 每个资源所需的路径)

@SpringBootApplication
@ComponentScan(basePackages = "com.your.package")
@Configuration
public class Application extends WebMvcConfigurerAdapter {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new ExecuterTimeInterceptor()).addPathPatterns("/**");
}

}

关于java - Spring Controller : Adding a response header parameter called Elapsed-Time,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46227751/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com