2011-04-14 189 views
1

我有這個問題,最近我閱讀了關於REST的一個架構,它具有完美的意義,所以我想實現一個RESTful Web應用程序。避免JSP servlet映射中的無限循環

現在,我正在關注的Front Controller pattern這意味着所有的URL映射到的controller.java的servlet,我映射通過特定的網址,而不會使用/*通配符, 控制器實現了四個HTTP方法POSTGET,PUT,DELETE,每種方法調用控制器service方法,在那裏我根據HttpServletRequestpathInfo確定要執行的動作。 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,該執行的動作和我加載適當的順序從動作返回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()調度。

現在,這裏是循環被觸發,我用下面的網址,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]被觸發循環和它可以通過分割它們來解決。

+0

你正在談論servlet,但是症狀表明你正在使用一個過濾器來掛接所有三種調度方法,而不是(默認)'REQUEST'。或者我完全誤解了你? – BalusC 2011-04-14 04:22:35

+0

我唯一使用的過濾器是一個認證過濾器,它是使用'/ *'應用的indee,但是我不知道如何觸發請求一遍又一遍,因爲它只檢查用戶是否登錄。 – Triztian 2011-04-14 05:58:59

+0

嗯..我我很樂意提供幫助,但是您必須展示一個最低限度必要的代碼片段,它只顯示重現此問題的原始Servlet API類/方法,而不是您沒有其他人瞭解的私有/本地生成的API。順便說一句,這只是一個私人學習練習?如果是這樣,那麼我就不要那麼着急,如果不是的話,我建議採用一個現有的API,而不是像一個美妙的JAX-RS API那樣使用現有的API。它也構建在Servlet API之上。另見http://www.vogella.de/articles/REST/article.html – BalusC 2011-04-14 16:10:05

回答

2

使用JAX-RS實現(如RESTEasyJersey)實現Java中的RESTful HTTP接口要容易得多。

使用Front Controller將請求分發到正確的資源是一種好方法,這正是這些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解析值。由於您可以獲得所有現成的配置/調度/解析,因此您可以專注於您的應用程序中特定於您的域的位(例如訂單包含的內容)。

+0

這是使用Jersey實現還是隻使用JAX-RS API,因爲所有我的搜索JAX-RS指向澤西島,也許你可以清除它的一些要點,JAX-RS是獨立的還是我必須使用Jersey實現? – Triztian 2011-04-14 22:38:39

+0

JAX-RS是一個規範,是JEE的一部分。您可以將JAX-RS視爲一組沒有實現的接口/註釋。要創建應用程序,您需要選擇JAX-RS的實現。 RESTEasy是一個實現(由JBoss擁有),Jersey是另一個實現(Jersey是參考實現,可在java.net上獲得)。還有其他不太受歡迎的實現,如Apache CXF和Restlet。您正在部署哪個容器(以及哪個版本)?您的容器可能已包含您可以使用的JAX-RS實施。 – joelittlejohn 2011-04-14 23:09:18

+0

我正在部署到apache-tomcat 6.0.26,我讀過一些比較,雖然我恨澤西島的名字,但它似乎比RESTlet(它有一個很酷的名字)簡單得多,謹慎分享任何經驗? – Triztian 2011-04-14 23:21:23