Java Spring MVC-获取HttpServletResponse主体
由于两天后我仍然无法确定如何在Java Spring MVC-获取HttpServletResponse主体,java,spring-mvc,servlets,Java,Spring Mvc,Servlets,由于两天后我仍然无法确定如何在HandlerInterceptorAdapter中打印HttpServletResponse正文,因此我将另问一次:) 使用HttpServletRequest我可以轻松地执行类似request.getReader().lines().collect(Collectors.joining(System.lineSeparator())和我有完整的正文,但是如何使用HttpServletResponse实现相同的内容呢 我在StackOverflow上发现了很多关于
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
以及FilterChain
的内容,而我的afterCompletion
处理程序中没有这些内容。即使是看起来最完整的一个也不适合(我认为)我的情况
有人能给我提供一个带有HttpServletResponse
的简单序列化示例吗?简单的答案是“在处理程序拦截器中不能这样做”。
:
HandlerInterceptor基本上类似于Servlet过滤器,但与后者不同的是,它只允许自定义预处理,并可以选择禁止执行处理程序本身,以及自定义后处理过滤器功能更强大,例如,它们允许交换传递给链的请求和响应对象。注意,过滤器是在web.xml中配置的,web.xml是应用程序上下文中的HandlerInterceptor
作为一项基本指导原则,与细粒度处理程序相关的预处理任务是HandlerInterceptor实现的候选任务,特别是考虑了常见处理程序代码和授权检查。另一方面,筛选器非常适合于请求内容和视图内容处理,如多部分表单和GZIP压缩。这通常显示何时需要将筛选器映射到某些内容类型(例如图像)或所有请求
因此,我建议您查看基于过滤器的解决方案,正如您所指出的。您可能会感兴趣:它似乎可以用最少的编码实现您想要的。但是,一旦你开始使用过滤器,你在问题中链接到的任何公认答案都可能会起到作用。深入搜索它很困难,但发现
ResponseBodyAdvice
可能适合我的目的。因此,在StackOverflow上寻找一些例子,发现guy也有同样的问题,必须操作对象体
这是我最后的工作解决方案,以实现我写的
@ControllerAdvice
公共类CSRFHandler实现ResponseBodyAdvice{
@值(${security.csrf.enabled}”)
私有字符串csrfEnabled;
@值(${security.csrf.headerName}”)
私有字符串csrfHeaderName;
@值(${security.csrf.salt}”)
私盐;
@凌驾
公共布尔支持(MethodParameter returnType,Class>converterType){
返回true;
}
@凌驾
BodyWrite之前的公共对象(对象主体、方法参数returnType、MediaType selectedContentType、,
Class>selectedConverterType,ServerHttpRequest请求,
服务器HttpResponse(响应){
if(新布尔值(csrfEnabled).booleanValue()){
String csrfValue=SecureUtil.buildCsrfValue(salt,StringUtil.toJson(body));
response.getHeaders().add(csrfHeaderName,csrfValue);
}
返回体;
}
}
在科特林,我的结局如下:
@Bean
open fun logFilter(): CommonsRequestLoggingFilter {
val filter = InfoRequestLoggingFilter()
filter.setIncludeQueryString(true)
filter.setIncludePayload(true)
filter.setMaxPayloadLength(10000)
filter.isIncludeHeaders = false
return filter
}
嗨Faraz Durrani谢谢你的回复。我正在寻找如何打印身体的反应,而不是要求。你好GPI谢谢你的有用的答案。很明显,为什么这不是一个好方法,但是尝试一下eperrequestfilter或Filter,似乎在控制器执行后没有调用dofilternental或doFilter。我应该用什么来代替呢?我猜如果你的过滤器的方法没有被调用,那可能是因为Spring没有把它们取出来并部署它们。因此,您可能应该阅读手册,了解“如何注册过滤器”。如果您使用纯SpringBoot应用程序,而不是嵌入Spring上下文的Servlet Web应用程序,那么这样做的方式就不同了。。。因此,请阅读相关文档。
@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()))
}
}