tomcat ssi配置及升級導致ssi include錯誤問題解決
最近tomcat升級版本時,遇到了ssi解析的問題,記錄下解決的過程,還有tomcat ssi配置的要點。
tomcat 配置SSI的兩種方式
Tomcat有兩種方式支援SSI:Servlet和Filter。
SSIServlet
通過Servlet,org.apache.catalina.ssi.SSIServlet,預設處理”*.shtml”的URL。
配置方式:
修改tomcat的 conf/web.xml檔案,去掉下面配置的註釋:
<servlet>
<servlet-name>ssi</servlet-name>
<servlet-class >
org.apache.catalina.ssi.SSIServlet
</servlet-class>
<init-param>
<param-name>buffered</param-name>
<param-value>1</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value >0</param-value>
</init-param>
<init-param>
<param-name>expires</param-name>
<param-value>666</param-value>
</init-param>
<init-param>
<param-name>isVirtualWebappRelative</param-name>
<param-value >false</param-value>
</init-param>
<load-on-startup>4</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ssi</servlet-name>
<url-pattern>*.shtml</url-pattern>
</servlet-mapping>
SSIFilter
通過Filter,org.apache.catalina.ssi.SSIFilter,預設處理”*.shtml”的URL。
配置方式:
修改tomcat的 conf/web.xml檔案,開啟去掉下面配置的註釋:
<filter>
<filter-name>ssi</filter-name>
<filter-class>
org.apache.catalina.ssi.SSIFilter
</filter-class>
<init-param>
<param-name>contentType</param-name>
<param-value>text/x-server-parsed-html(;.*)?</param-value>
</init-param>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>expires</param-name>
<param-value>666</param-value>
</init-param>
<init-param>
<param-name>isVirtualWebappRelative</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>ssi</filter-name>
<url-pattern>*.shtml</url-pattern>
</filter-mapping>
注意事項
注意:兩種配置方式最好不要同時開啟,除非很清楚是怎樣配置的。
另外,在Tomcat的conf/context.xml裡要配置privileged=”true”,否則有些SSI特性不能生效。
<Context privileged="true">
歷史程式碼裡處理SSI的辦法
在公司的歷史程式碼裡,在一個公共的jar包裡通過自定義一個EnhancedSSIServlet,繼承了Tomcat的org.apache.catalina.ssi.SSIServlet來實現SSI功能的。
@WebServlet(name="ssi",
initParams={@WebInitParam(name="buffered", value="1"), @WebInitParam(name="debug", value="0"),
@WebInitParam(name="expires", value="666"), @WebInitParam(name="isVirtualWebappRelative", value="0"),
@WebInitParam(name="inputEncoding", value="UTF-8"), @WebInitParam(name="outputEncoding", value="UTF-8") },
loadOnStartup=1, urlPatterns={"*.shtml"}, asyncSupported=true)
public class EnhancedSSIServlet extends SSIServlet {
其中@WebServlet是Servlet3.0規範裡的,所以使用到web-common的web專案的web.xml檔案都要配置為3.0版本以上,例如:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
</web-app>
Tomcat是啟動Web應用時,會掃描所有@WebServlet的類,並初始化。
所以在使用到歷史程式碼的專案都只能使用Tomcat伺服器,並且不能在tomcat的conf/web.xml裡開啟SSI相關的配置。
Tomcat版本升級的問題
Tomcat版本從7.0.57升級到7.0.59過程中,出現了無法解析SSI include指令的錯誤:
SEVERE: #include--Couldn't include file: /pages/test/intelFilter.shtml
java.io.IOException: Couldn't get context for path: /pages/test/intelFilter.shtml
at org.apache.catalina.ssi.SSIServletExternalResolver.getServletContextAndPathFromVirtualPath(SSIServletExternalResolver.java:422)
at org.apache.catalina.ssi.SSIServletExternalResolver.getServletContextAndPath(SSIServletExternalResolver.java:465)
at org.apache.catalina.ssi.SSIServletExternalResolver.getFileText(SSIServletExternalResolver.java:522)
at org.apache.catalina.ssi.SSIMediator.getFileText(SSIMediator.java:161)
at org.apache.catalina.ssi.SSIInclude.process(SSIInclude.java:50)
at org.apache.catalina.ssi.SSIProcessor.process(SSIProcessor.java:159)
at com.test.webcommon.servlet.EnhancedSSIServlet.processSSI(EnhancedSSIServlet.java:72)
at org.apache.catalina.ssi.SSIServlet.requestHandler(SSIServlet.java:181)
at org.apache.catalina.ssi.SSIServlet.doPost(SSIServlet.java:137)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
at org.apache.catalina.core.ApplicationDispatcher.doInclude(ApplicationDispatcher.java:604)
at org.apache.catalina.core.ApplicationDispatcher.include(ApplicationDispatcher.java:543)
at org.apache.jasper.runtime.JspRuntimeLibrary.include(JspRuntimeLibrary.java:954)
at org.apache.jsp.pages.lottery.jczq.index_jsp._jspService(index_jsp.java:107)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:395)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:339)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
仔細檢視原始碼後,發現不能處理的include指令程式碼如下:
<!--#include virtual="/pages/test/intelFilter.shtml"-->
經過對比除錯Tomcat的程式碼,發現是在7.0.58版本時,改變了處理URL的方法,關鍵的處理函式是
org.apache.catalina.core.ApplicationContext.getContext( String uri)
在7.0.57版本前,Tomcat在處理處理像/pages/test/intelFilter.shtml這樣的路徑時,恰好迴圈處理了”/”字元,使得childContext等於StandardContext,最終由StandardContext處理了/pages/test/intelFilter.shtml的請求。
這個程式碼實際上是錯誤的,不過恰好處理了include virtual的情況。
在7.0.58版本修改了處理uri的程式碼,所以在升級Tomcat到7.0.59時出錯了。
/**
* Return a <code>ServletContext</code> object that corresponds to a
* specified URI on the server. This method allows servlets to gain
* access to the context for various parts of the server, and as needed
* obtain <code>RequestDispatcher</code> objects or resources from the
* context. The given path must be absolute (beginning with a "/"),
* and is interpreted based on our virtual host's document root.
*
* @param uri Absolute URI of a resource on the server
*/
@Override
public ServletContext getContext(String uri) {
// Validate the format of the specified argument
if ((uri == null) || (!uri.startsWith("/")))
return (null);
Context child = null;
try {
Host host = (Host) context.getParent();
String mapuri = uri;
while (true) {
child = (Context) host.findChild(mapuri);
if (child != null)
break;
int slash = mapuri.lastIndexOf('/');
if (slash < 0)
break;
mapuri = mapuri.substring(0, slash);
}
} catch (Throwable t) {
ExceptionUtils.handleThrowable(t);
return (null);
}
if (child == null)
return (null);
if (context.getCrossContext()) {
// If crossContext is enabled, can always return the context
return child.getServletContext();
} else if (child == context) {
// Can still return the current context
return context.getServletContext();
} else {
// Nothing to return
return (null);
}
}
那麼正確的處理辦法是怎樣的?
仔細檢視Tomcat的SSI配置的說明文件,發現有一個isVirtualWebappRelative的配置,而這個配置預設是false的。
isVirtualWebappRelative - Should "virtual" SSI directive paths be interpreted as relative to the context root, instead of the server root? Default false.
**也就是說,如果要支援“#include virtual=”/b.shtml”絕對路徑這種指令,就要配置isVirtualWebappRelative為true。
但是tomcat預設的SSI配置,以及上面的EnhancedSSIServlet類預設都配置isVirtualWebappRelative為false。**
因此,把EnhancedSSIServlet類裡的isVirtualWebappRelative配置為true,重新測試,發現已經可以正常處理”#include virtual=”/b.shtml”指令了。
相關的邏輯處理的程式碼在org.apache.catalina.ssi.SSIServletExternalResolver.getServletContextAndPathFromVirtualPath( String virtualPath):
protected ServletContextAndPath getServletContextAndPathFromVirtualPath(
String virtualPath) throws IOException {
if (!virtualPath.startsWith("/") && !virtualPath.startsWith("\\")) {
return new ServletContextAndPath(context,
getAbsolutePath(virtualPath));
}
String normalized = RequestUtil.normalize(virtualPath);
if (isVirtualWebappRelative) {
return new ServletContextAndPath(context, normalized);
}
ServletContext normContext = context.getContext(normalized);
if (normContext == null) {
throw new IOException("Couldn't get context for path: "
+ normalized);
}
總結
之前的EnhancedSSIServlet類的配置就不支援”#include virtual=”/b.shtml”,這種絕對路徑的SSI指令,而以前版本的Tomcat因為恰好處理了”/test.shtml”這種以”/”開頭的url,因此以前版本的Tomcat沒有報錯。而升級後的Tomcat修正了程式碼,不再處理這種不合理的絕對路徑請求了,所以報“ Couldn’t get context for path”的異常。
把tomcat的ssi配置裡的isVirtualWebappRelative設定為true就可以了。
最後,留一個小問題:
tomcat是如何知道處理*.jsp請求的?是哪個servlet在起作用?
參考
相關推薦
tomcat ssi配置及升級導致ssi include錯誤問題解決
最近tomcat升級版本時,遇到了ssi解析的問題,記錄下解決的過程,還有tomcat ssi配置的要點。 tomcat 配置SSI的兩種方式 Tomcat有兩種方式支援SSI:Servlet和Filter。 SSIServlet 通過Servl
Java_Web —Tomcat安裝配置及Servlet初探
作者:WenWu_Both 出處:http://blog.csdn.net/wenwu_both/article/ 版權:本文版權歸作者和CSDN部落格共有 轉載:歡迎轉載,但未經作者同意,必須保留此段宣告;必須在文章中給出原文連結;否則必究法律責任 Java的Web開發選用的
Tomcat安裝配置及操作
Tomcat是Servlet容器,本身完全JAVA語言編寫,所以tomcat的執行需要JAVA的支援,要先安裝JDK,才能執行。 一、Tomcat的目錄層次結構 1、Tomcat的目錄層次結構 2、JavaWeb應用的組成結構 |--
Tomcat 記憶體配置 及 配置引數詳解
一、JVM記憶體管理機制: 堆(Heap)和非堆(Non-heap)記憶體 按照官方的說法:“Java 虛擬機器具有一個堆,堆是執行時資料區域,所有類例項和陣列的記憶體均從此處分配。堆是在 Java 虛擬機器啟動時建立的。在JVM中堆之外的記憶體稱為非堆記憶體(Non-
Tomcat 伺服器配置及遠端除錯和不同web專案session共享方法以及設定TOMCAT的記憶體
tomcat環境變數配置 classpath = ./;%JAVA_HOME%/lib/dt.jar;%JAVA_HOME%/lib/tools.jar;%TOMCAT_HOMT%/common/lib/servlet-api.jar;%TOMCAT_HOME%/com
Myeclipse中Tomcat的配置及login.sql檔案的配置
第一篇日誌~~~~~~~~~~~~~~原創,轉載註明出處~~~~~~~~~~~~謝謝同志們==# 重灌了下系統,配置了一下Tomcat和login.sql 一、Myeclipse中Tomcat的配置 1.安裝JDK 這裡下載版本為JDK1.6,安裝到CLASSPATH=F:
Tomcat SSL配置及Tomcat CA證書安裝
最近要做一個SSL的應用,用SSL進行雙向身份驗證意思就是在客戶機連線伺服器時,連結雙方都要對彼此的數字證書進行驗證,保證這是經過授權的才能夠連線。我們連結一般的SSL時採用的是單向驗證,客戶機只驗證伺服器的證書,伺服器不驗證客戶機的證書;而連線網上銀行時使用的U盾就是用來儲存進行雙向驗證所需要的客戶端證書
MySQL+Toad for Mysql安裝,配置及導入中文數據解決亂碼等問題
下載 tools 不同 打開 show amd rac mysql\ 默認 1.下載MySQL5.7版本,安裝官網上的windows安裝版,下載地址為:https://dev.mysql.com/downloads/windows/installer/5.7.html 安
配置spring外掛導致maven崩潰的解決
同新人,學習spring時去c*s*d*n首頁搜了一堆教程就上路了,其中大部分人都會讓裝spring外掛,然後我又隨便的找了一個教程上路裝spring外掛,我也沒選最新版,隨便選了一個版本的springsource-tool-suite,照著教程裝好後發現sp
Jenkins許可權配置失誤後導致登入失敗的解決辦法
為了便於管理,Jenkins一般需要設定使用者,而且這些使用者是需要配置相應的許可權的,如果一不小心配置的時候出了問題,那麼,你就斯巴達了。 這裡,用我的切身經歷,為大家說一下Jenki
GitLab升級維護及升級後報500錯誤
早先給公司內網搭建了一套基於Git的伺服器GitLab,GitLab升級包更新較快,筆者在升級過程中記錄下爬的教程以及遇到了不少的問題,現在分享給出來以供需要時參考。 備份GitLab 修改預設備份目錄: 預設備份目錄是/var/opt/gitlab/backup
Linux下Tomcat控制檯輸出及日誌中文亂碼問題的解決
剛寫了個定時器,呼叫網上流傳的飛信API,實現每天每週的固定時間給特定的手機號上發簡訊提醒的功能。按照網上資料,使用的Servlet監聽器+Timer類。 剛開始完全照搬人家的例子,倒也正常。後來查API時看到到Timer有個方法: "void sche
glibc升級導致系統段錯誤問題解決方案
報錯 封裝 enabled 分享 segment 功能 stat 版本過低 技術分享 系統:阿裏雲ECS CentOS6.5 當前GLIBC版本:2.12 準備升級GLIBC版本:2.19 一,GLIBC介紹
Tomcat啟動時報org.springframework.web.context.ContextLoaderListener錯誤解決方案
lean handler 轉載 現象 tail size enc fault new 問題現象:新從svn上檢出maven的項目maven+spring+springmvc項目在Tomcat啟動時,報如下錯誤。 嚴重: Error configuring appl
js製作CSV檔案下載功能時,由於值中含有json字串導致匯出格式錯誤解決方法
問題描述: 由於做的是真分頁,所以下載的時候不用在查詢資料庫,因而直接用的是js製作CSV檔案下載功能,但是由於值中含有json字串導致匯出格式錯誤。格式錯誤體現在json字串被拆分,佔用了多個單元格。 解決方法: 根據CSV檔案識別單元格的方式,用雙引號括起來的內容被
pip升級時遇到的錯誤解決方案
原來安裝的pip為9.0版的,後來安裝flask時發現報錯誤,提示需要升級至18.0版。 屢試不成功,最後把根目錄下pip的安裝檔案給全delete了。 但是執行還是出現問題,拒絕訪問。最後百度,發現是許可權問題。以下為管理員許可權登入cmd後的命令。 結果果斷升級成功
linux遠端拷貝檔案方法及not a regular file 錯誤解決方案
操作步驟: 1、搭建區域網:參考以下文章中網路配置部分:http://dblab.xmu.edu.cn/blog/install-hadoop-cluster/ 2、搭建好區域網後,可以使用scp命令完成遠端檔案拷貝操作 命令格式: scp [引數] [原路徑] [目標路
Linux PC和ARM版的QT環境設定及到ARM移植&常見錯誤解決方法
* *********安裝前,系統更新,能夠減少未知情況出現 1 PC版本 http://blog.csdn.net/chchchdx123/article/details/6911267 在終端中輸入:sudo apt-get install qt4-dev-t
SQLyog連線MySQL8.0及以上版本出現2058錯誤解決方案
重新安裝系統後安裝了MySQL 8.0版本 下載sqlyog工具 連線 mysql 時 配置新連線報錯:錯誤號碼 2058,通過分析錯誤原因,猜測是 mysql 密碼加密方法變了。 解決方法:windows 下cmd 登入 mysql -u root -p 登入你的 my
配置maven專案pom.xml出現錯誤解決程式碼步驟
在一開始建立maven專案的時候,pom.xml一直報錯。新增以下這段程式碼即可解決,同時,程式碼必須是放在其他的配置開頭: <build> <sourceDirector