【问题标题】:Routing request to matching pages using guice servlets使用 guice servlet 将请求路由到匹配页面
【发布时间】:2011-10-06 16:46:11
【问题描述】:

我正在开发继承的 jsp/java ee 应用程序,我想将 Guice IoC 容器引入我的应用程序。但是,我发现了一些障碍。如果有多个路由到使用不同 url 的单个 servlet,我无法将 web.xml 条目转换为 guice 注册。问题在于初始化参数。

以下是我的 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) );
    }
}

当我尝试将其翻译成 guice(然后注册此模块)时:

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 servlet 创建为具有来自第一个注册方法的 init 参数的单例,然后不管请求 url 具有来自第一次注册的参数。考虑到当前用户角色,是否有任何其他解决方案可以将用户路由到不同站点?是否可以用两种不同的配置来配置同一个 servlet 类?

【问题讨论】:

    标签: java jakarta-ee routes guice guice-servlet


    【解决方案1】:

    我找到了解决方案,但是 我对此并不完全满意。我发现,在没有 guice 的解决方案中,Web 容器(tomcat)使用相同的 servlet 类并注入不同的 init 参数创建两个单独的 servlet。默认情况下,Guice 将 servlet 限制为单例,因此要从 web.xml 解决方案中复制默认行为,我需要找到一种方法来创建同一类的两个实例并使用不同的参数对其进行两次注册。我通过为我的 servlet 类创建两个子类来解决这个问题,它们都是空的,然后我用不同的参数注册它们。

    此解决方案有效,但它涉及创建我不满意的空体子类。当我有两个子类时这不是问题,但是随着它们的更多,代码变得很麻烦。

    【讨论】:

    • 这是正确的方法。 Servlet 应该是单例的——Guice 是对的。您可能已经发现您之前的配置导致某些 servlet 容器中只有一个实例,因为据我所知,规范并不清楚这种情况下的实例数量。
    猜你喜欢
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-16
    • 1970-01-01
    • 1970-01-01
    • 2012-12-14
    相关资源
    最近更新 更多