【发布时间】:2011-08-05 03:53:28
【问题描述】:
我遇到了这个问题,最近我读到了REST 架构,它非常有意义,所以我想实现一个 RESTful Web 应用程序。
现在,我关注 Front Controller pattern,这意味着所有 URL 映射都转到 controller.java servlet,我按特定 URL 映射,而不是使用 /* 通配符,
控制器实现POST,GET,PUT,DELETE这四种HTTP方法,每个方法调用控制器service方法,我根据HttpServletRequest和pathInfo确定要执行的动作.
控制器.java
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
IAction action;
View view;
try {
action = ActionFactory.produceAction(req);
view = action.execute(req, resp);
switch (view.getDispatchMethod()) {
case REDIRECT:
resp.sendRedirect(resp.encodeURL(view.getResource()));
break;
case FORWARD:
req.getRequestDispatcher(view.getResource()).forward(req, resp);
break;
case INCLUDE:
req.getRequestDispatcher(view.getResource()).include(req,resp);
break;
default:
}
} catch (ActionFailedException uae) {
req.setAttribute("ActionName", "Action");
req.setAttribute("FailCause", uae.getMessage());
req.getRequestDispatcher(VIEW_FAIL.getResource()).forward(req, resp);
}
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.service(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.service(req, resp);
}
@Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.service(req, resp);
}
@Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.service(req, resp);
}
我在通过 URI /orders/* 加载特定订单时遇到了一个特定问题,它被映射到控制器 servlet,执行该操作并加载适当的顺序该操作返回一个 View.java 类
//ommited accessors and mutators for brevety.
public class View {
public enum DispatchMethod {
INCLUDE, FORWARD, REDIRECT
}
private DispatchMethod dispatchMethod;
private String resource;
public View(DispatchMethod dispatchMethod, String resource) {
this.dispatchMethod = dispatchMethod;
this.resource = resource;
}
}
然后根据返回视图的getDispatchMethod()调度请求。
现在,这里是触发循环的地方,我使用以下 URL,myapp/orders/78965 /orders/* 被映射到 controller.java 执行适当的操作,并通过 pathInfo() 返回的视图找到正确的顺序是new View(View.DispatchMethod.FORWARD,"order_details.jsp") 问题在于,使用三种可用的调度方法REDIRECT,FORWARD and INCLUDE 会在URL 上重新触发请求,依此类推,我永远无法到达呈现数据的order_details.jsp。
那么,您将如何避免循环,因为我想保留显示订单号的 URI,我使用 forward 方法,另外,我想使用 servlet,我听说过 UrlRewriteFilter也许在未来,但现在,由于我使用的是前端控制器模式,如何使用“Plain Vanilla”来完成,是否有必要在 /orders/ URI 中添加一个额外的 servlet ?
非常感谢任何帮助或见解。
编辑 1:
粘贴了控制器的源代码,一个非常基本的,我怀疑service方法调用servlet的所有覆盖do[Method]的方式触发了循环,它可以通过以下方式解决分裂他们。
【问题讨论】:
-
您在谈论 servlet,但症状表明您正在使用一个过滤器,该过滤器挂钩所有三种调度方法,而不是(默认)
REQUEST。还是我完全误解了你? -
我使用的唯一过滤器是身份验证过滤器,它是使用
/*应用的,但我不知道它是如何反复触发请求的,因为它只检查用户是否登录. -
好吧.. 我很乐意提供帮助,但您确实必须显示最低限度的必要代码 sn-p,它仅显示重现此确切问题的原始 Servlet API 类/方法,而不是您的其他人不知道的私有/本土 API。顺便问一下,这只是一个私人学习练习吗?如果是这样,那就别管我了,继续吧,如果不是,那么我建议采用现有的 API 而不是自行开发的 API,例如出色的 JAX-RS API。它也建立在 Servlet API 之上。另见vogella.de/articles/REST/article.html
-
嗨,@BalusC,谢谢你的回复,是的,这是一个学习练习。
-
可以肯定的是,在转发/包含期间
view.getResource()是否返回与此 servlet 的 URL 模式匹配的 URL?它不应该。您通常希望将这些 JSP 资源放在/WEB-INF文件夹中。
标签: java jsp rest servlets restful-url