我想从请求和响应中获得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
将内容转换成字符串变量的正确方法是什么?
@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
}
}
这里有一堆类来完成它。这是一个OncePerRequestFilter实现,请查看https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/filter/OncePerRequestFilter.html。基本上问题在于,在链式过滤器中,请求流和响应流只能读取一次。因此,需要将这两个流包装在可以多次读取的内容中。
在前两行中,我将request和response封装在requestToUse和responseTouse中。ResettableStreamHttpServletRequest和ResettableStreamHttpServletResponse是将原始字符串主体保存在其中的包装类,每次需要流时,它们都会返回一个新的流。
我从我做的一个老项目里拿来的。实际上有更多的包层,但我为你提取了主要部分。这可能不能立即编译。试试看,让我知道,我会帮助你使它发挥作用。
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的Filter,该请求是一个POST,其中包含我需要读入我的filter方法的xml。从HttpServletRequest对象获取发布的xml的最佳方法是什么。 问题答案: 这取决于客户端的发送方式。 如果已将其作为原始请求正文发送,则使用: 如果已将其作为常规请求参数发送,请使用: 如果已将其作为具有部分风味的上载文件发送,请使用。
问题内容: 是否可以从ServletContext获取HttpServletRequest? 问题答案: 是否可以从ServletContext获取HttpServletRequest? 没有。 该代表的应用程序。该应用程序可以涵盖许多会话和请求。但是您无法通过来获取“当前正在运行”的请求或会话。有关servlet和作用域如何工作的详细信息,可以在以下相关答案中找到:servlet如何工作?实例化
我想从Java Servlet的POST请求中读出数据。这个servlet在Geoserver上作为服务运行,用URL调用。 发布请求(使用python脚本创建): Java servlet: 输出: 问题: 为什么我不能读出xml数据体?请求有问题,数据没有传递给Java吗? 编辑1: 使用Inputstream尝试其他方法,但正文始终是空行。可能是服务器在创建请求对象时忽略了Body并仅使用头
我正在使用一个应用程序,它的前端使用html、Javascript和jQuery,后端和数据库使用Java和Oracle。 目前,它将数据从前端传回java,并在后端附加一个URL参数,如http://localhost/28182391238912398172 然后,它使用一个ajaxget请求,使用URL中的id调用servlet,以运行一个准备好的语句,使用Java查询数据库。 我需要做的是
问题内容: 我有一个XML文档,其中包含具有格式正确的HTML内容的标签。我需要使用JavaScript将HTML导入页面。但是,由于CMS问题,HTML不能使用<![CDATA []]>或其他任何符号进行转义,并且<>必须存在,而不是编码为&lt;。&gt; 我使用jQuery来获取XML,并将子菜单放入数组中。我可以通过以下方式获取文字: 但是,这仅返回“ Hello World Lorem
主要内容:1. ServletActionContext,2. ServletRequestAware,参考在Struts2中,可以使用以下两种方法来获取HttpServletRequest对象。 1. ServletActionContext 直接从 org.apache.struts2.ServletActionContext 获取 HttpServletRequest 对象。 2. ServletRequestAware 让你的类实现org.apache.struts2.intercept