2011-10-06 2 views
2

상속 된 jsp/java ee 애플리케이션을 개발 중이며 Guice IoC 컨테이너를 내 애플리케이션에 소개하고 싶습니다. 그러나 몇 가지 장애물을 발견했습니다. 다른 URL을 사용하는 단일 서블릿으로 라우팅하는 경로가 여러 개있는 경우 web.xml 항목을 guice 등록으로 변환 할 수 없습니다. init 매개 변수에 문제가 있습니다.guice 서블릿을 사용하여 일치하는 페이지로 라우팅 요청

이 하나의 문제와 관련이 있지만, 우리는 초기화 매개 변수를 사용하는 방법이 좋은 예이다 : 여기

내 web.xml의 일부를 추출합니다. 기본적으로 시스템의 다른 역할을 가진 사용자를 적절한 페이지에 매핑합니다. 내가 guice로 번역 (다음이 모듈을 등록) 할 때

@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)); 
    } 
} 

: 여기

<!-- 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> 

내 서블릿입니다 :

그 두

<!-- 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> 

는 귀찮은 것들

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입니다. hat guice는 ContextForwarder 서블릿을 첫 번째 등록 된 메소드의 init 매개 변수가있는 싱글 톤으로 작성한 다음 요청 URL에 관계없이 첫 번째 등록의 매개 변수를 갖습니다. 현재 사용자 역할을 고려하여 다른 사이트로 사용자를 라우팅하는 다른 솔루션이 있습니까? 서로 다른 두 가지 구성으로 동일한 서블릿 클래스를 구성 할 수 있습니까?

답변

3

나는 해결책을 찾았지만, 나는 그것을 완전히 만족하지 않는다.. 웹 컨테이너 (tomcat)는 guice가없는 솔루션에서 동일한 서블릿 클래스를 사용하고 서로 다른 초기화 매개 변수를 주입하는 두 개의 별도 서블릿을 생성한다는 것을 알게되었습니다. Guice는 기본적으로 서블릿을 싱글 톤으로 제한합니다. 따라서 web.xml 솔루션에서 기본 비헤이비어를 복사하려면 같은 클래스의 인스턴스 두 개를 만들고 다른 매개 변수로 두 번 등록하는 방법을 찾아야했습니다. 나는 빈 몸체를 가진 서블릿 클래스에 두 개의 서브 클래스를 생성하여이를 해결했다. 그런 다음 서로 다른 매개 변수로 등록했다.

이 솔루션은 효과가 있지만 만족스럽지 않은 빈 몸체 하위 클래스를 만드는 것이 포함됩니다. 두 개의 하위 클래스가있을 때 문제가되지 않지만 코드가 많아지면 번거로워집니다.

+0

이것이 올바른 방법입니다. 서블릿은 싱글 톤으로 간주됩니다. Guice가 맞습니다. 내가 알 수있는 한,이 경우 인스턴스의 수에 대한 스펙이 명확하지 않기 때문에 이전 구성으로 인해 일부 서블릿 컨테이너에서 단일 인스턴스가 발생했을 수 있습니다. – mjaggard