在 AEM 的 Servlet 中获取 JSP 输出
Get JSP output within Servlet in AEM
在 CQ 中,我们需要在 servlet 中处理 jsp 然后将结果与我们从服务器获得的其他结果组合起来,然后再写回浏览器。
下面的代码几乎就是我们所需要的,只是它在处理完jsp.
后将结果写回浏览器
RequestDispatcher dispatcher = request.getRequestDispatcher(resource);
dispatcher.forward(request, response);
我们尝试使用如下模拟响应:
RequestData requestData = new RequestData(slingRequestProcessor, request, mockResponse);
SlingHttpServletRequest slingRequest = requestData.getSlingRequest();
SlingHttpServletResponse slingResponse = requestData.getSlingResponse();
RequestDispatcher dispatcher = request.getRequestDispatcher(resource);
dispatcher.forward(slingRequest, slingResponse);
但我们遇到了问题。
首先 - 根据您的描述,您似乎想使用 requestDispatcher.include
而不是 requestDispatcher.forward
。
关于响应内容的包含,您传递给 requestDispatcher.include
调用的响应可以是您自己创建的对象,它将其输出写入字符串而不是将其返回给浏览器。以下内容可能是合适的:
final ServletOutputStream outputStream = new ServletOutputStream() {
public void write(int b) throws IOException {
outputBuffer.append((char) b);
}
};
SlingHttpServletResponseWrapper responseWrapper = new SlingHttpServletResponseWrapper(response) {
public ServletOutputStream getOutputStream() {
return outputStream;
}
public PrintWriter getWriter() throws IOException {
return new PrintWriter(outputBuffer);
}
public SlingHttpServletResponse getSlingResponse() {
return super.getSlingResponse();
}
};
包含后outputStream.toString()
应该提供资源请求的执行结果。
综合所有反馈,我们得出以下结论:
//Map<String, Object> jstlValues, final Map<String, Object> propertyValues, String resourceType, SlingHttpServletRequest request, SlingHttpServletResponse response
final StringWriter outputBuffer = new StringWriter();
SlingHttpServletResponseWrapper responseWrapper = new SlingHttpServletResponseWrapper(response) {
public PrintWriter getWriter() throws IOException {
return new PrintWriter(outputBuffer);
}
public SlingHttpServletResponse getSlingResponse() {
return super.getSlingResponse();
}
};
ResourceMetadata resourceMetaData = new ResourceMetadata();
resourceMetaData.setResolutionPath("/dummy");
for (Map.Entry<String, Object> entry: jstlValues.entrySet()) {
request.setAttribute(entry.getKey(), entry.getValue());
}
SyntheticResource resource = new SyntheticResource(request.getResourceResolver(), resourceMetaData, resourceType) {
public <T> T adaptTo(Class<T> type) {
if (type == ValueMap.class) {
ValueMap m = new ValueMapDecorator(propertyValues);
return (T) m;
}
return super.adaptTo(type);
}
};
RequestDispatcher dispatcher = request.getRequestDispatcher(resource);
dispatcher.include(request, responseWrapper);
return outputBuffer.toString();
在 CQ 中,我们需要在 servlet 中处理 jsp 然后将结果与我们从服务器获得的其他结果组合起来,然后再写回浏览器。
下面的代码几乎就是我们所需要的,只是它在处理完jsp.
后将结果写回浏览器RequestDispatcher dispatcher = request.getRequestDispatcher(resource);
dispatcher.forward(request, response);
我们尝试使用如下模拟响应:
RequestData requestData = new RequestData(slingRequestProcessor, request, mockResponse);
SlingHttpServletRequest slingRequest = requestData.getSlingRequest();
SlingHttpServletResponse slingResponse = requestData.getSlingResponse();
RequestDispatcher dispatcher = request.getRequestDispatcher(resource);
dispatcher.forward(slingRequest, slingResponse);
但我们遇到了问题。
首先 - 根据您的描述,您似乎想使用 requestDispatcher.include
而不是 requestDispatcher.forward
。
关于响应内容的包含,您传递给 requestDispatcher.include
调用的响应可以是您自己创建的对象,它将其输出写入字符串而不是将其返回给浏览器。以下内容可能是合适的:
final ServletOutputStream outputStream = new ServletOutputStream() {
public void write(int b) throws IOException {
outputBuffer.append((char) b);
}
};
SlingHttpServletResponseWrapper responseWrapper = new SlingHttpServletResponseWrapper(response) {
public ServletOutputStream getOutputStream() {
return outputStream;
}
public PrintWriter getWriter() throws IOException {
return new PrintWriter(outputBuffer);
}
public SlingHttpServletResponse getSlingResponse() {
return super.getSlingResponse();
}
};
包含后outputStream.toString()
应该提供资源请求的执行结果。
综合所有反馈,我们得出以下结论:
//Map<String, Object> jstlValues, final Map<String, Object> propertyValues, String resourceType, SlingHttpServletRequest request, SlingHttpServletResponse response
final StringWriter outputBuffer = new StringWriter();
SlingHttpServletResponseWrapper responseWrapper = new SlingHttpServletResponseWrapper(response) {
public PrintWriter getWriter() throws IOException {
return new PrintWriter(outputBuffer);
}
public SlingHttpServletResponse getSlingResponse() {
return super.getSlingResponse();
}
};
ResourceMetadata resourceMetaData = new ResourceMetadata();
resourceMetaData.setResolutionPath("/dummy");
for (Map.Entry<String, Object> entry: jstlValues.entrySet()) {
request.setAttribute(entry.getKey(), entry.getValue());
}
SyntheticResource resource = new SyntheticResource(request.getResourceResolver(), resourceMetaData, resourceType) {
public <T> T adaptTo(Class<T> type) {
if (type == ValueMap.class) {
ValueMap m = new ValueMapDecorator(propertyValues);
return (T) m;
}
return super.adaptTo(type);
}
};
RequestDispatcher dispatcher = request.getRequestDispatcher(resource);
dispatcher.include(request, responseWrapper);
return outputBuffer.toString();