我希望使用过滤器替换现有的json
响应(在某些情况下)。我想要做的是从过滤器中读取现有的响应(JSON
)。使用新值修改它并回写到响应。但结果显示了这两种反应。
也就是说,我从回复中读到了什么以及我刚刚添加了什么。但我需要用新的替换旧的响应。代码在下面添加。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
{
try{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
final PrintStream ps = new PrintStream(baos);
chain.doFilter(request,new HttpServletResponseWrapper((HttpServletResponse)response) {
@Override
public ServletOutputStream getOutputStream() throws IOException {
return new DelegatingServletOutputStream(new TeeOutputStream(super.getOutputStream(), ps)
);
}
@Override
public PrintWriter getWriter() throws IOException {
return new PrintWriter(new DelegatingServletOutputStream (new TeeOutputStream(super.getOutputStream(), ps))
);
}
});
/* get existing response as string*/
String respopn=baos.toString();
JSONObject json=new JSONObject(respopn);
JSONObject dMap=new JSONObject(json.get("dataMap"));
dMap.put("new", "newValue");
json.put("dataMap", dMap); // Modified the old datamap with new json
JsonMapper jsonMap=new JsonMapper();
jsonMap.setJson(json);
String str=jsonMap.getJson();
byte[] responseToSend = restResponseBytes(jsonMap);
response.getOutputStream().write(responseToSend); // write to response only the new one
}
catch(Exception e)
{
e.printStackTrace();
}
}
private byte[] restResponseBytes(Object response) throws IOException {
String serialized = new ObjectMapper().writeValueAsString(response);
return serialized.getBytes();
}
答案 0 :(得分:2)
我觉得下面的代码片段应该可以工作。上面的问题是它被附加到现有数据而不是重写。我们需要创建一个包含数据存储位置的副本,并在操作到原始ServletResponse后进行复制。希望下面的代码片段可以解决您的问题。
下面是主要的过滤方法 -
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ServletResponseWrapperCopier capturingResponseWrapper = new ServletResponseWrapperCopier(
(HttpServletResponse) response);
chain.doFilter(request, capturingResponseWrapper);
try{
String respopn = capturingResponseWrapper.getCaptureAsString();
JSONObject json=new JSONObject(respopn);
JSONObject dMap=new JSONObject(json.get("dataMap"));
dMap.put("new", "newValue");
json.put("dataMap", dMap); // Modified the old datamap with new json
JsonMapper jsonMap=new JsonMapper();
jsonMap.setJson(json);
String str=jsonMap.getJson();
response.getOutputStream().write(str.getBytes());
} catch(Exception e){
log.error("");
}
}
下面的类用于复制上面代码片段中的ServletResponse
public class ServletResponseWrapperCopier extends HttpServletResponseWrapper{
private final ByteArrayOutputStream capture;
private ServletOutputStream output;
private PrintWriter writer;
public ServletResponseWrapperCopier(HttpServletResponse response) {
super(response);
capture = new ByteArrayOutputStream(response.getBufferSize());
}
@Override
public ServletOutputStream getOutputStream() {
if (writer != null) {
throw new IllegalStateException(
"getWriter() has already been called on this response.");
}
if (output == null) {
output = new ServletOutputStream() {
@Override
public void write(int b) throws IOException {
capture.write(b);
}
@Override
public void flush() throws IOException {
capture.flush();
}
@Override
public void close() throws IOException {
capture.close();
}
};
}
return output;
}
@Override
public PrintWriter getWriter() throws IOException {
if (output != null) {
throw new IllegalStateException(
"getOutputStream() has already been called on this response.");
}
if (writer == null) {
writer = new PrintWriter(new OutputStreamWriter(capture,
getCharacterEncoding()));
}
return writer;
}
public byte[] getCaptureAsBytes() throws IOException {
if (writer != null) {
writer.close();
} else if (output != null) {
output.close();
}
return capture.toByteArray();
}
public String getCaptureAsString() throws IOException {
return new String(getCaptureAsBytes(), getCharacterEncoding());
}
}
答案 1 :(得分:0)
也许这也可以考虑。 因此,首先创建一个响应包装。 (如果需要,请添加内容类型,否则您可以原样保留。我的内容类型为xhml,这促使我更改了内容类型)
接下来,为printwriter和ServletOutputStream创建包装器。 Servlet OutputStream的包装器是可选的,但这取决于您的需要。这里是实现
ByteArrayServletStream.java
public class ByteArrayServletStream extends ServletOutputStream {
ByteArrayOutputStream baos;
ByteArrayServletStream(ByteArrayOutputStream baos) {
this.baos = baos;
}
@Override
public void write(int param) throws IOException {
baos.write(param);
}
@Override
public boolean isReady() {
// TODO Auto-generated method stub
return false;
}
@Override
public void setWriteListener(WriteListener listener) {
// TODO Auto-generated method stub
}
}
ByteArrayPrinter.java
/**
* IMplemented own Printer as the new wrapper
*
*/
public class ByteArrayPrinter {
private ByteArrayOutputStream baos = new ByteArrayOutputStream();
private PrintWriter pw = new PrintWriter(baos);
private ServletOutputStream sos = new ByteArrayServletStream(baos);
public PrintWriter getWriter() {
return pw;
}
public ServletOutputStream getStream() {
return sos;
}
byte[] toByteArray() {
return baos.toByteArray();
}
}
SwaggerFilter.java
public class SwaggerFilter implements Filter {
final String APPLICATION_XHTML = "application/xhtml";
final String XML_ELEMENT_START = "<Json>";
final String XML_ELEMENT_END = "</Json>";
@Override
public void init(FilterConfig config) throws ServletException {
}
/**
* Filter to remove the extra JSON element and render it
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
ByteArrayPrinter pw = new ByteArrayPrinter();
// Create a wrapper
HttpServletResponse wrappedResp = new HttpServletResponseWrapper(response) {
@Override
public void setContentType(final String type) {
super.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
}
@Override
public PrintWriter getWriter() {
return pw.getWriter();
}
// set the outputstream content type to JSON
@Override
public ServletOutputStream getOutputStream() throws IOException {
ServletResponse response = this.getResponse();
String ct = (response != null) ? response.getContentType() : null;
if (ct != null && ct.contains(APPLICATION_XHTML)) {
response.setContentType(ct + AppConstants.CONSTANT_COMMA + MediaType.APPLICATION_JSON_UTF8_VALUE);
}
return pw.getStream();
}
};
chain.doFilter(httpRequest, wrappedResp);
byte[] bytes = pw.toByteArray();
String respBody = new String(bytes);
if (respBody.startsWith(XML_ELEMENT_START)) {
// Instead of using substring made use of stream to identify any occurence of <Json> xml element
List<String> xmlStringList = Stream.of(respBody).filter((s1) -> s1.contains(XML_ELEMENT_START))
// filter the string. Split it by mapping to new arraylist by space
.map((stringBeforeSplit) -> Arrays.asList(stringBeforeSplit.split(AppConstants.CONSTANT_SPACE)))
// create a new stream of array list strings
.flatMap((stringArrayAfterSplit) -> {
StringBuffer concatenateStringStream = new StringBuffer();
stringArrayAfterSplit.forEach(item -> {
concatenateStringStream.append(item);
});
// remove the <JSON> xml element and return the values
return Stream
.of(concatenateStringStream.toString().trim()
.replace(XML_ELEMENT_START, AppConstants.CONSTANT_NO_SPACE)
.replace(XML_ELEMENT_END, AppConstants.CONSTANT_NO_SPACE));
// collect it as a new list of strings with the xmlelement - <JSON> removed
}).collect(Collectors.toList());
// Join the list to make it one
String finalString = String.join(AppConstants.CONSTANT_NO_SPACE, xmlStringList);
// write to the outputstream with JSON mediatype
response.getOutputStream().write(finalString.getBytes());
} else {
response.getOutputStream().write(bytes);
}
}
@Override
public void destroy() {
}
}