【问题标题】:Java JSP/Servlet: controller servlet throwing the famous stack overflowJava JSP/Servlet:控制器 servlet 抛出著名的堆栈溢出
【发布时间】:2010-06-01 02:32:46
【问题描述】:

我已经阅读了几个文档,但我不明白:我知道我做错了什么,但我不明白是什么。我有一个完全动态生成的网站:几乎没有任何静态内容。

所以,为了理解 JSP/Servlet,我编写了自己的“前端控制器”来拦截每一个查询,它看起来像这样:

<servlet-mapping>
        <servlet-name>defaultservlet</servlet-name>
        <url-pattern>/*</url-pattern>
</servlet-mapping>

基本上我想要任何用户请求,例如:

  • example.org
  • example.org/bar
  • example.org/foo.html

通过我编写的默认 servlet。

servlet 然后检查 URI 并找到必须将请求分派到哪个 .jsp,然后在正确设置所有属性后执行:

RequestDispatcher dispatcher = getServletContext().getRequestDispatcher("/WEB-INF/jsp/index.jsp");
dispatcher.forward(req, resp);

当我使用 url 模式(在 web.xml 中)时,例如 *.html,一切正常。但是当我将其更改为/*(真正拦截所有内容)时,我进入了一个无限循环,它最终以... StackOverflow :)

当请求被分派时,URI ".../WEB-INF/jsp/index.jsp" 本身是否被 web.xml 过滤器匹配/ * 我设置的?

EDIT 显然,不,因为这是到 index.jsp 的精确映射,因此它绕过了 web.xml url-pattern。所以我仍然不明白如何进入那个无限循环。

如果我想使用 /* url-pattern 拦截所有内容但又能够调度/转发/,我应该怎么做?

我不是在这里询问规范/Javadocs:我真的对大局感到困惑,我需要一些关于可能发生的事情的解释。

难道我不应该拦截所有东西吗?

如果我可以拦截所有内容,关于转发/调度我应该注意什么?

【问题讨论】:

  • @leonbloy:哦,谢谢……我明白了。从 BalusC 的回答来看,使用“/*”进行 servlet 映射显然不是一个好主意:(
  • 请在此处转储完整的堆栈跟踪/类代码
  • @techzen:没必要。原因很明显。 url-pattern 是 /*。 servlet 一次又一次地将请求转发给它自己。 @Nooz:确实,当您想要转发和忘记时(​​即仅处理直接传入的请求),您想使用过滤器。默认情况下,servlet 拦截每个 请求(直接传入、转发、包含、错误)。过滤器可以通过 web.xml 中的 &lt;dispatcher&gt; 条目单独配置(默认为 REQUEST)。

标签: java jsp servlets


【解决方案1】:

不幸的是,Serlvet 规范不允许创建一个 servlet 映射来只匹配传入的请求,而不是转发。但是,这可以用于过滤器映射(默认情况下过滤器映射只匹配传入的请求)。

因此,使用单个 servlet 拦截所有内容的典型解决方案是使用 UrlRewriteFilter:

<filter>
    <filter-name>urlRewrite</filter-name>
    <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>urlRewrite</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<servlet>
    <servlet-name>application</servlet-name>
    <servlet-class>...</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>application</servlet-name>
    <url-pattern>/app/*</url-pattern>
</servlet-mapping>

/WEB-INF/urlrewrite.xml:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE urlrewrite
    PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN"
    "http://tuckey.org/res/dtds/urlrewrite3.0.dtd">

<urlrewrite default-match-type="wildcard">
    <rule>
        <from>/**</from>
        <to>/app/$1</to>
    </rule>
    <outbound-rule>
        <from>/app/**</from>
        <to>/$1</to>
    </outbound-rule>    
</urlrewrite>

这种方式还允许您从静态文件的/* 映射中指定例外。

【讨论】:

    【解决方案2】:

    尝试使用内置前端控制器模式的 struts。在那里你将有一个动作类,你可以在 struts-config 文件中定义转发,使用它可以轻松管理转发。

    阅读教程http://www.roseindia.net/struts/struts2/index.shtml。希望对您有所帮助。

    【讨论】:

    • 我不追求框架。如我的问题所述,我正在尝试学习 JSP/Servlet。另外,我觉得 Struts 有点像上世纪的技术,从零开始的人应该投资 Spring MVC 等框架:)
    • 尝试使用 * 。 *(不带空格)在您的 url 模式中。
    • 此外,roseindia.net 是一个horrible 来源。它只教坏做法。不要将该网站用作学习资源。
    猜你喜欢
    • 2013-06-06
    • 2021-09-02
    • 1970-01-01
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-18
    • 2018-11-13
    相关资源
    最近更新 更多