友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
第三电子书 返回本书目录 加入书签 我的书架 我的书签 TXT全本下载 『收藏到我的浏览器』

JSP入门教程(DOC格式)-第20部分

快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!


都可以在循环体中使用到。  



范例在 15…02。  



                                        141 / 148  


…………………………………………………………Page 142……………………………………………………………

                                         



                     第 16 章 Never End。。。  



学习到此为止告一段落  



对教程内容和 jsp 有什么建议的话,可以跟叮咚姐姐联系,随着技术的进步,我 

们也会同步更新教程的内容。  



16。1。 对 session 何时生成的无用讨论  



提出问题:“session 是在什么时候生成的?”  



现象:  



    1。  如果写一个 servlet,在里边调用 getSession(false),得到的是 null。 

        (这里的参数表示当session 不存在时是否新建,返回 null 表示还没为 

       当前用户生成对应的 session)。  



                                                                         



   2。  如果写一个 jsp,在里边打印 session,可以看到打印的信息,说明session 

       已经创建了。  



                                                                         



对现象的感性认识:jsp 会自动创建 HttpSession 对象,而 servlet 则不会,只 

有在 servlet 中显式调用 getSession()方法时才创建 session。  



对现象的理性说明  



    1。  只有执行了 getSession()才会生成 session。(此处无参数,默认与 

       getSession(true)功能相同)。  

   2。  jsp 转换成 servlet 后,生成的 servlet 代码中包含 getSession()。  



       例子中见 tomcat 目录下, 

       workCatalinalocalhost99…01orgapachejsptest1。jsp,其中包含 

       了pageContext。getSession()。  



                                      142 / 148  


…………………………………………………………Page 143……………………………………………………………

                                                    



    3。  我们可以在 jsp 中使用禁止生成 session 

         的代码,这样即使访问此 jsp 页面,也不会创建 session。  



                                                                                            



         例子中见 tomcat 目录下, 

         workCatalinalocalhost99…01orgapachejsptest2。jsp,这里已经 

         看不到 getSession()的代码了。  



因为不会生成默认的 session,在这个 jsp 页面里 

就无法直接使用 session 变量了。下面的代码会导致 jsp 无法编译的错误。  



  

  

   



访问 test3。jsp 会出现 500 服务器内部错误  



                                                                                        



                                               143 / 148  


…………………………………………………………Page 144……………………………………………………………

                                       



在使用过的页面里只能使用 getSession()手工获 

得 session 才能使用了。  



演示用代码放在 99…01 目录下,TestServlet 映射到/请求路径,test1。jsp 会自 

动创建 session,test2。jsp 禁用了 session,test3。jsp 直接使用 session 会出 

现错误。  



这个问题是典型的无用研究之一,实际工作中会有人使用 getSession(false) 

吗?  



16。2。 对手工将 jsp 转换为 servlet 的无用讨论  



有同学提到了一个问题:让用户自己编写 jsp 上传到服务器,服务器接收后保存 

入数据库,在用户访问的时候从数据库中取出对应的 jsp,运行后返回响应。  



这个效果从理论上讲是可以实现的,我们已经对 jsp 的运行机制非常熟悉了, 

第 6。2 节  “jsp 与 servlet 的关系”,我们只需要将 jsp 转换为对应 servlet 

的 java 文件,再编译为 class,最后使用 ClassLoader 加载生成的 class 执行 

即可。  



好消息是 tomcat 为我们提供了批量转换 jsp 的工具,使用以下的 ant 脚本就可 

以将指定目录下的 jsp 转换成对应 servlet 的 java 代码。(ant 的使用方法已 

经超出了本文的讨论范围,如果有兴趣请自行参阅官方网站。 

http://ant。apache。org/)  



  

      

  

      

          

          

              

          

      

  

      

          

              

                  

                  

                      

                  

                  



                                    144 / 148  


…………………………………………………………Page 145……………………………………………………………

                                           



                      

                  

                  

              

          

  

          

      

   



为了顺利完成转换工作,我们需要把一系列 jar 文件放入 classpath 中:  



    1。  WEB…INF/lib/*。jar (星号代表所有)  

    2。  {java。home}/。。/lib/tools。jar ({java。home}表示 jdk 安装目录)  

    3。  {CATALINA_HOME}/server/lib/*。jar ({CATALINA_HOME}表示 tomcat 

       的安装目录)  

    4。  {CATALINA_HOME}/mon/lib/*。jar  



简要介绍一下 jasper2 的配置参数。  



    1。  verbose=〃1〃表示打印进度信息,如果 verbose=〃0〃则不打印信息。  

    2。  package=〃org。apache。jsp〃表示生成 servlet 中的包名(package)。  

    3。  uriroot=〃。〃表示会把当前目录下的所有 jsp 都转换成 servlet。  

    4。  webXmlFragment=〃WEB…INF/generated_web。xml〃会在 WEB…INF 目录下生 

       成 servlet 的默认配置。  



       比如我们转换的test。jsp 将生成如下部分。  



         

           org。apache。jsp。test_jsp  

           org。apache。jsp。test_jsp  

         

         

         

           org。apache。jsp。test_jsp  

           /test。jsp  

         

                         



                                       145 / 148  


…………………………………………………………Page 146……………………………………………………………

                                 



     将这部分复制到你项目中的web。xml 中就可以通过/test。jsp 请求来访问 

      生成的 servlet 了。  



   5。  outputDir=〃。/WEB…INF/src/〃表示生成的 servlet文件放在WEB…INF/src 

      目录下,tomcat 会自动生成 package 对应的目录,比如 test。jsp 生成的 

     最终路径是 WEB…INF/src/org/apache/jsp/test_jsp。java。  



接着把生成的 servlet 编译成 class,这次除了 mon/lib/servlet…api。jar 

以外我们还需要mon/lib/jasper…runtime。jar 加入 classpath 中,编译脚本 

参考 WEB…INF/src/pile。bat。  



现在可以删除 test。jsp 了,web。xml 中已经将/test。jsp 请求转发至对应的 

servlet 处理,我们甚至不需要修改任何链接。  



jspc 的主要功能在于预先编译 jsp 发现其中的语法错误,有些公司也使用这种 

方式进行加密(毫无意义的做法,把 jsp 唯一的灵活性都浪费了)。  



演示程序在 99…02 目录下,需要安装ant 之后才可能执行 run。bat 将 jsp 转换成 

servlet。  



在了解如何手工转换 jsp 之后,我们可以来讨论在数据库中保存 jsp 的问题了。  



将 jsp 从数据库中提取出来,将这些数据保存成本地文件,使用 jspc 转换成 

servlet 再编译为 class,最后使用自定义的ClassLoader 读取到 jvm 中执行。  



难点在于生成文件要保证互不影响和自定义 ClassLoader 如何加载管理这些生 

成的 class。  



这个问题是典型的无用研究之一,任何想获得灵活模板功能的同学都应该亦然决 

然的抛弃 jsp,jsp 这种先解释编译再执行的机制不仅没有帮助我们提升效率, 

反而大大增加技术难度并降低响应效率。需要自定义模板的同志务必考虑 

velocity; freemarker 此类模板引擎或者 groovy 一类脚本语言,这时使用 jsp 

无异于给自己带上一副沉重的枷锁。  



16。3。 胡乱解释一下 session  



会话都保存在服务器端。  



每个用户打开浏览器就服务器就会给它生成一个 sessionId,浏览器或者把这个 

sessionId 放到 cookie 里,或者每次请求都带在 url 后边(自动的),然后服 

务器就拿到这个 sessionid,在内存里翻啊翻啊,翻出对应的 session 来,就这 

么对应上的。  



ServletContext 和 session 就没多大关系了,虽然 ServletContext 也是在服务 

器端,每个 web 应用发布的时候,就要创建这么一块空间放置 ServletContext, 



                               146 / 148  


…………………………………………………………Page 147……………………………………………………………

                                          



这个 web 应用中的所有的 servlet; jsp; filter; listener 都可以访问这块空 

间。你可以把他看作是一个全局变量,所有共享数据都放到里边。  



16。4。 下载文件乱码  



参考 如何在 PHP 下载文件名中解决乱码。  



基本代码如下:  



 0) {  

    fileName = 〃attachment; filename=”〃 +  

java。URLEncoder。encode(fileName; 〃utf…8〃) + 〃。txt”〃 ;  

} else  {  

    fileName = 〃attachment; filename*=”utf8''〃 +  

java。URLEncoder。encode(fileName; 〃utf…8〃) + 〃。txt”〃 ;  

}  

String content = 〃xml 格式内容。〃  ;  

response。setContentType(〃application/octet…stream;charset=UTF…8〃);  

response。setHeader(〃Content…Disposition〃; fileName);  

out。print(content);  

%》  

          



按照 RFC2231 的定义, 多语言编码的 Content…Disposition 应该这么定义:  



Content…Disposition: attachment;  

filename*=〃utf8''%E4%B8%AD%E6%96%87%20%E6%96%87%E4%BB%B6%E5%90%8D。txt 

〃  



filename 后面的等号之前要加 *  



filename 的值用单引号分成三段,分别是字符集(utf8)、语言(空)和 urlencode 

过的文件名。  



最好加上双引号,否则文件名中空格后面的部分在 Firefox 中显示不出来。  



使用 urlencode 对非 iso…8859…1 字符进行编码。  



                                      147 / 148  


…………………………………………………………Page 148……………………………………………………………

                                                



经过试验,发现几种主流浏览器的支持情况如下:  



    IE6  



attachment; filename=〃〃  



    FF3  



attachment; filename=〃UTF…8 文件名〃  

attachment; filename*=〃utf8''〃  



    O9  



attachment; filename=〃UTF…8 文件名〃  



    Safari3(Win)  



貌似不支持?上述方法都不行  



                                            148 / 148  


………………………………………………………………………用户上传之内容结束……………………………………………………………………………………

返回目录 上一页 回到顶部 0 0
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!