使用java servlet实现前端控制器的最佳实践

时间:2009-07-27 19:30:40

标签: design-patterns jsp servlets java-ee front-controller

假设我们有一些具有下一个结构的项目:

web
  articles
    main.jsp
    sidearts.jsp
    central.jsp
  forum
    main.jsp
  css
  js
  WEB-INF
    web.xml

请注意,此时我们还没有前置控制器。

在部署了一些方面(让它为'asdf')后,我们可以使用下一个网址访问我们的网页:

http://localhost:8080/asdf/articles/main.jsp
http://localhost:8080/asdf/forum/main.jsp

and so on..

main.jsp生成一些html并包含sidearts.jsp(通过jstl c:import或任何其他方式)

添加前置控制器后会发生什么?

假设我们有servlet ArticlesController,它负责调度
一些请求和下一个映射:

<servlet>
  <servlet-name>ArtsController</servlet-name>
  <servlet-class>org.forstackoverflow.ArticlesController</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>ArtsController</servlet-name>
  <url-pattern>/articles/*</url-pattern>
</servlet-mapping>

现在,当我们请求URL http://localhost:8080/asdf/articles/main时,ArticlesController处理此请求并尝试包含articles / main.jsp。此时无限循环开始,因为/ articles / *映射到ArtsController。

所述问题的正确解决方案是什么?

我的变种是:

1)为所有jsp文件制作映射(我不认为它是可加入的)

2)更改目录名称(articles-&gt; arts);但后来我们得到了很多新的URL(比如http://localhost:8080/asdf/arts/main.jsp),我认为它可能是bug的来源。

2 个答案:

答案 0 :(得分:1)

您可能会将servlet与过滤器混淆。使用servlet,将没有无限循环。您的JSP页面将始终通过精确模式进行映射,无论是显式模式(如果它们是预编译的)还是隐式模式(如果未预编译,则通过相对于webapp root的JSP文件路径)。这意味着你的“articles / main.jsp”实际上是一个具有以下映射的servlet:

<servlet-mapping>
  <servlet-name>name_does_not_matter_here</servlet-name>
  <url-pattern>/articles/main.jsp</url-pattern>
</servlet-mapping>

ArticlesController servlet映射到/articles/*,将发生以下情况:

http://localhost:8080/asdf/articles/main URL将由您的servlet处理,因为它与JSP的模式不匹配。但是,匹配两个模式的http://localhost:8080/asdf/articles/main.jsp URL将映射到JSP页面而不是servlet,因为servlet容器将始终更喜欢与通配符匹配完全匹配(这是J2EE规范的一部分)

答案 1 :(得分:0)

由于您使用的是MVC,因此您应该让客户端(即浏览器)访问视图,在这种情况下是jsp。在对其执行操作时,应从视图中调用控制器servlet。在控制器中处理操作后,您将重定向到下一个视图(可能与启动操作的视图相同。)

使servlet url-pattern匹配到一个真实的目录,因为它告诉容器选择servlet而不是该目录的默认页面。