2011-10-06 104 views
2

我正在開發繼承的jsp/java ee應用程序,我想向我的應用程序介紹Guice IoC容器。但是,我發現了一些障礙。如果有多個使用不同url的路由到單個servlet,我無法將web.xml條目轉換爲guice註冊。問題在於init參數。使用guice servlets將請求路由到匹配頁面

下面是我的web.xml一部分摘錄:

這一個是無關的問題,但它是我們如何使用初始化參數很好的例子。基本上,它將系統中不同角色的用戶映射到適當的頁面。

<!-- LIST INTERNSHIPS SERVLET --> 
<servlet> 
    <servlet-name>ListInternships</servlet-name> 
    <servlet-class>pl.poznan.put.ims.controllers.ListInternships</servlet-class> 
    <init-param> 
     <param-name>CoordinatorPage</param-name> 
     <param-value>WEB-INF/pages/coordinator/listinternships.jsp</param-value> 
    </init-param> 
    <init-param> 
     <param-name>MentorPage</param-name> 
     <param-value>WEB-INF/pages/mentor/listinternships.jsp</param-value> 
    </init-param> 
    <init-param> 
     <param-name>AdministratorPage</param-name> 
     <param-value>WEB-INF/pages/administrator/listinternships.jsp</param-value> 
    </init-param> 
    <init-param> 
     <param-name>AllowedRoles</param-name> 
     <param-value>Coordinator, Mentor, Administrator</param-value> 
    </init-param> 
</servlet> 
<servlet-mapping> 
    <servlet-name>ListInternships</servlet-name> 
    <url-pattern>/internships</url-pattern> 
</servlet-mapping> 

這兩個都是麻煩的:

<!-- CHANGE PASSWORD SERVLET --> 
<servlet> 
    <servlet-name>ChangePassword</servlet-name> 
    <servlet-class>myapp.controllers.ContextForwarder</servlet-class> 
    <init-param> 
     <param-name>SharedPage</param-name> 
     <param-value>WEB-INF/pages/shared/password.jsp</param-value> 
    </init-param> 
    <init-param> 
     <param-name>AllowedRoles</param-name> 
     <param-value>*</param-value> 
    </init-param> 
</servlet> 
<servlet-mapping> 
    <servlet-name>ChangePassword</servlet-name> 
    <url-pattern>/changepassword</url-pattern> 
</servlet-mapping> 

<!-- HELP SERVLET --> 
<servlet> 
    <servlet-name>Help</servlet-name> 
    <servlet-class>myapp.controllers.ContextForwarder</servlet-class> 
    <init-param> 
     <param-name>SharedPage</param-name> 
     <param-value>WEB-INF/pages/help/help.jsp</param-value> 
    </init-param> 
    <init-param> 
     <param-name>AllowedRoles</param-name> 
     <param-value>*</param-value> 
    </init-param> 
</servlet> 
<servlet-mapping> 
    <servlet-name>Help</servlet-name> 
    <url-pattern>/help</url-pattern> 
</servlet-mapping> 

這裏是我的servlet:

@Singleton 
public class ContextForwarder extends HttpServlet { 
    private static final long serialVersionUID = 1L; 
    private final IUserDao dao; 

    @Inject 
    public ContextForwarder(IUserDao dao) { 
     this.dao = dao; 
    } 

    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException { 

      //trying to get rid of statics, using Ioc 
      Validator.checkUserLoggedIn (request); 
      Validator.checkUserAuthorized(this, request); 

      User currentUser  = UserManager.getCurrentUser(request); 
      //pick matching page for user 
      String userViewPage  = ServletUtils.getUserURL(this, currentUser, "Page"); 


      try { 
        dao.openSession(); 
        dao.beginTransaction(); 
        currentUser = UserManager.reloadCurrentUser(request, dao); 

        ServletUtils.forward(request, response, userViewPage); 
        dao.commit(); 
      } 
      catch(ServletException e) { 
        dao.rollback(); 
        throw e; 
      } 
      catch(Exception e) { 
        dao.rollback(); 
        throw new ServletException(e); 
      } 
      finally { 
        dao.closeSession(); 
      } 
    } 
} 

public class ServletUtils { 
    public static void forward(HttpServletRequest request, HttpServletResponse  response, String location) 
      throws ServletException, IOException { 
      RequestDispatcher view = request 
        .getRequestDispatcher(response.encodeRedirectURL(location)); 

      view.forward(request, response); 
    } 


    public static String getUserParameter(GenericServlet servlet, User user, String suffix) { 
      return servlet.getInitParameter(user.getRoles() + suffix); 
    } 

    public static String getUserURL(GenericServlet servlet, User user, String suffix) 
      throws ResourceNotFoundException { 
      String URL = getUserParameter(servlet, user, suffix); 

      if(URL == null) { 
        URL = servlet.getInitParameter("Shared" + suffix); 
        if(URL == null) 
          throw new ResourceNotFoundException(suffix); 
      } 

      return URL; 
    } 

    public static void redirect(HttpServletRequest request, HttpServletResponse response, String location) 
      throws ServletException, IOException { 
      response.sendRedirect(response.encodeRedirectURL(location)); 
    } 
} 

當我嘗試把它翻譯成吉斯(然後註冊該模塊):

public class MyServletModule extends ServletModule 
{ 

    @Override 
protected void configureServlets() { 
    configureHelp(); 
    configurePassword(); 
} 

    private void configureHelp() 
    { 
    Map<String, String> params = new HashMap<String, String>(); 
    params.put("SharedPage", "WEB-INF/pages/shared/help.jsp"); 
    params.put("AllowedRoles", "*"); 

    serve("/help").with(ContextForwarder.class, params); 
    } 

    private void configurePassword() 
    { 
    Map<String, String> params = new HashMap<String, String>(); 
    params.put("SharedPage", "WEB-INF/pages/shared/password.jsp"); 
    params.put("AllowedRoles", "*"); 

    // it's routing correctly to servlet, but it uses params from first registration, 
    // so that routing to jsp page is incorrect 
    serve("/changepassword").with(ContextForwarder.class, params); 
    }  
}  

問題是t帽子guice使用第一個註冊方法的init參數創建ContextForwarder servlet作爲單例,然後不管第一次註冊時的參數是什麼請求url。考慮到當前的用戶角色,是否有其他解決方案將用戶路由到不同的站點?是否可以使用兩種不同的配置來配置相同的servlet類?

回答

3

我找到了解決辦法,但是我對此並不完全滿意。我發現,在沒有guice的解決方案中,web容器(tomcat)使用相同的servlet類創建兩個單獨的servlet並注入不同的初始參數。 Guice默認將servlet限制爲單例,所以要從web.xml解決方案中複製默認行爲,我需要找到一種方法來創建同一個類的兩個實例,並使用不同的參數註冊兩次。我通過創建兩個子類到我的servlet類來解決這個問題,兩個子類都是空的,然後我用不同的參數註冊它們。

該解決方案有效,但它涉及創建我不滿意的空體子類。當我有兩個子類時,這不是問題,但其中更多的代碼變得非常麻煩。

+0

這是正確的路要走。 Servlets應該是單身人士 - Guice是對的。 您可能已經發現,您之前的配置在某些servlet容器中導致了單個實例,因爲據我所知,規範在這種情況下的實例數量不明確。 – mjaggard