从HttpServletRequest获取XML并用于端点

我想从请求和响应中获取XML数据,并将其用于Rest控制器。我尝试了这个:

@RestController()

public class HomeController {

@PostMapping(value = "/v1")

public Response handleMessage(@RequestBody Transaction transaction, HttpServletRequest request, HttpServletResponse response) throws Exception {

HttpServletRequest request, HttpServletResponse response

System.out.println("!!!!!!! InputStream");

System.out.println(request.getInputStream());

System.out.println(response.getOutputStream());

InputStream in = request.getInputStream();

String readLine;

BufferedReader br = new BufferedReader(new InputStreamReader(in));

while (((readLine = br.readLine()) != null)) {

System.out.println(readLine);

}

}

}

但是我明白了 java.io.IOException: UT010029: Stream is closed

将内容放入String变量的正确方法是什么?

:我也尝试使用筛选器的解决方案,但我不知道如何使用请求有效载荷到其余控制器:

读取请求有效负载:

@Component

public class HttpLoggingFilter implements Filter {

private static final Logger logger = LoggerFactory.getLogger(HttpLoggingFilter.class);

@Override

public void init(FilterConfig filterConfig) throws ServletException {

}

@Override

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

throws IOException, ServletException {

ResettableStreamHttpServletRequest wrappedRequest = new ResettableStreamHttpServletRequest((HttpServletRequest) request);

wrappedRequest.getInputStream().read();

String body = IOUtils.toString(wrappedRequest.getReader());

System.out.println("!!!!!!!!!!!!!!!!!! " + body);

wrappedRequest.resetInputStream();

chain.doFilter(request, response);

}

public class ResettableStreamHttpServletRequest extends HttpServletRequestWrapper {

private byte[] rawData;

private HttpServletRequest request;

private ResettableServletInputStream servletStream;

ResettableStreamHttpServletRequest(HttpServletRequest request) {

super(request);

this.request = request;

this.servletStream = new ResettableServletInputStream();

}

void resetInputStream() {

servletStream.stream = new ByteArrayInputStream(rawData);

}

@Override

public ServletInputStream getInputStream() throws IOException {

if (rawData == null) {

rawData = IOUtils.toByteArray(this.request.getInputStream());

servletStream.stream = new ByteArrayInputStream(rawData);

}

return servletStream;

}

@Override

public BufferedReader getReader() throws IOException {

if (rawData == null) {

rawData = IOUtils.toByteArray(this.request.getInputStream());

servletStream.stream = new ByteArrayInputStream(rawData);

}

String encoding = getCharacterEncoding();

if (encoding != null) {

return new BufferedReader(new InputStreamReader(servletStream, encoding));

} else {

return new BufferedReader(new InputStreamReader(servletStream));

}

}

private class ResettableServletInputStream extends ServletInputStream {

private InputStream stream;

@Override

public int read() throws IOException {

return stream.read();

}

@Override

public boolean isFinished() {

// TODO Auto-generated method stub

return false;

}

@Override

public boolean isReady() {

// TODO Auto-generated method stub

return false;

}

@Override

public void setReadListener(ReadListener readListener) {

// TODO Auto-generated method stub

}

}

}

}

其余端点:

@RestController()

public class HomeController {

@PostMapping(value = "/v1")

public Response handleMessage(@RequestBody Transaction transaction, HttpServletRequest request, org.zalando.logbook.HttpRequest requestv, HttpServletResponse response) throws Exception {

// Get here request and response and log it into DB

}

}

如何调用HttpLoggingFilterJava方法handleMessage并将请求作为正文String获取?也许我可以提供服务并注入它?您可以给我一些建议,以评估代码吗?

回答:

这里有很多课程。这是一次OncePerRequestFilter实现,请在此处查看https://docs.spring.io/spring-

framework/docs/current/javadoc-

api/org/springframework/web/filter/OncePerRequestFilter.html。基本上,问题是在链式过滤器中,请求流和响应流只能读取一次。因此,需要将这两个流包装在可以多次读取的内容中。

在前两行中,我将请求和响应包装在requestToUse和responseToUse内。ResettableStreamHttpServletRequest和ResettableStreamHttpServletResponse是包装器类,它们将原始字符串主体保留在其中,并且每次需要该流时,它们都将返回一个新流。然后,您就无需再请求和响应了,而是开始使用requestToUse和responseToUse。

我是从我做的一个旧项目中摘下来的。其实还有更多的分类,但是我为您提取了主要部分。这可能不会立即编译。尝试一下,让我知道,我会帮助您使其工作。

    public class RequestResponseLoggingFilter extends OncePerRequestFilter {

@Override

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

//here you wrap the request and response into some resetable istream class

HttpServletRequest requestToUse = new ResettableStreamHttpServletRequest(request);

HttpServletResponse responseToUse = new ResettableStreamHttpServletResponse(response);

//you read the request to log it

byte[] payload = IOUtils.toByteArray(requestToUse.getReader(), requestToUse.getCharacterEncoding());

String body = new String(payload, requestToUse.getCharacterEncoding());

//here you log the body request

log.(body);

//let the chain continue

filterChain.doFilter(requestToUse, responseToUse);

// Here we log the response

String response = new String(responseToUse.toString().getBytes(), responseToUse.getCharacterEncoding());

//since you can read the stream just once, you will need it again for chain to be able to continue, so you reset it

ResettableStreamHttpServletResponse responseWrapper = WebUtils.getNativeResponse(responseToUse, ResettableStreamHttpServletResponse.class);

if (responseWrapper != null) {

responseWrapper.copyBodyToResponse(true);

}

}

}

public class ResettableStreamHttpServletRequest extends HttpServletRequestWrapper {

private byte[] rawData;

private ResettableServletInputStream servletStream;

public ResettableStreamHttpServletRequest(HttpServletRequest request) throws IOException {

super(request);

rawData = IOUtils.toByteArray(request.getInputStream());

servletStream = new ResettableServletInputStream();

servletStream.setStream(new ByteArrayInputStream(rawData));

}

@Override

public ServletInputStream getInputStream() throws IOException {

servletStream.setStream(new ByteArrayInputStream(rawData));

return servletStream;

}

@Override

public BufferedReader getReader() throws IOException {

servletStream.setStream(new ByteArrayInputStream(rawData));

return new BufferedReader(new InputStreamReader(servletStream));

}

}

public class ResettableStreamHttpServletResponse extends HttpServletResponseWrapper {

private ByteArrayServletOutputStream byteArrayServletOutputStream = new ByteArrayServletOutputStream();

public ResettableStreamHttpServletResponse(HttpServletResponse response) throws IOException {

super(response);

}

/**

* Copy the cached body content to the response.

*

* @param complete whether to set a corresponding content length for the complete cached body content

* @since 4.2

*/

public void copyBodyToResponse(boolean complete) throws IOException {

byte[] array = byteArrayServletOutputStream.toByteArray();

if (array.length > 0) {

HttpServletResponse rawResponse = (HttpServletResponse) getResponse();

if (complete && !rawResponse.isCommitted()) {

rawResponse.setContentLength(array.length);

}

rawResponse.getOutputStream().write(byteArrayServletOutputStream.toByteArray());

if (complete) {

super.flushBuffer();

}

}

}

/**

* The default behavior of this method is to return getOutputStream() on the wrapped response object.

*/

@Override

public ServletOutputStream getOutputStream() throws IOException {

return byteArrayServletOutputStream;

}

/**

* The default behavior of this method is to return getOutputStream() on the wrapped response object.

*/

@Override

public String toString() {

String response = new String(byteArrayServletOutputStream.toByteArray());

return response;

}

}

以上是 从HttpServletRequest获取XML并用于端点 的全部内容, 来源链接: utcz.com/qa/424721.html

回到顶部