1

我遇到了这个问题,最近我读到了REST 架构,它很有意义,所以我想实现一个 RESTful Web 应用程序。

现在,我遵循前端控制器模式,这意味着所有 URL 映射都转到controller.javaservlet,我按特定 URL 映射,而不是使用/*通配符,控制器实现四个 HTTP 方法POST, GET, PUT, DELETE, 每个方法调用控制器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 可能在未来,但是现在,由于我使用的是 Front Controller 模式,如何使用“Plain Vanilla”来完成,是否有必要在/orders/URI 中添加一个额外的 servlet?

任何帮助或见解都非常感谢。


编辑1:

粘贴了控制器的源代码,一个非常基本的源代码,我怀疑该service方法调用所有 servlet 覆盖do[Method]的方式是触发循环,并且可以通过拆分它们来解决。

4

1 回答 1

2

使用RESTEasyJersey等 JAX-RS 实现在 Java 中实现 RESTful HTTP 接口要容易得多。

使用前端控制器将请求分派到正确的资源是一种很好的方法,这正是这些 JAX-RS 框架所采用的方法。我担心你可能会通过编写一个定制的 URL 解析和调度机制来重新发明轮子,而这种机制可以是现成的。

JAX-RS 是一种公开资源的轻量级方式。通过使用几个简单的注释,您可以公开一个 REST 接口,而无需任何管道。例如:

public class Order {

    @GET
    @Path("/orders/{orderId}")
    @Produces("text/html")
    public void getOrder(@Context HttpServletResponse response,
                         @Context HttpServletRequest request,
                         @PathParam("orderId") String orderId) throws ServletException, IOException {

        // ... create view and add to request here

        request.getRequestDispatcher("orders.jsp").forward(request, response);

    }

}

您可以看到将此类附加到 URL 路径(使用@Path注释)是多么简单,以及使用@PathParam. 由于您获得了现成的所有管道/调度/解析,因此您可以专注于特定于您的域的应用程序位(例如订单包含的内容)。

于 2011-04-14T20:39:21.703 回答