咱们都知道在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 时省略此标志,则编译将失败。