Направление запроса на соответствующие страницы с помощью сервлетов-подсказок - PullRequest
2 голосов
/ 06 октября 2011

Я занимаюсь разработкой унаследованного приложения jsp / java ee и хочу представить контейнер Guice IoC для моего приложения. Однако я обнаружил некоторые препятствия. Я не могу перевести записи web.xml в обычные регистрации, если существует более одной маршрутизации на один сервлет с разными URL. Проблема с init-параметрами.

Вот некоторые выдержки из моего web.xml:

Это не связано с проблемой, но это хороший пример того, как мы используем параметры init. В основном он отображает пользователей с разными ролями в системах на соответствующие страницы.

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

Вот мой сервлет:

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

Проблема в том, что guice создает сервлет ContextForwarder в виде синглтона с параметрами init из первого зарегистрированного метода, а затем независимо от URL-адреса запроса он имеет параметры из первой регистрации. Есть ли другое решение для направления пользователя на другие сайты с учетом текущей роли пользователя? Можно ли настроить один и тот же класс сервлетов на две разные конфигурации?

1 Ответ

3 голосов
/ 08 октября 2011

Я нашел решение, однако Я не полностью удовлетворен им . Я обнаружил, что в решении без хитрости веб-контейнер (tomcat) создает два отдельных сервлета, используя один и тот же класс сервлетов и вводя разные параметры инициализации. Guice по умолчанию ограничивает сервлеты синглами, поэтому для копирования поведения по умолчанию из решения web.xml мне нужно было найти способ создать два экземпляра одного и того же класса и зарегистрировать его дважды с разными параметрами. Я решил это, создав два подкласса для моего класса сервлетов, оба с пустым телом, а затем зарегистрировал их с разными параметрами.

Это решение работает, но оно включает создание подклассов пустого тела, которые меня не устраивают. Это не проблема, когда у меня есть два подкласса, но с большим количеством из них код становится громоздким.

...