學習到此為止告一段落 對教程內(nèi)容和jsp有什么建議的話,可以跟叮咚姐姐聯(lián)系,隨著技術(shù)的進步,我們也會同步更新教程的內(nèi)容。 提出問題:“session是在什么時候生成的?” 現(xiàn)象:
對現(xiàn)象的感性認識:jsp會自動創(chuàng)建HttpSession對象,而servlet則不會,只有在servlet中顯式調(diào)用getSession()方法時才創(chuàng)建session。 對現(xiàn)象的理性說明
因為<%@ page session="false"%>不會生成默認的session,在這個jsp頁面里就無法直接使用session變量了。下面的代碼會導致jsp無法編譯的錯誤。 <%@ page session="false"%>
<%
out.println(session);
%>
<hr />
訪問test3.jsp會出現(xiàn)500服務(wù)器內(nèi)部錯誤 在使用過<%@ page session="false"%>的頁面里只能使用getSession()手工獲得session才能使用了。 演示用代碼放在99-01目錄下,TestServlet映射到/請求路徑,test1.jsp會自動創(chuàng)建session,test2.jsp禁用了session,test3.jsp直接使用session會出現(xiàn)錯誤。 這個問題是典型的無用研究之一,實際工作中會有人使用getSession(false)嗎? 有同學提到了一個問題:讓用戶自己編寫jsp上傳到服務(wù)器,服務(wù)器接收后保存入數(shù)據(jù)庫,在用戶訪問的時候從數(shù)據(jù)庫中取出對應(yīng)的jsp,運行后返回響應(yīng)。 這個效果從理論上講是可以實現(xiàn)的,我們已經(jīng)對jsp的運行機制非常熟悉了,第 6.2 節(jié) “jsp與servlet的關(guān)系”,我們只需要將jsp轉(zhuǎn)換為對應(yīng)servlet的java文件,再編譯為class,最后使用ClassLoader加載生成的class執(zhí)行即可。 好消息是tomcat為我們提供了批量轉(zhuǎn)換jsp的工具,使用以下的ant腳本就可以將指定目錄下的jsp轉(zhuǎn)換成對應(yīng)servlet的java代碼。(ant的使用方法已經(jīng)超出了本文的討論范圍,如果有興趣請自行參閱官方網(wǎng)站。http://ant./) <project name="jspc" default="jspc" basedir="."> <property name="CATALINA_HOME" location="../../"/> <path id="build.lib"> <pathelement location="WEB-INF/classes"/> <fileset dir="WEB-INF/lib"> <include name="*.jar"/> </fileset> </path> <target name="jspc"> <taskdef classname="org.apache.jasper.JspC" name="jasper2"> <classpath> <pathelement location="${java.home}/../lib/tools.jar"/> <fileset dir="${CATALINA_HOME}/server/lib"> <include name="*.jar"/> </fileset> <fileset dir="${CATALINA_HOME}/common/lib"> <include name="*.jar"/> </fileset> <path refid="build.lib"/> </classpath> </taskdef> <jasper2 verbose="1" package="org.apache.jsp" uriroot="." webXmlFragment="WEB-INF/generated_web.xml" outputDir="./WEB-INF/src/" /> </target> </project> 為了順利完成轉(zhuǎn)換工作,我們需要把一系列jar文件放入classpath中:
簡要介紹一下jasper2的配置參數(shù)。
接著把生成的servlet編譯成class,這次除了common/lib/servlet-api.jar以外我們還需要common/lib/jasper-runtime.jar加入classpath中,編譯腳本參考WEB-INF/src/compile.bat。 現(xiàn)在可以刪除test.jsp了,web.xml中已經(jīng)將/test.jsp請求轉(zhuǎn)發(fā)至對應(yīng)的servlet處理,我們甚至不需要修改任何鏈接。 jspc的主要功能在于預(yù)先編譯jsp發(fā)現(xiàn)其中的語法錯誤,有些公司也使用這種方式進行加密(毫無意義的做法,把jsp唯一的靈活性都浪費了)。 演示程序在99-02目錄下,需要安裝ant之后才可能執(zhí)行run.bat將jsp轉(zhuǎn)換成servlet。 在了解如何手工轉(zhuǎn)換jsp之后,我們可以來討論在數(shù)據(jù)庫中保存jsp的問題了。 將jsp從數(shù)據(jù)庫中提取出來,將這些數(shù)據(jù)保存成本地文件,使用jspc轉(zhuǎn)換成servlet再編譯為class,最后使用自定義的ClassLoader讀取到j(luò)vm中執(zhí)行。 難點在于生成文件要保證互不影響和自定義ClassLoader如何加載管理這些生成的class。 這個問題是典型的無用研究之一,任何想獲得靈活模板功能的同學都應(yīng)該亦然決然的拋棄jsp,jsp這種先解釋編譯再執(zhí)行的機制不僅沒有幫助我們提升效率,反而大大增加技術(shù)難度并降低響應(yīng)效率。需要自定義模板的同志務(wù)必考慮velocity, freemarker此類模板引擎或者groovy一類腳本語言,這時使用jsp無異于給自己帶上一副沉重的枷鎖。 會話都保存在服務(wù)器端。 每個用戶打開瀏覽器就服務(wù)器就會給它生成一個sessionId,瀏覽器或者把這個sessionId放到cookie里,或者每次請求都帶在url后邊(自動的),然后服務(wù)器就拿到這個sessionid,在內(nèi)存里翻啊翻啊,翻出對應(yīng)的session來,就這么對應(yīng)上的。 ServletContext和session就沒多大關(guān)系了,雖然ServletContext也是在服務(wù)器端,每個web應(yīng)用發(fā)布的時候,就要創(chuàng)建這么一塊空間放置ServletContext,這個web應(yīng)用中的所有的servlet, jsp, filter, listener都可以訪問這塊空間。你可以把他看作是一個全局變量,所有共享數(shù)據(jù)都放到里邊。 參考 如何在PHP下載文件名中解決亂碼。 基本代碼如下: <%@page contentType="text/html;charset=UTF-8"%><%request.setCharacterEncoding("utf-8");%><% String client = request.getHeader("User-Agent"); String fileName = "中文"; if (client.indexOf("MSIE") > 0) { fileName = "attachment; filename=\"" + java.net.URLEncoder.encode(fileName, "utf-8") + ".txt\""; } else { fileName = "attachment; filename*=\"utf8''" + java.net.URLEncoder.encode(fileName, "utf-8") + ".txt\""; } String content = "xml格式內(nèi)容." ; response.setContentType("application/octet-stream;charset=UTF-8"); response.setHeader("Content-Disposition", fileName); out.print(content); %> 按照RFC2231的定義, 多語言編碼的Content-Disposition應(yīng)該這么定義: Content-Disposition: attachment; filename*="utf8''%E4%B8%AD%E6%96%87%20%E6%96%87%E4%BB%B6%E5%90%8D.txt"
經(jīng)過試驗,發(fā)現(xiàn)幾種主流瀏覽器的支持情況如下:
|
|