最近想接了一个活,需求是采集多方网站,然后导入到自己库中。 CMS+爬虫。考虑到CMS期初打算用 织梦做一个前台,java做数据来着,结果想了想还是自己写一个吧。
尝试了下Freemarker,但是都有点缺点就是 标签库不够我用,不能定义全局变量。个人习惯想找一个不需要任何框架,我就一个modelandview对象你就生成html就行。找了很多 ぜんぜん 不好使。所以考虑自己写一个吧,参考了国外大神的回答:https://stackoverflow.com/questions/8933054/how-to-read-and-copy-the-http-servlet-response-output-stream-content-for-logging
首先,Springmvc 它自己是不给我们返回响应的,这一点搞得人很纠结,所以要重写方法。
You need to create a Filter wherein you wrap the ServletResponse argument with a custom HttpServletResponseWrapper implementation wherein you override the getOutputStream() and getWriter() to return a custom ServletOutputStream implementation wherein you copy the written byte(s) in the base abstract OutputStream#write(int b) method. Then, you pass the wrapped custom HttpServletResponseWrapper to the FilterChain#doFilter() call instead and finally you should be able to get the copied response after the the call. 上面是原话。就是重写 response 和 ServletOutputStream 。然后建立一个过滤器即可。
过滤器:
@WebFilter("/*")
public class ResponseLogger implements Filter {
@Override
public void init(FilterConfig config) throws ServletException {
// NOOP.
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
if (response.getCharacterEncoding() == null) {
response.setCharacterEncoding("UTF-8"); // Or whatever default. UTF-8 is good for World Domination.
}
HttpServletResponseCopier responseCopier = new HttpServletResponseCopier((HttpServletResponse) response);
try {
chain.doFilter(request, responseCopier);
responseCopier.flushBuffer();
} finally {
byte[] copy = responseCopier.getCopy();
}
}
@Override
public void destroy() {
// NOOP.
}
}
在过滤器中使用“new String(copy, response.getCharacterEncoding())” 获取返回的响应内容。然后写一个写入到文件的方法,就可以生成html咯。不过速度挺一般的。
大家可以在后台单独写一个方法,然后定义为生成html的方法,然后首页列表页直接修改为静态页面的地址即可。因为这个生成html要走过滤器,大家也可以自行改进,然后做成调用的方法来用就比较好使。
重写的Response
public class HttpServletResponseCopier extends HttpServletResponseWrapper {
private ServletOutputStream outputStream;
private PrintWriter writer;
private ServletOutputStreamCopier copier;
public HttpServletResponseCopier(HttpServletResponse response) throws IOException {
super(response);
}
@Override
public ServletOutputStream getOutputStream() throws IOException {
if (writer != null) {
throw new IllegalStateException("getWriter() has already been called on this response.");
}
if (outputStream == null) {
outputStream = getResponse().getOutputStream();
copier = new ServletOutputStreamCopier(outputStream);
}
return copier;
}
@Override
public PrintWriter getWriter() throws IOException {
if (outputStream != null) {
throw new IllegalStateException("getOutputStream() has already been called on this response.");
}
if (writer == null) {
copier = new ServletOutputStreamCopier(getResponse().getOutputStream());
writer = new PrintWriter(new OutputStreamWriter(copier, getResponse().getCharacterEncoding()), true);
}
return writer;
}
@Override
public void flushBuffer() throws IOException {
if (writer != null) {
writer.flush();
} else if (outputStream != null) {
copier.flush();
}
}
public byte[] getCopy() {
if (copier != null) {
return copier.getCopy();
} else {
return new byte[0];
}
}
}
重写的ServletOutputStream
public class ServletOutputStreamCopier extends ServletOutputStream {
private OutputStream outputStream;
private ByteArrayOutputStream copy;
public ServletOutputStreamCopier(OutputStream outputStream) {
this.outputStream = outputStream;
this.copy = new ByteArrayOutputStream(1024);
}
@Override
public void write(int b) throws IOException {
outputStream.write(b);
copy.write(b);
}
public byte[] getCopy() {
return copy.toByteArray();
}
}