Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 避免jspservlet映射中的无休止循环_Java_Jsp_Rest_Servlets_Restful Url - Fatal编程技术网

Java 避免jspservlet映射中的无休止循环

Java 避免jspservlet映射中的无休止循环,java,jsp,rest,servlets,restful-url,Java,Jsp,Rest,Servlets,Restful Url,我有这个问题,最近我读到了关于Arquit体系结构的文章,它非常有意义,所以我想实现一个RESTful web应用程序 现在,我遵循的是,这意味着所有的URL映射都指向controller.javaservlet,我通过特定的URL映射,而不是使用/*通配符, 控制器实现了四个HTTP方法POST,GET,PUT,DELETE,每个方法调用控制器service方法,然后我根据HttpServletRequest和pathInfo确定要执行的操作。 Controller.java @Overr

我有这个问题,最近我读到了关于Arquit体系结构的文章,它非常有意义,所以我想实现一个RESTful web应用程序

现在,我遵循的是,这意味着所有的URL映射都指向
controller.java
servlet,我通过特定的URL映射,而不是使用
/*
通配符, 控制器实现了四个HTTP方法
POST
GET
PUT
DELETE
,每个方法调用控制器
service
方法,然后我根据
HttpServletRequest
pathInfo
确定要执行的操作。 Controller.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,操作被执行,我加载了相应的顺序,操作返回了一个
视图.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()
找到正确的顺序返回的视图是
新视图(view.DispatchMethod.FORWARD),“order_details.jsp”)
问题在于,使用三种可用的分派方法
重定向、转发和包含
会在URL上重新触发请求,依此类推,我永远无法到达呈现数据的
order_details.jsp

那么,您将如何避免循环,因为我想保留显示订单号的URI,我使用forward方法,而且,我想使用servlets,我听说URLRewiteFilter可能在将来,但现在,如何使用“纯香草”呢“由于我使用的是前端控制器模式,是否需要在
/orders/
URI中添加一个额外的servlet

我们真诚地感谢您的任何帮助或见解


编辑1:


粘贴了控制器的源代码,这是一个非常基本的源代码,我怀疑
服务
方法调用所有重写的
do[method]的方式servlet的
正在触发循环,可以通过拆分它们来解决。

使用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
解析URL中的值有多么容易。既然你已经准备好了所有的管道/分派/解析功能,你就可以专注于你的应用程序中特定于你的域的部分(比如订单包含的内容)。

你说的是servlet,但症状表明你使用的过滤器钩住了所有三种分派方法,而不是(默认)
请求
。还是我完全误解了你?我使用的唯一过滤器是身份验证过滤器,它是使用
/*
独立应用的,但我不知道它是如何触发请求的,因为它只检查用户是否登录。。我很乐意提供帮助,但您确实需要显示一个最少的必要代码片段,它只显示原始的Servlet API类/方法,这些类/方法重现了这个确切的问题,而不是您的私有/自主开发的API,其他人都不知道。顺便问一下,这只是一个私人学习练习吗?如果是这样的话,那就别理我,继续吧,如果不是这样的话,我建议采用现有的API,而不是家庭成长的API,比如出色的JAX-RSAPI。它也构建在ServletAPI之上。另请参见您好,@BalusC,谢谢您的回复,是的,这是一个学习练习。当然,在转发/包含过程中执行
view.getResource()
是否返回与此servlet的URL模式匹配的URL?不应该。您通常希望将这些JSP资源放在
/WEB-INF
文件夹中。这是使用Jersey实现还是仅使用JAX-RS API,因为我对JAX-RS的所有搜索都指向Jersey,也许您可以清除其中的一些要点,JAX-RS是独立的还是我必须使用Jersey实现?JAX-RS是一个规范,是JEE的一部分。您可以将JAX-RS看作是一组没有实现的接口/注释。要创建应用程序,需要选择JAX-RS的实现。RESTEasy是一个实现(归JBoss所有),Jersey是另一个实现(Jersey是参考实现,可在java.net上获得)。还有其他不太流行的实现,如ApacheCXF和Restlet。您将部署到哪个容器(以及哪个版本)?您的容器可能已经包含了一个您可以使用的JAX-RS实现。我正在部署到apache tomcat 6.0.26,我读了一些比较,虽然我讨厌Jersey的名称,但它似乎比RESTlet(它有一个很酷的名称)简单得多,想分享一下经验吗?我推荐。它非常容易配置,特别是在像tomcat这样的简单servlet容器中。它也很成熟,有很多集成点。我只使用了Jersey的客户端API(这很好),但我认为它大致相同。Restlet已经存在很长时间了,它有自己的替代方法(非JAX-RS)来实现REST资源,我已经使用过。最近,它添加了一个JAX-RSCOM