Looking for an example for inserting content into the response using a servlet filter
2015-09-01 05:42
639 查看
I’ve been searching the net and stackoverflow for an example of somebody inserting content into the response using a servlet filter, but can only find examples of people capturing/compressing the output and/or changing the headers. My goal is to append a chunk of HTML just before the closing
I’m working on a solution that extends the
I feel that somebody must have solved this problem already, and probably more elegantly than I will. I’d appreciate any examples of how to use a servlet filter to insert content into a response.
UPDATED
Responding to a comment, I am also trying to implement the
I am also wrapping the request, but that code works and shouldn’t affect the response.
The codebase I am using, calls the
One important note: you need to use
Servlet:
Filter:
CharResponseWrapper (exactly as the article)
web.xml
理解要修改resonse的关键是提供一个假的输出流替换response的输出流
</body>of all HTML responses.
I’m working on a solution that extends the
HttpServletResponseWrapperto use my own
PrintWriter, then overriding the
writemethods thereon. Inside the write method I’m storing the last 7 characters to see if it’s equal to the closing body tag, and then I write my HTML chunk plus the closing body tag, before continuing normal write operations for the rest of the document.
I feel that somebody must have solved this problem already, and probably more elegantly than I will. I’d appreciate any examples of how to use a servlet filter to insert content into a response.
UPDATED
Responding to a comment, I am also trying to implement the
CharResponseWrapperfrom http://www.oracle.com/technetwork/java/filters-137243.html. Here is my code:
PrintWriter out = response.getWriter(); CharResponseWrapper wrappedResponse = new CharResponseWrapper( (HttpServletResponse)response); chain.doFilter(wrappedRequest, wrappedResponse); String s = wrappedResponse.toString(); if (wrappedResponse.getContentType().equals("text/html") && StringUtils.isNotBlank(s)) { CharArrayWriter caw = new CharArrayWriter(); caw.write(s.substring(0, s.indexOf("</body>") - 1)); caw.write("WTF</body></html>"); response.setContentLength(caw.toString().length()); out.write(caw.toString()); } else { out.write(wrappedResponse.toString()); } out.close();
I am also wrapping the request, but that code works and shouldn’t affect the response.
The codebase I am using, calls the
getOutputStreammethod, instead of
getWriterwhen it processes the response, so the examples included in the other answer doesn’t help.
import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class MyFilter implements Filter { private FilterConfig filterConfig = null; private static class ByteArrayServletStream extends ServletOutputStream { ByteArrayOutputStream baos; ByteArrayServletStream(ByteArrayOutputStream baos) { this.baos = baos; } public void write(int param) throws IOException { baos.write(param); } } private static class ByteArrayPrintWriter { 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(); } } public class CharResponseWrapper extends HttpServletResponseWrapper { private ByteArrayPrintWriter output; private boolean usingWriter; public CharResponseWrapper(HttpServletResponse response) { super(response); usingWriter = false; output = new ByteArrayPrintWriter(); } public byte[] getByteArray() { return output.toByteArray(); } @Override public ServletOutputStream getOutputStream() throws IOException { // will error out, if in use if (usingWriter) { super.getOutputStream(); } usingWriter = true; return output.getStream(); } @Override public PrintWriter getWriter() throws IOException { // will error out, if in use if (usingWriter) { super.getWriter(); } usingWriter = true; return output.getWriter(); } public String toString() { return output.toString(); } } public void init(FilterConfig filterConfig) throws ServletException { this.filterConfig = filterConfig; } public void destroy() { filterConfig = null; } public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { CharResponseWrapper wrappedResponse = new CharResponseWrapper( (HttpServletResponse)response); chain.doFilter(request, wrappedResponse); byte[] bytes = wrappedResponse.getByteArray(); if (wrappedResponse.getContentType().contains("text/html")) { String out = new String(bytes); // DO YOUR REPLACEMENTS HERE out = out.replace("</head>", "WTF</head>"); response.getOutputStream().write(out.getBytes()); } else { response.getOutputStream().write(bytes); } } }
One important note: you need to use
HttpServletResponse.setContentLengthmethod to update response header according to your response body change, otherwise mismatch may lead to unknown behavior on client.
Servlet:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.getWriter().println("Test"); }
Filter:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { System.out.println("BEFORE filter"); PrintWriter out = response.getWriter(); CharResponseWrapper responseWrapper = new CharResponseWrapper( (HttpServletResponse) response); chain.doFilter(request, responseWrapper); String servletResponse = new String(responseWrapper.toString()); out.write(servletResponse + " filtered"); // Here you can change the response System.out.println("AFTER filter, original response: " + servletResponse); }
CharResponseWrapper (exactly as the article)
public class CharResponseWrapper extends HttpServletResponseWrapper { private CharArrayWriter output; public String toString() { return output.toString(); } public CharResponseWrapper(HttpServletResponse response) { super(response); output = new CharArrayWriter(); } public PrintWriter getWriter() { return new PrintWriter(output); } }
web.xml
<servlet> <servlet-name>TestServlet</servlet-name> <servlet-class>TestServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>TestServlet</servlet-name> <url-pattern>/TestServlet</url-pattern> </servlet-mapping> <filter> <filter-name>TestFilter</filter-name> <filter-class>MyFilter</filter-class> </filter> <filter-mapping> <filter-name>TestFilter</filter-name> <url-pattern>/TestServlet/*</url-pattern> </filter-mapping>
理解要修改resonse的关键是提供一个假的输出流替换response的输出流
相关文章推荐
- Java中super的几种用法并与this的区别
- Modify html response using filter
- 这两天
- Android ORM DB使用心得
- Filter that uses a response wrapper to convert all output to uppercase
- [LeetCode]Different Ways to Add Parentheses
- Spring 4 MVC HelloWorld Tutorial – Full XML Example
- 加载文档后,知道文档中有哪些“看不见的”转义字符
- EF 存储过程
- CLASSPATH   PATH环境变量以及JAVA_HOME的作用
- POJ 1032 解题报告
- Visual Studio 2015的C++开发新特性(链接)
- 各种居中问题
- LeetCode Partition List
- LeetCode Partition List
- [LeetCode#263]Factorial Trailing Zeroes
- 做软件不要忘了做荷兰文
- Oracle+Ado.Net(四)
- 卷积神经网络小结(Convolutional Neural Networks)
- LeetCode Linked List Cycle II