JSP入门教程(DOC格式)-第22部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
有在 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
………………………………………………………………………用户上传之内容结束……………………………………………………………………………………