使用 url 模式“/*"的 servlet 映射中的 StackOverflowError [英] StackOverflowError in servlet mapping with url-pattern "/*"
问题描述
我有一组 JSP 页面,我想隐藏 .jsp 扩展名(经过一些研究,它似乎对 SEO 有好处).
I have a set of JSP pages and I want to hide the .jsp extension (after a bit of research it seems it's good for SEO).
我遇到的一个解决方案如下:
One solution I came across was the following:
<servlet>
<servlet-name>mypage</servlet-name>
<jsp-file>/some-page.jsp</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>mypage</servlet-name>
<url-pattern>/some-page</url-pattern>
</servlet-mapping>
虽然这有效,但我相信我必须为我网站上的每个 jsp 页面设置此映射.
And while this works, I believe I have to set up this mapping for every jsp page on my site.
我在这里发布了另一个解决方案(简单友好的 URL):隐藏功能JSP/Servlet
I came across another solution posted here (Easy friendly URL's): Hidden features of JSP/Servlet
... 它使用一个简单的 servlet 来转发请求.在我的 web.xml 中,我有以下内容并且工作正常:
... which uses a simple servlet to forward the request. In my web.xml I have the following and it works fine:
<servlet>
<servlet-name>MyServletName</servlet-name>
<servlet-class>myservlets.PrettyUrlServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServletName</servlet-name>
<url-pattern>/myservlet/*</url-pattern>
</servlet-mapping>
现在的问题是我不想点击 URL:www.mydomain.com/myservlet/some-page
Now the problem is I don't want to hit the URL: www.mydomain.com/myservlet/some-page
我想使用网址:www.mydomain.com/some-page
I want to use the URL: www.mydomain.com/some-page
所以我将 url-pattern 更改为/*"
So I changed the url-pattern to "/*"
<servlet>
<servlet-name>MyServletName</servlet-name>
<servlet-class>myservlets.PrettyUrlServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServletName</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
但这会导致无限循环:
Exception in thread "http-bio-8080-exec-1" java.lang.StackOverflowError
at org.apache.catalina.core.ApplicationHttpRequest.getAttribute(ApplicationHttpRequest.java:219)
at org.apache.catalina.core.ApplicationHttpRequest.getAttribute(ApplicationHttpRequest.java:228)
.
.
at org.apache.catalina.core.ApplicationHttpRequest.getAttribute(ApplicationHttpRequest.java:228)
at org.apache.catalina.core.ApplicationHttpRequest.getAttribute(ApplicationHttpRequest.java:228)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:379)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:329)
at myservlets.PrettyUrlServlet.doGet(PrettyUrlServlet.java:22)
我不知道如何解决.有什么想法吗?
Which I'm not sure how to fix. Any ideas?
推荐答案
映射在 /*
上的 servlet 也将在 RequestDispatcher#forward()
调用上运行.因此,如果您在该 servlet 中执行转发,它每次都会在无限循环中调用自己.这解释了 StackOverflowError
.
A servlet which is mapped on /*
will also run on RequestDispatcher#forward()
calls. So if you're performing a forward in that servlet, it would call itself everytime in an infinite loop. That explains the StackOverflowError
.
毕竟,您根本不应该将 /*
用于 servlet.它只对 servlet 过滤器有意义.将 servlet 映射放回更具体的 URL 模式,并在 /*
上创建过滤器,以便在必要时转发到所需的 servlet.您当然不想让 servlet 来处理例如图像/CSS/JS 文件.假设它们都放在 /resources
文件夹中,并且您的前端控制器映射在 /myservlet/*
上,然后在 doFilter() 中执行以下工作代码>:
After all, you should not be using /*
for servlets at all. It only makes sense on servlet filters. Put the servlet mapping back on a more specific URL pattern and create a filter on /*
which forwards to the desired servlet when necessary. You of course don't want to have the servlet to handle for example images/CSS/JS files. Assuming that they're all placed in /resources
folder and that your front controller is mapped on /myservlet/*
, then do the following job in doFilter()
:
HttpServletRequest req = (HttpServletRequest) request;
String path = req.getRequestURI().substring(req.getContextPath().length());
if (path.startsWith("/resources/")) {
// Just let container's default servlet do its job.
chain.doFilter(request, response);
}
else {
// Delegate to your front controller.
request.getRequestDispatcher("/myservlet" + path).forward(request, response);
}
另见:
- Tomcat 中的 URL 映射到 FrontController servlet
这篇关于使用 url 模式“/*"的 servlet 映射中的 StackOverflowError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!