专栏名称: ImportNew
伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等。
目录
相关文章推荐
芋道源码  ·  1.8k ... ·  7 小时前  
芋道源码  ·  今年金三银四的实感。。 ·  2 天前  
芋道源码  ·  DeepSeek,又杀疯了! ·  3 天前  
芋道源码  ·  自从系统引入 Disruptor 后,性能起飞! ·  4 天前  
51好读  ›  专栏  ›  ImportNew

tomcat ssi 配置及问题解决

ImportNew  · 公众号  · Java  · 2017-06-02 12:42

正文

(点击 上方公众号 ,可快速关注)


来源:hengyunabc ,

hengyunabc.github.io/tomcat-ssi-problem/

如有好文章投稿,请点击 → 这里了解详情


最近tomcat升级版本时,遇到了ssi解析的问题,记录下解决的过程,还有tomcat ssi配置的要点。


tomcat 配置SSI的两种方式


Tomcat有两种方式支持SSI:Servlet和Filter。


SSIServlet


通过Servlet,org.apache.catalina.ssi.SSIServlet,默认处理”*.shtml”的URL。


配置方式


修改tomcat的 conf/web.xml文件,去掉下面配置的注释:


ssi

org.apache.catalina.ssi.SSIServlet

buffered

1

debug

0

expires

666

isVirtualWebappRelative

false

4

ssi

*.shtml


SSIFilter


通过Filter,org.apache.catalina.ssi.SSIFilter,默认处理”*.shtml”的URL。


配置方式:


修改tomcat的 conf/web.xml文件,打开去掉下面配置的注释:


ssi

org.apache.catalina.ssi.SSIFilter

contentType

text/x-server-parsed-html(;.*)?

debug

0

expires

666

isVirtualWebappRelative

false

ssi

*.shtml


注意事项


注意:两种配置方式最好不要同时打开,除非很清楚是怎样配置的。


另外,在Tomcat的conf/context.xml里要配置privileged=”true”,否则有些SSI特性不能生效。



历史代码里处理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版本以上,例如:


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">


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指令代码如下:



经过对比调试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时出错了。


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


/**

* Return a ServletContext 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 RequestDispatcher 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);







请到「今天看啥」查看全文