从HttpServletRequest获取XML并将其用于端点

编程入门 行业动态 更新时间:2024-10-24 06:33:19
本文介绍了从HttpServletRequest获取XML并将其用于端点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

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

I would like to get the XML data from request and response and use it into Rest controller. I tried this:

@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变量的正确方法是什么?

What is the proper way to get the content into String variable?

编辑:我也尝试了使用Filter的解决方案,但我不知道如何将请求有效负载用于rest控制器:

EDIT: I also tried solution with Filter but I'm not aware how to use the request payload into rest controller:

读取请求有效载荷:

@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 } }

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

How I can call HttpLoggingFilter into the Java method handleMessage and get the request as body String? Probably I can make it service and Inject it? Can you give me some advice how I can assess the code?

推荐答案

这里有很多类可以做到这一点.这是一次OncePerRequestFilter的实现,请在此处检查 docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/OncePerRequestFilter.html .基本上,问题在于在链式过滤器中,请求流和响应流只能被读取一次.因此,需要将这两个流包装在可以多次读取的内容中.

Here are a bunch of classes to do it. This is a once a OncePerRequestFilter implementation, check here docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/OncePerRequestFilter.html. Basically the problem is that in the chain filter, the request stream and response stream can be read just once. So, need to wrap these 2 streams inside something that can be read more than once.

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

In the first 2 lines I wrapped request and response inside requestToUse and responseToUse. ResettableStreamHttpServletRequest and ResettableStreamHttpServletResponse are wrapper classes that keeps the original string body inside of them, and every time the stream is needed they return a new stream.Then from there, you forget about request and response and start using requestToUse and responseToUse.

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

I took this from an old project I did. Actually there are more clases, but I extracted the main parts for you. This may not compile right away. Give it a try and let me know and I will help you to make it work.

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并将其用于端点

本文发布于:2023-10-11 23:26:04,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1483135.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:并将其   HttpServletRequest   XML

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!