Spring MVC - Get HttpServletResponse body



由于 2 天后我仍然无法弄清楚如何在HandlerInterceptorAdapter中打印HttpServletResponse体,我会再问一次:)

有了HttpServletRequest我可以轻松地做一些像request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));这样的事情,我有全身,但如何用HttpServletResponse做同样的事情?

我在StackOverflow上发现了很多关于这个问题的问题,但似乎都没有奏效。

这是处理程序:

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
//how to print here the "response" by using the "response" parameter
super.afterCompletion(request, response, handler, ex);
}

这个答案是完全相同的,并链接到这个,但他们使用ServletResponse而不是HttpServletResponse以及我在afterCompletion处理程序中没有的FilterChain的东西。即使是这个看起来最完整的一个也不适合(我认为(在我的情况下。

有人可以为我提供一个简单的序列化示例吗HttpServletResponse

很难深入研究它,但发现ResponseBodyAdvice可能适合我的目的。因此,在StackOverflow上寻找一些示例,发现这家伙在必须操纵Object body时遇到了完全相同的问题。

这是我的最终工作解决方案,以便实现我在这里写的内容

@ControllerAdvice
public class CSRFHandler implements ResponseBodyAdvice<Object> {
@Value("${security.csrf.enabled}")
private String csrfEnabled;
@Value("${security.csrf.headerName}")
private String csrfHeaderName;
@Value("${security.csrf.salt}")
private String salt;
@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) {
if (new Boolean(csrfEnabled).booleanValue()) {
String csrfValue = SecureUtil.buildCsrfValue(salt, StringUtil.toJson(body));
response.getHeaders().add(csrfHeaderName, csrfValue);
}
return body;
}
}

简单的答案是"你不能在处理程序拦截器中这样做"。 手册中这样说:

HandlerInterceptor 基本上类似于 Servlet Filter,但与后者相比,它只允许自定义预处理,可以选择禁止执行处理程序本身和自定义后处理。过滤器更强大,例如,它们允许交换沿链传递的请求和响应对象。请注意,过滤器是在 web.xml 中配置的,在应用程序上下文中配置了 HandlerInterceptor。

作为基本准则,与处理程序相关的细粒度预处理任务是 HandlerInterceptor 实现的候选项,尤其是分解的常见处理程序代码和授权检查。另一方面,筛选器非常适合请求内容和视图内容处理,例如多部分表单和 GZIP 压缩。这通常显示何时需要将过滤器映射到某些内容类型(例如图像(或所有请求。

因此,正如您所指出的,我建议您查看基于过滤器的解决方案。您可能对以下内容感兴趣:ContentCachingResponseWrapper 产生空响应,它似乎可以用最少的编码完成您想要的。但是,一旦您开始使用过滤器,您在问题中链接到的任何广为接受的答案都可能完成这项工作。

我最终在 Kotlin 中得到了以下内容:

@Bean
open fun logFilter(): CommonsRequestLoggingFilter {
val filter = InfoRequestLoggingFilter()
filter.setIncludeQueryString(true)
filter.setIncludePayload(true)
filter.setMaxPayloadLength(10000)
filter.isIncludeHeaders = false
return filter
}
import org.apache.commons.io.output.TeeOutputStream
import org.springframework.mock.web.DelegatingServletOutputStream
import org.springframework.web.filter.CommonsRequestLoggingFilter
import java.io.ByteArrayOutputStream
import java.io.IOException
import java.io.PrintStream
import java.io.PrintWriter
import javax.servlet.FilterChain
import javax.servlet.ServletOutputStream
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import javax.servlet.http.HttpServletResponseWrapper
class InfoRequestLoggingFilter : CommonsRequestLoggingFilter() {
override fun beforeRequest(request: HttpServletRequest, message: String) {
logger.info(message)
}
override fun afterRequest(request: HttpServletRequest, message: String) {
// logger.info(message) - NOP, since doFilterInternal is logging it instead
}
override fun doFilterInternal(request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain) {
val outputStream = ByteArrayOutputStream()
val printStream = PrintStream(outputStream)
filterChain.doFilter(request, object : HttpServletResponseWrapper(response) {
@Throws(IOException::class)
override fun getOutputStream(): ServletOutputStream {
return DelegatingServletOutputStream(TeeOutputStream(super.getOutputStream(), printStream)
)
}
@Throws(IOException::class)
override fun getWriter(): PrintWriter {
return PrintWriter(DelegatingServletOutputStream(TeeOutputStream(super.getOutputStream(), printStream))
)
}
})
logger.info(String.format("%s ;status=%s ;payload=%s", createMessage(request, "", ""), response.status, outputStream.toString()))
}
}

相关内容

  • 没有找到相关文章

最新更新