JSP 默认在首次被请求时才会编译,结果就是首次请求时响应异常缓慢。下面的办法可实现应用启动时完成 JSP 预编译。
// ...
import org.springframework.boot.web.servlet.ServletContextInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
import static org.apache.catalina.core.Constants.JSP_SERVLET_CLASS;
// ...
@Bean("jspPreCompileServletContextInitializer")
public ServletContextInitializer preCompileJspsOnStartup() {
return servletContext -> getDeepResourcePaths(servletContext, "/views/")
.filter(jspPath -> StringUtils.endsWith(jspPath, ".jsp"))
.forEach(jspPath -> {
ServletRegistration.Dynamic servletRegistration =
servletContext.addServlet(jspPath, JSP_SERVLET_CLASS);
servletRegistration.setInitParameter("development", "false");
servletRegistration.setInitParameter("jspFile", jspPath);
servletRegistration.setLoadOnStartup(1);
servletRegistration.addMapping(jspPath);
});
}
private Stream<String> getDeepResourcePaths(ServletContext servletContext, String path) {
return path.endsWith("/") ? servletContext.getResourcePaths(path).stream()
.flatMap(p -> getDeepResourcePaths(servletContext, p)) : Stream.of(path);
}
注意:
development
参数表示以开发模式运行(将检查 JSP 文件是否有修改),tomcat默认为true
,配合modificationTestInterval
参数可以改变检查频率,此处将其关闭。- JSP 的编译是在
JspServlet
初始化时进行的,因此setLoadOnStartup(1)
让JspServlet
在启动时初始化,就可以实现 JSP 文件在启动时就完成编译而不是首次被请求时。
另外,还可用使用 JSPC
在项目编译期实现 JSP 预编译。