Java 避免jspservlet映射中的无休止循环
我有这个问题,最近我读到了关于Arquit体系结构的文章,它非常有意义,所以我想实现一个RESTful web应用程序 现在,我遵循的是,这意味着所有的URL映射都指向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
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