這篇文章將為大家詳細(xì)講解有關(guān)怎樣修改JSP文件的實(shí)時(shí)生效,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。
創(chuàng)新互聯(lián)建站-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價(jià)比德興網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫(kù),直接使用。一站式德興網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋德興地區(qū)。費(fèi)用合理售后完善,10余年實(shí)體公司更值得信賴。
那JSP文件是怎么樣做到改動(dòng)實(shí)時(shí)生效的呢
在JSP處理過(guò)程中,會(huì)判斷文件是否生成,是否過(guò)期,根據(jù)此來(lái)決定是否重新編譯JSP文件生成Servlet類。這個(gè)一般是通過(guò)JspServletWrapper的service方法開始調(diào)用的。
在該方法中有如下代碼:
if (options.getDevelopment() || firstTime ) {//重點(diǎn)看這里
synchronized (this) {
firstTime = false;
// The following sets reload to true, if necessary
ctxt.compile();
}}
默認(rèn)的情況下,這個(gè)options的development屬性為true,所以都會(huì)進(jìn)到這個(gè)代碼塊中。
對(duì)應(yīng)的compile方法,有如下代碼段:
public void compile() {
createCompiler();
if (jspCompiler.isOutDated()) {//此處判斷文件是否過(guò)期
if (isRemoved()) {
throw new FileNotFoundException(jspUri);
}
try {
jspCompiler.removeGeneratedFiles();
jspLoader = null; //注意這里
jspCompiler.compile();
jsw.setReload(true); //這里會(huì)設(shè)置reload標(biāo)識(shí)
jsw.setCompilationException(null);
}
判斷過(guò)期的代碼比較多,這里不全部羅列了,大致包含以下幾個(gè)點(diǎn):
檢查jsp文件生成的Servlet類對(duì)應(yīng)的class文件,如果不存在,則認(rèn)為過(guò)期
如果class文件修改時(shí)間和jsp的修改時(shí)間不一致,則認(rèn)為過(guò)期
對(duì)于jsp中include的一些資源,如果有更新操作的,也會(huì)認(rèn)為過(guò)期
從上面的代碼看到,在判斷文件過(guò)期之后,會(huì)執(zhí)行這樣幾個(gè)操作:
刪除舊文件,
編譯并生成新文件,
設(shè)置reload屬性為true
設(shè)置jspLoader為null
操作的最后兩點(diǎn),是jsp文件能夠修改立即生效的秘密所在。
我們看在jsp所對(duì)應(yīng)的Wrapper的service方法中,判斷并執(zhí)行compile操作之后,第二步就是獲取具體的servlet類,這個(gè)方法的一些主要代碼如下:
public Servlet getServlet() throws ServletException {
if (reload) {
synchronized (this) {
if (reload) {
destroy();
final Servlet servlet;
try {
InstanceManager instanceManager = InstanceManagerFactory.getInstanceManager(config);
servlet = (Servlet) instanceManager.newInstance(ctxt.getFQCN(), ctxt.getJspLoader());
} catch (Exception e) {}
theServlet = servlet;
reload = false;
}}}
return theServlet;
}
我們看,上面首先根據(jù)reload標(biāo)識(shí)來(lái)判斷是否要重新加載Servlet類。而每次的jsp修改,都會(huì)導(dǎo)致compile時(shí)將此標(biāo)識(shí)設(shè)置為true,自然每次的修改都是要加載的。那這個(gè)和上面的jspLoader有什么關(guān)系呢?
我們注意到instanceManager的newInstance方法,會(huì)從JspCompilationContext
這個(gè)類取Jsp的ClassLoader,這個(gè)取classLoader的過(guò)程如下:
public ClassLoader getJspLoader() {
if( jspLoader == null ) {//看這里
jspLoader = new JasperLoader
(new URL[] {baseUrl}, //這里的baseUrl,就是應(yīng)用的file:/D:/xxx/work/Catalina/localhost/test/
getClassLoader(),
rctxt.getPermissionCollection());
}
return jspLoader;
}
在獲取jspLoader的,如果這個(gè)對(duì)象為null,就會(huì)新創(chuàng)建一個(gè)。這個(gè)get到的
jspLoader會(huì)被用來(lái)執(zhí)行l(wèi)oadClass的操作,即jsp對(duì)應(yīng)的Servlet類是會(huì)被其進(jìn)行加載的。
假設(shè)在請(qǐng)求應(yīng)用的index.jsp頁(yè)面,那初次請(qǐng)求時(shí), instanceManager對(duì)應(yīng)的classLoader是一個(gè),當(dāng)修改jsp文件后再次請(qǐng)求時(shí),又是使用的另一個(gè)classLoader,所以新的內(nèi)容修改被成功加載,而原來(lái)舊的內(nèi)容,已經(jīng)在compile階段被清除了。
關(guān)于怎樣修改JSP文件的實(shí)時(shí)生效就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。