Servlet学习——分析一牛同事的代码

 
业务需求:一管理系统,系统架构是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();
        }

 

 

/* 在这学习一下 RequestDispatcher ,它有两个方法, forward(ServletRequest request, ServletResponse response)
             和 include(ServletRequest request, ServletResponse response), 都是用与 servlet 之间的通讯.
            .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();
    }
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值