Resin3 JSP预编译实现
?
Resin3?JSP预编译实现?
?
一、预编译需求
通过预先编译JSP,而不是在线上编译,节省了线上编译时间,降低系统上线初期超高的CPU使用率,以及用户请求等待事件
默认方式,Resin3提供了俩种预编译(http://www.caucho.com/resin-3.0/jsp/compile.xtp),但在实际使用的时候,无论哪种方法,都只能编译部分JSP,导致优化很不明显,据运维的说,还发生了log4j日志无法输出的情况(这个我也很莫名其妙,至今不知道原因)
二、预编译改善原理
幸好Resin是公开源码的,通过分析预编译代码,其默认编译方式是每64个jsp文件为一组,好处是这样编译速度快,但如果其中有一个jsp没有编译通过,则这64个文件都奖编译失败。在我们系统中,有很多子jsp,如果一些JSP不幸与这些子JSP分在一组,则编译不通过。
?
目前解决办法是每组JSP只包含一个jJSP文件。这样就能保证全部编译,但缺点是需要较长编译时间,在测试系统上大概需要1分钟才能编译好200多个JSP文件
?
代码如下:
package?com.javamonkey.common.util;
?
import?java.lang.reflect.Method;
?
import?com.caucho.java.JavacConfig;
?
public?class?ResinJSPCompileTask?{
?
/**
?*?@param?args
?*/
public?static?void?main(String[]?args)?throws?Exception?{
JavacConfig?config?=?JavacConfig.getLocalConfig();
if?(config?==?null)?{
config?=?new?JavacConfig();
}
config.setMaxBatch(1);
config.setArgs("-nowarn");
config.init();
//String?appDir?=?"D:\\workspace\\20111221_data\\resin\\webRoot";
//String?classDir?=?"D:\\workspace\\20111221_data\\resin\\webRoot\\WEB-INF\\work\";
?
?String?appDir?=?args[0];
?String?classDir?=?args[1];
String?clsName?=?"com.caucho.jsp.JspCompiler";
Class?jsp?=?Class.forName(clsName);
Method?main?=?jsp.getMethod("main",?new?String[0].getClass());
main.invoke(null,?new?Object[]?{?new?String[]?{?"-app-dir",?appDir,
"-class-dir",?classDir?}?});
?
}
}
?
?
?
?
?
核心代码就是config.setMaxBatch(1);
另外?appDir?是web根目录,classDir?是jsp编译后的保存的目录,其实就是${appDir}/WEB-INF/work.
?
针对编译速度慢的情况,可以做如下调整
1?换到线上机器进行预编译,速度能提高
2?setMatBatch(2),能节约一半时间。但会有少数JSP(<?子JSP个数)无法预编译。
?
?
?