业务需求:一管理系统,系统架构是struts+sping+hibernate,客户在页面上点击一按钮,触发一个发送E-mail的操作。Email的内容是html的格式,内容不是死的,但有一个模板。
解决思路:
其一,读入这个模板的html源代码,把需要动态显示的部分分别用特殊的代码做标记,然后在后台把这些特殊的标记用该显示的内容替换。这样做的缺点,如果动态显示的内容较多,需要做多个特殊标记,引起代码混乱,也不便于以后的维护。
其二,把这个模板作为一个jsp页面,发送email的时候,先生成这个jsp页面,当然这个页面不在前台显示,然后把这个jsp页面转换为html文件。然后在读取这个html文件作为email的内容发送。这样做方法一的所有缺点都不存在了。但是如何把一个jsp在后台转换为一个html文件,是一个难点。一较猛同事给出了如下方法,我在这事后诸葛亮,给大家做个分析,共同学习。
/** */
/**
* @param jspFile jsp文件路径
* @param htmlFile 要输出的html文件的路径
* @add 2007/08/30
*/
public void convertJspToHtml(HttpServletRequest request,
HttpServletResponse response, String jspFile, String htmlFile)
throws ServletException, IOException ... {
String url = jspFile;
String name = htmlFile;
ServletContext servletContext = request.getSession()
.getServletContext();
//生成一个特定于jsp的RequestDispatcher对象,以用来对jsp传送请求信息.
RequestDispatcher requestDispatcher = servletContext
.getRequestDispatcher(url);
/**//*new这个ByteArrayOutputStream的作用在于它有一个writeTo(OutputStream out)方法.
用于将此字节数组输出流的全部内容写入到指定的输出流参数中.*/
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//实现了servlet.ServletOutputStream抽象类的write方法,用于把响应信息写入到刚new的byteArrayOutputStream中.
/**//*只是不知道为什么要实现这两个write方法*/
final ServletOutputStream servletOutputStream = new ServletOutputStream() ...{
public void write(byte[] data, int offset, int length) ...{
byteArrayOutputStream.write(data, offset, length);
}
public void write(int b) throws IOException ...{
byteArrayOutputStream.write(b);
}
};
//new一个PrintWriter,连接到刚new的byteArrayOutputStream中
final PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(
byteArrayOutputStream));
//重写了servlet.HttpServletResponseWrapper类的两个方法
HttpServletResponse res = new HttpServletResponseWrapper(response) ...{
//此方法返回ServletOutputStream对象,它是java.io.OutputStream的一个子类。此对象向客户发送二进制数据。
public ServletOutputStream getOutputStream() ...{
return servletOutputStream;
}
//此方法将返回PrintWriter对象,把servlet的结果作为文本返回给调用者。
//PrintWriter对象自动把Java内部的UniCode编码字符转换成正确的编码以使客户端能够阅读。
public PrintWriter getWriter() ...{
return printWriter;
}
};
requestDispatcher.include(request, res);
printWriter.flush();
FileOutputStream fos = new FileOutputStream(name); // 把jsp输出的内容写到xxx.htm
byteArrayOutputStream.writeTo(fos);
fos.close();
}
* @param jspFile jsp文件路径
* @param htmlFile 要输出的html文件的路径
* @add 2007/08/30
*/
public void convertJspToHtml(HttpServletRequest request,
HttpServletResponse response, String jspFile, String htmlFile)
throws ServletException, IOException ... {
String url = jspFile;
String name = htmlFile;
ServletContext servletContext = request.getSession()
.getServletContext();
//生成一个特定于jsp的RequestDispatcher对象,以用来对jsp传送请求信息.
RequestDispatcher requestDispatcher = servletContext
.getRequestDispatcher(url);
/**//*new这个ByteArrayOutputStream的作用在于它有一个writeTo(OutputStream out)方法.
用于将此字节数组输出流的全部内容写入到指定的输出流参数中.*/
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//实现了servlet.ServletOutputStream抽象类的write方法,用于把响应信息写入到刚new的byteArrayOutputStream中.
/**//*只是不知道为什么要实现这两个write方法*/
final ServletOutputStream servletOutputStream = new ServletOutputStream() ...{
public void write(byte[] data, int offset, int length) ...{
byteArrayOutputStream.write(data, offset, length);
}
public void write(int b) throws IOException ...{
byteArrayOutputStream.write(b);
}
};
//new一个PrintWriter,连接到刚new的byteArrayOutputStream中
final PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(
byteArrayOutputStream));
//重写了servlet.HttpServletResponseWrapper类的两个方法
HttpServletResponse res = new HttpServletResponseWrapper(response) ...{
//此方法返回ServletOutputStream对象,它是java.io.OutputStream的一个子类。此对象向客户发送二进制数据。
public ServletOutputStream getOutputStream() ...{
return servletOutputStream;
}
//此方法将返回PrintWriter对象,把servlet的结果作为文本返回给调用者。
//PrintWriter对象自动把Java内部的UniCode编码字符转换成正确的编码以使客户端能够阅读。
public PrintWriter getWriter() ...{
return printWriter;
}
};
requestDispatcher.include(request, res);
printWriter.flush();
FileOutputStream fos = new FileOutputStream(name); // 把jsp输出的内容写到xxx.htm
byteArrayOutputStream.writeTo(fos);
fos.close();
}
/*
在这学习一下
RequestDispatcher
,它有两个方法,
forward(ServletRequest request, ServletResponse response)
和
include(ServletRequest request, ServletResponse response),
都是用与
servlet
之间的通讯.
1
.forward()
方法:
被用来从这个
Servlet
向其它服务器资源传递请求。
当一个
Servlet
对响应作了初步的处理,并要求其它的对象对此作出响应时,可以使用这个方法。
当
request
对象被传递到目标对象时,请求的
URL
路径和其他路径参数会被调整为反映目标对象的目标
URL
路径。
如果已经通过响应返回了一个
ServletOutputStream
对象或
PrintWriter
对象,这个方法将不能使用,
否则,这个方法会抛出一个
IllegalStateException
。
我的理解:用于一个
servlet
向目标
servlet
的单向通讯.
2.include()
方法:
用来包括发送给其他服务器资源的响应的内容。本质上来说,这个方法反映了服务器端的内容。
请求对象传到目标对象后会反映调用请求的请求
URL
路径和路径信息。
这个响应对象只能调用这个
Servlet
的
ServletOutputStream
对象和
PrintWriter
对象。
一个调用
include
的
Servlet
不能设置头域,如果这个
Servlet
调用了必须设置头域的方法(例如
cookie
),
这个方法将不能保证正常使用。作为一个
Servlet
开发者,你必须妥善地解决那些可能直接存储头域的方法。
例如,即使你使用会话跟踪,为了保证
session
的正常工作,你必须在一个调用
include
的
Servlet
之外开始你的
session
我的理解:用于两个
servlet
之间的双向通讯.
*/
/*public abstract class ServletOutputStream extends OutputStream
这是一个由
Servlet
引擎使用的抽象类。
Servlet
通过使用
ServletResponse
接口的使用获得了对一个这种类型的对象的说明。
利用这个输出流可以将数据返回到客户端。
这个类的子类必须提供一个向
OutputStream
接口写入有关信息的方法。
在这个接口中,当一个刷新或关闭的方法被调用时。所有数据缓冲区的信息将会被发送到客户端,也就是说响应被提交了。
请注意,关闭这种类型的对象时不一定要关闭隐含的
socket
流。
*/
/*
public PrintWriter(OutputStream out)
根据现有的
OutputStream
创建不带自动行刷新的新
PrintWriter
。
此便捷构造方法创建必要的中间
OutputStreamWriter
,后者使用默认字符编码将字符转换为字节。
*/
/*public class ServletResponseWrapper
extends java.lang.Object
implements ServletResponse
Provides a convenient implementation of the ServletResponse interface t
hat can be subclassed by developers wishing to adapt the response from a Servlet.
This class implements the Wrapper or Decorator pattern.
Methods default to calling through to the wrapped response object.*/
我做了如下修改也可以
public
void
convertJspToHtml(HttpServletRequest request,
HttpServletResponse response, String jspFile, String htmlFile)
throws ServletException, IOException ... {
String url = jspFile;
String name = htmlFile;
ServletContext servletContext = request.getSession()
.getServletContext();
//生成一个特定于jsp的RequestDispatcher对象,以用来对jsp传送请求信息.
RequestDispatcher requestDispatcher = servletContext
.getRequestDispatcher(url);
/**//*new这个ByteArrayOutputStream的作用在于它有一个writeTo(OutputStream out)方法.
用于将此字节数组输出流的全部内容写入到指定的输出流参数中.*/
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//实现了servlet.ServletOutputStream抽象类的write方法,用于把响应信息写入到刚new的byteArrayOutputStream中.
final class ServletOutputStream ...{
public void write(byte[] data, int offset, int length) ...{
byteArrayOutputStream.write(data, offset, length);
}
public void write(int b) throws IOException ...{
byteArrayOutputStream.write(b);
}
};
//new一个PrintWriter,连接到刚new的byteArrayOutputStream中
final PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(
byteArrayOutputStream));
//重写了servlet.HttpServletResponseWrapper类的两个方法
HttpServletResponse res = new HttpServletResponseWrapper(response) ...{
//此方法返回ServletOutputStream对象,它是java.io.OutputStream的一个子类。此对象向客户发送二进制数据。
// public ServletOutputStream getOutputStream() {
// return servletOutputStream;
// }
//此方法将返回PrintWriter对象,把servlet的结果作为文本返回给调用者。
//PrintWriter对象自动把Java内部的UniCode编码字符转换成正确的编码以使客户端能够阅读。
public PrintWriter getWriter() ...{
return printWriter;
}
};
requestDispatcher.include(request, res);
printWriter.flush();
FileOutputStream fos = new FileOutputStream(name); // 把jsp输出的内容写到xxx.htm
byteArrayOutputStream.writeTo(fos);
fos.close();
}
HttpServletResponse response, String jspFile, String htmlFile)
throws ServletException, IOException ... {
String url = jspFile;
String name = htmlFile;
ServletContext servletContext = request.getSession()
.getServletContext();
//生成一个特定于jsp的RequestDispatcher对象,以用来对jsp传送请求信息.
RequestDispatcher requestDispatcher = servletContext
.getRequestDispatcher(url);
/**//*new这个ByteArrayOutputStream的作用在于它有一个writeTo(OutputStream out)方法.
用于将此字节数组输出流的全部内容写入到指定的输出流参数中.*/
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//实现了servlet.ServletOutputStream抽象类的write方法,用于把响应信息写入到刚new的byteArrayOutputStream中.
final class ServletOutputStream ...{
public void write(byte[] data, int offset, int length) ...{
byteArrayOutputStream.write(data, offset, length);
}
public void write(int b) throws IOException ...{
byteArrayOutputStream.write(b);
}
};
//new一个PrintWriter,连接到刚new的byteArrayOutputStream中
final PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(
byteArrayOutputStream));
//重写了servlet.HttpServletResponseWrapper类的两个方法
HttpServletResponse res = new HttpServletResponseWrapper(response) ...{
//此方法返回ServletOutputStream对象,它是java.io.OutputStream的一个子类。此对象向客户发送二进制数据。
// public ServletOutputStream getOutputStream() {
// return servletOutputStream;
// }
//此方法将返回PrintWriter对象,把servlet的结果作为文本返回给调用者。
//PrintWriter对象自动把Java内部的UniCode编码字符转换成正确的编码以使客户端能够阅读。
public PrintWriter getWriter() ...{
return printWriter;
}
};
requestDispatcher.include(request, res);
printWriter.flush();
FileOutputStream fos = new FileOutputStream(name); // 把jsp输出的内容写到xxx.htm
byteArrayOutputStream.writeTo(fos);
fos.close();
}