咱們都知道在weblogic中JSP是每次第一次訪問的時候纔會編譯,這就形成第一次訪問某個JSP的時候性能降低,有時候咱們也但願JSP被編譯成class而後打包在jar中實現隱藏JSP的功能,下面介紹本身幾天來的研究成果。在這裏weblogic採用的是weblogic12c。html
前提知道JSP編譯以後存放的位置在:%base%\user_projects\domains\base_domain\servers\AdminServer\tmp\_WL_user\Struts\km2umq\jsp_servlet文件夾下面。(Struts是個人項目根路徑的名稱,jsp_servlet是一個存放JSP編譯以後的class文件的根文件)。java
本文介紹的%base%表示E:\weblogic\user_projects\domains\base_domain\autodeploy\Struts,也就是項目的根目錄web
例如個人一個weblogic.xml以下:spring
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE weblogic-web-app PUBLIC "-//BEA Systems, Inc.//DTD Web Application 8.1//EN" "http://www.bea.com/servers/wls810/dtd/weblogic810-web-jar.dtd"> <weblogic-web-app> <jsp-descriptor> <jsp-param> <param-name>encoding</param-name> <param-value>GBK</param-value> </jsp-param> <jsp-param> <param-name>pageCheckSeconds</param-name> <param-value>-1</param-value> </jsp-param> <jsp-param> <param-name>precompile</param-name> <param-value>true</param-value> </jsp-param> <jsp-param> <param-name>compilerSupportsEncoding</param-name> <param-value>true</param-value> </jsp-param> <jsp-param> <param-name>verbose</param-name> <param-value>false</param-value> </jsp-param> </jsp-descriptor> <container-descriptor> <prefer-web-inf-classes>true</prefer-web-inf-classes> </container-descriptor> <context-root>/C8</context-root> </weblogic-web-app>
上面標紅的地方就是設置weblogic對JSP進行預編譯。express
例如我項目中三個JSP文件的位置以下:數組
%base%index.jsporacle
%base%WEB-INF\jsps\index.jspapp
%base%\view\index.jspdom
編譯後的三個文件位置以下:eclipse
E:\weblogic\user_projects\domains\base_domain\servers\AdminServer\tmp\_WL_user\Struts\km2umq\jsp_servlet\__index.class
反編譯查看頭信息:(也就是jsp_servlet是一個根目錄)
E:\weblogic\user_projects\domains\base_domain\servers\AdminServer\tmp\_WL_user\Struts\km2umq\jsp_servlet\_view\__index.class
E:\weblogic\user_projects\domains\base_domain\servers\AdminServer\tmp\_WL_user\Struts\km2umq\jsp_servlet\_web_45_inf_jsps\__index.class
WEB-INF目錄下的JSP比較特殊,會自動編譯到jsp_servlet\_web_45_inf_jsps\目錄下。
訪問項目首頁進行測試:
有時候咱們也但願將原來的JSP刪掉,只保留編譯後的class文件,這樣能夠隱藏JSP。若是在上面編譯完以後只是將咱們的JSP刪掉,那麼不會起做用。例如:
部署成功以後從新訪問會報404:
咱們將以前編譯後的JSP打包放進項目的lib中:
ain/servers/AdminServer/tmp/_WL_user/Struts/km2umq $ ls jsp_servlet/ public/ war/ Administrator@MicroWin10-1535 MINGW64 /e/weblogic/user_projects/domains/base_domain/servers/AdminServer/tmp/_WL_user/Struts/km2umq $ jar cvf ./jsp.jar ./jsp_servlet/ 已添加清單 正在添加: jsp_servlet/(輸入 = 0) (輸出 = 0)(存儲了 0%) 正在添加: jsp_servlet/_view/(輸入 = 0) (輸出 = 0)(存儲了 0%) 正在添加: jsp_servlet/_view/__index.class(輸入 = 5683) (輸出 = 2656)(壓縮了 53%) 正在添加: jsp_servlet/_web_45_inf/(輸入 = 0) (輸出 = 0)(存儲了 0%) 正在添加: jsp_servlet/_web_45_inf/_jsps/(輸入 = 0) (輸出 = 0)(存儲了 0%) 正在添加: jsp_servlet/_web_45_inf/_jsps/__index.class(輸入 = 5715) (輸出 = 2674)(壓縮了 53%) 正在添加: jsp_servlet/__index.class(輸入 = 5666) (輸出 = 2649)(壓縮了 53%)
在web.xml加入下面的配置:
至關於springMVC入口同樣,因此的jsp後綴請求都進weblogic的servlet中處理。(webservice的請求也是如此)
<servlet> <servlet-name>JSPClassServlet</servlet-name> <servlet-class>weblogic.servlet.JSPClassServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>JSPClassServlet</servlet-name> <url-pattern>*.jsp</url-pattern> </servlet-mapping>
再次啓動訪問項目便可,這樣就達到了隱藏JSP和預編譯JSP的目的。
:
有時候咱們的項目採用ant進行部署,因此還必須ant編譯JSP。因而研究了ant結合weblogic.jspc進行編譯JSP的過程。
實際上進行編譯的JSPC位於:E:\weblogic\wlserver\modules\com.oracle.weblogic.package.jar內。
咱們發現E:\weblogic\wlserver\server\lib\weblogic.jar裏面沒有任何一個class,只有一個MANIFEST.MF,裏面的classpath引入了幾乎weblogic帶的全部報,包括E:\weblogic\wlserver\modules下面的包。
網上一篇關於 MANIFEST.MF中classpath的解釋:
1. 基本格式
屬性名稱+:+空格+屬性值
2. 沒行最多72個字符,換行繼續必須以空格開頭
3. 文件最後必需要有一個回車換行
4. Class-Path 當前路徑是jar包所在目錄,若是要引用當前目錄下一個子目錄中的jar包,使用如下格式
子目錄/xxx.jar 子目錄/yyy.jar
技巧:多個jar包的引用,可使用 .classpath 文件中classpathentry 的值
5. 在任何平臺上路徑分割符都是 /,多個jar包引用以空格分開
Manifest-Version: 1.0
Agent-Class: com.ali.b2b.crm.dynamic.agent.MyAgentMain
Main-Class: com.ali.b2b.crm.dynamic.agent.Dynamic
Can-Redefine-Classes: true
Can-Retransform-Classes: true
Boot-Class-Path: javassist.jar
Class-Path: lib/tools.jar lib/guava-r09.jar lib/guice-2.0.jar
因此網上不少說jspc在weblogic包內,weblogic12的機制不是這樣的,是在weblogic.jar內引入weblogic模塊的其餘包。編譯JSP的話引入%weblogic%\wlserver\server\lib,這個模塊自動依賴:%weblogic%\modules
weblogic10.3.6確實在weblogic包內,不過還依賴其餘許多lib。若是隻是編譯JSP,不想找的話能夠引入兩個目錄下的lib分別是:%weblogic%\wlserver_10.3\server\lib,這個模塊自動依賴:%weblogic%\modules
<?xml version="1.0" encoding="UTF-8"?> <project name="AppcTest" default="precompile" basedir="."> <description>Sample build file using Ant to call WLS APPC</description> <property name="wls_root" value="E:/weblogic" /> <property name="wls_home" value="${wls_root}/wlserver" /> <path id="wls.classpath"> <fileset dir="${wls_home}/server/lib"> <include name="*.jar" /> </fileset> </path> <!-- ================================= target: precompile ================================= --> <target name="precompile" description="--> description"> <!--compile JSP--> <java classname="weblogic.jspc" classpathref="wls.classpath" fork="true" failonerror="yes" maxmemory="1028m"> <arg line="-webapp E:/xiangmu/WebTest/WebContent/ -d C:/Users/Administrator/Desktop/wlappc -compileAll" /> </java> </target> </project>
參數解釋:
在precompile任務中,調用了weblogic.jspc,該類位於com.oracle.weblogic.package.jar包內,所以要將此包放入classpath內,這就是classpathref的做用(classpath引入weblogic.jar,其MANIFEST.MF又引入相關jar包),fork是叉牛排用的大叉子,因其一個把手多個爪子的特點,故而被借用到計算機中來代稱「指令的派生」,一輩子二,二生三,三生無窮。。咱們知道ant自己必須跑在虛擬機環境之中,而每一個任務也一樣必須跑在一個虛擬機環境之中。這樣就存在一個選擇的問題:任務能夠和ant處在同一虛擬機中,也能夠不。fork正是來幹這件事的,它來負責作決定。Maxmemory屬性要指定,否則文件多了就會失敗。Arg標籤指定了weblogic.jspc的一些參數,這裏是比較關鍵的幾個參數,-webapp表示web應用所在的目錄,編譯程序會在此目錄及其子目錄尋找jsp文件,-d參數指示jsp編譯後的class文件放哪裏,通常是web目錄下的WEB-INF/classes目錄,-compileAll表示編譯-d指定的目錄及其全部子目錄(包括WEB-INF目錄)。
若是咱們想查看更多的參數解釋能夠運行以下ant:
<?xml version="1.0" encoding="UTF-8"?> <project name="AppcTest" default="precompile" basedir="."> <description>Sample build file using Ant to call WLS APPC</description> <property name="wls_root" value="E:/weblogic" /> <property name="wls_home" value="${wls_root}/wlserver" /> <path id="wls.classpath"> <fileset dir="${wls_home}/server/lib"> <include name="*.jar" /> </fileset> </path> <!-- ================================= target: precompile ================================= --> <target name="precompile" description="--> description"> <!--compile JSP--> <java classname="weblogic.jspc" classpathref="wls.classpath" fork="true" failonerror="yes" maxmemory="1028m"> <arg line="-advanced" /> </java> </target> </project>
結果:(而後本身去意會去把)
precompile: [java] Usage: java weblogic.servlet.jsp.jspc20 [options] <jsp files>... [java] where options include: [java] -help Print the standard usage message. [java] -version Print version information. [java] -webapp <dir> Directory to be considered as the document [java] root for resolving relative files. [java] -verboseJspc whether JSP Compiler runs in verbose mode [java] (default is false) [java] -k continue compiling files, even when some fail [java] -noPrintNulls show "null" in jsp expressions as "" [java] -backwardcompatible Backward compatibility option. [java] -charsetMap <charsetMapString> specify mapping of IANA or unofficial [java] charset names used in JSP contentType [java] directives to java charset names. E.g., [java] '-charsetMap x-sjis=Shift_JIS,x-big5=Big5' [java] The most common mappings are built-in to [java] jspc. Use this option only if a desired [java] charset mapping isn't recognized. [java] -maxfiles <int> Maximum number of generated java files to be [java] compiled at one time. [java] -forceGeneration Force generation of JSP classes. Without [java] this flag, the classes may not be generated [java] if it is determined to be unnecessary. [java] -compressHtmlTemplate Remove additional white spaces in html [java] template. Without this flag, html template [java] will be output as is. [java] -optimizeJavaExpression Optimize string concatenation in Java [java] expression. Without this flag, Java [java] expression will be output as is. [java] -strictJspDocumentValidation Validate JSP document's format strictly [java] with XML Parser. [java] -keepgenerated Keep the generated .java files. [java] -classpath <path> Classpath to use. [java] -target <target> Target version. [java] -d <dir> Target (top-level) directory. [java] -encoding <options> Valid args are "default" to use the default [java] character encoding of JDK, or named [java] character encoding, like "8859_1". If the [java] -encoding flag is not present, an array of [java] bytes is used. [java] -package <packageName> The package into which the .jsp files should [java] be placed 這個參數用於設置默認的包名字,就是上面的jsp_servlet包名 [java] -superclass <superclass> The class name of the superclass which this [java] servlet should extend. [java] -advanced Print advanced usage options.
補充:ant也有編譯的JRE版本,在編譯JDK8的時候因爲ant使用JDK7搞死我了--:
選中如圖位置:External xxx....
配置ant的jre版本:
補充:若是有錯誤而且ant日誌亂碼,解決辦法以下:
在運行時修改ant 的運行時輸出編碼,咱們添加(<sysproperty key="file.encoding" value="UTF-8" />) 後,控制檯就能夠正常顯示中文了,以下:
<!-- ================================= target: precompile ================================= --> <target name="precompile" description="--> description"> <!--compile JSP--> <java classname="weblogic.jspc" classpathref="wls.classpath" fork="true" failonerror="yes" maxmemory="1028m"> <sysproperty key="file.encoding" value="utf-8"/> <arg line="-advanced" /> </java> </target>
補充:若是咱們但願在編譯的classpath中引入某個目錄下的class文件做爲classpath,辦法以下dirset就是將與build.xml同級的build\classes目錄引入classpath(通常eclipse編譯後文件在這個目錄):
<path id="wls.classpath"> <fileset dir="${wls_home}/server/lib"> <include name="*.jar" /> </fileset> <dirset dir="./build/classes"> </dirset> </path>
web.xml中加入:
<servlet> <servlet-name>JSPClassServlet</servlet-name> <servlet-class>weblogic.servlet.JSPClassServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>JSPClassServlet</servlet-name> <url-pattern>*.jsp</url-pattern> </servlet-mapping>
附一個完整的能夠部署的腳本:
<?xml version="1.0" encoding="UTF-8"?> <project name="AppcTest" default="precompile" basedir="."> <description>Sample build file using Ant to call WLS APPC</description> <property name="wls_root" value="E:/weblogic" /> <property name="wls_home" value="${wls_root}/wlserver" /> <property name="adf_lib_root" value="${wls_root}/oracle_common/modules" /> <property name="common_lib_root" value="${wls_home}/common/deployable-libraries" /> <property name="dist.dir" value="dist" /> <property name="web.dir" value="WebContent" /> <property name="weblogic.autodeploy" value="E:/weblogic/user_projects/domains/base_domain/autodeploy" /> <!--import file --> <import file="" /> <path id="wls.classpath"> <fileset dir="${wls_home}/server/lib"> <include name="*.jar" /> </fileset> </path> <!-- ================================= target: clean ================================= --> <target name="clean" description="--> description"> <delete dir="${dist.dir}"> </delete> </target> <!-- ================================= target: precompile ================================= --> <target name="precompile" description="--> description"> <java classname="weblogic.jspc" classpathref="wls.classpath" fork="true" failonerror="yes" maxmemory="1028m"> <arg line="-webapp E:/xiangmu/WebTest/WebContent/ -d E:/xiangmu/WebTest/WebContent/WEB-INF/classes -compileAll" /> </java> </target> <!-- ================================= target: jar ================================= --> <target name="jar" depends="" description="--> package java"> <jar destfile="E:/xiangmu/WebTest/WebContent/lib/commons-jsp.jar"> <fileset dir="E:/xiangmu/WebTest/WebContent/WEB-INF/classes" includes="*.class"> </fileset> </jar> </target> <!-- ================================= target: war ================================= --> <target name="war" depends="clean,precompile" description="--> description"> <mkdir dir="${dist.dir}" /> <war destfile="${dist.dir}/TestPreCompile.war" webxml="${web.dir}/WEB-INF/web.xml"> <classes dir="${web.dir}/WEB-INF/classes"> </classes> <fileset dir="${web.dir}"> <include name="**/weblogic.xml" /> </fileset> </war> </target> <!-- ================================= target: deploy_war ================================= --> <target name="deploy_war" depends="war" description="--> description"> <copy todir="${weblogic.autodeploy}" preservelastmodified="true"> <fileset dir="${dist.dir}"> <include name="*.war" /> </fileset> </copy> </target> </project>
附:JSPc 編譯器選項 使用如下選項的任何組合: -classpath 添加組成所需 CLASSPATH 的目錄的列表(在 Windows NT/2000 平臺上由分號分隔,在 UNIX 平臺上由冒號分隔)。包括包含 JSP 所需的任何類的目錄。例如(要在一行上輸入): $ java weblogic.jspc -classpath java/classes.zip;/weblogic/classes.zip myFile.JSP -charsetMap 指定 JSP contentType 指令中使用的 IANA 或非正式字符集名稱到 Java 字符集名稱的映射。例如: -charsetMap x-sjis=Shift_JIS,x-big5=Big5 最經常使用的映射已內置到 JSP 編譯器中。僅在未識別出所需的字符集映射時,才使用此選項。 -commentary 使 JSP 編譯器未來自 JSP 的註釋包含在生成的 HTML 頁中。若是忽略此選項,則註釋不會出如今生成的 HTML 頁中。 -compileAll 遞歸編譯當前目錄中或經過 -webapp 標誌指定的目錄中的全部 JSP。(請參閱此選項列表中的 -webapp 條目)。還會編譯子目錄中的 JSP。 -compileFlags 將一個或多個命令行標誌傳遞到編譯器。將多個標誌括在引號中,以空格分隔。例如: java weblogic.jspc -compileFlags "-g -v" myFile.jsp -compiler 指定要用於從生成的 Java 源代碼編譯類文件的 Java 編譯器。使用的默認編譯器爲 javac。除非您顯式指定編譯器的絕對路徑,不然 Java 編譯器程序應位於您的 PATH 中。 -compilerclass 將 Java 編譯器做爲 Java 類(而不是本地可執行文件)運行。 -d <dir> 指定已編譯輸出(即類文件)的目標。將此選項用做將已編譯的類放入已位於 CLASSPATH 中的目錄的快捷方式。 -depend 若是之前爲某個 JSP 生成的類文件具備比該 JSP 源文件更新的日期戳,則不會從新編譯該 JSP。 -debug 在啓用調試的狀況下進行編譯。 -deprecation 將源文件編譯爲類文件時,若是在生成的 Java 源文件中使用了不同意使用的方法,則會對此作出警告。 -docroot directory 請參閱 -webapp。 -encoding default|named character encoding 有效參數包括 (a) default,它指定使用 JDK 默認字符編碼,(b) 指定的字符編碼,如 8859_1。若是未指定 -encoding 標誌,則使用字節數組。 -g 指示 Java 編譯器將調試信息包含在類文件中。 -help 顯示 JSP 編譯器的全部可用標誌的列表。 -J 獲取傳遞到您的編譯器的選項的列表。 -k 當使用單個命令編譯多個 JSP 時,即便沒法編譯這些 JSP 中的一個或多個 JSP,編譯器也會繼續進行編譯。 -keepgenerated 保留編譯過程當中做爲中間級建立的 Java 源代碼文件。一般狀況下,這些文件會在編譯以後刪除。 -noTryBlocks 若是 JSP 文件具備許多自定義 JSP 標記或嵌套很深的自定義 JSP 標記,而且您在編譯時收到 java.lang.VerifyError 異常,則使用此標誌可以使 JSP 正確進行編譯。 -nowarn 從 Java 編譯器關閉警告消息。 -noPrintNulls 在 JSP 表達式中將「null」顯示爲「」。 -O 在打開優化的狀況下編譯 Java 源文件。此選項會替換 -g 標誌。 -package packageName 設置預規劃給生成的 Java HTTP Servlet 的包名的包名。默認爲 jsp_servlet。 -superclass classname 設置由生成的 Servlet 擴展的超類的類名。命名的超類必須是 HttpServlet 或 GenericServlet 的派生。 -verbose 將 verbose 標誌傳遞到使用 compiler 標誌指定的 Java 編譯器。有關詳細信息,請參閱編譯器文檔。默認值爲 Off。 -verboseJavac 輸出由指定的 JSP 編譯器生成的消息。 -version 輸出 JSP 編譯器的版本。 -webapp directory 展開的目錄格式的包含 Web 應用程序的目錄名稱。若是 JSP 包含對 Web 應用程序中的資源(如 JSP 標記庫或其餘 Java 類)的引用,則 JSP 編譯器將在此目錄中查找這些資源。若是在編譯須要 Web 應用程序中的資源的 JSP 時省略此標誌,則編譯將失敗。