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">- 1
- 1
歷史代碼里處理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規(guī)范里的,所以使用到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.shtmlat 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)仔細查看源代碼后,發(fā)現不能處理的include指令代碼如下:
<!--#include virtual="/pages/test/intelFilter.shtml"-->經過對比調試Tomcat的代碼,發(fā)現是在7.0.58版本時,改變了處理URL的方法,關鍵的處理函數是
org.apache.catalina.core.ApplicationContext.getContext( String uri)在7.0.57版本前,Tomcat在處理處理像/pages/test/intelFilter.shtml這樣的路徑時,恰好循環(huán)處理了”/”字符,使得childContext等于StandardContext,最終由StandardContext處理了/pages/test/intelFilter.shtml的請求。
這個代碼實際上是錯誤的,不過恰好處理了include virtual的情況。
在7.0.58版本修改了處理uri的代碼,所以在升級Tomcat到7.0.59時出錯了。
7.0.57版的代碼:?
https://svn.apache.org/repos/asf/tomcat/tc7.0.x/tags/TOMCAT_7_0_57/java/org/apache/catalina/core/ApplicationContext.java
7.0.58的代碼:?
https://svn.apache.org/repos/asf/tomcat/tc7.0.x/tags/TOMCAT_7_0_58/java/org/apache/catalina/core/ApplicationContext.java
那么正確的處理辦法是怎樣的?
仔細查看Tomcat的SSI配置的說明文檔,發(fā)現有一個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,重新測試,發(fā)現已經可以正常處理”#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在起作用?
分類: JAVA 好文要頂 關注我 收藏該文 左正關注 - 29
粉絲 - 126 +加關注 0 0 ? 上一篇:配置tomcat讓shtml嵌套文件顯示
? 下一篇:IntelliJ IDEA部署tomcat時Edit Configuration無artifact選項
posted @ 2017-03-03 19:19 左正 閱讀(167) 評論(0) 編輯 收藏 刷新評論刷新頁面返回頂部 (評論功能已被禁用) 【推薦】超50萬VC++源碼: 大型工控、組態(tài)\仿真、建模CAD源碼2018!
【推薦】騰訊云新用戶域名搶購1元起,抓緊搶購
最新IT新聞:
· 阮一峰:加密貨幣的本質
· ofo被曝訂單較峰值跌六成 賬戶現金僅能支撐一個月
· 途牛宣布一億美元股票回購計劃及CTO任命
· 我們幫你劃了一份微信公開課PRO的重點
· iPhone 4S起死回生,可降級至iOS 6.1.3
? 更多新聞... 本文轉自左正博客園博客,原文鏈接:http://www.cnblogs.com/soundcode/p/6498147.html,如需轉載請自行聯(lián)系原作者
總結
以上是生活随笔為你收集整理的tomcat ssi配置及升级导致ssi include错误问题解决的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手势追踪,高通走完其VR一体机的最后一里
- 下一篇: jpa tutorials