使用ControllerServlet是JavaEE6的良好实践吗?

使用ControllerServlet是JavaEE6的良好实践吗?,java,jakarta-ee,Java,Jakarta Ee,我在Oracle提供的针对JavaEE6的affablebean教程中了解了ControllerServlet的用法 它以一个servlet处理许多不同的URL请求而结束,如下所示: @WebServlet(name = "ControllerServlet", loadOnStartup = 1, urlPatterns = { "/category", "/addToCart", "/viewCart", "/u

我在Oracle提供的针对JavaEE6的affablebean教程中了解了ControllerServlet的用法

它以一个servlet处理许多不同的URL请求而结束,如下所示:

@WebServlet(name = "ControllerServlet",
    loadOnStartup = 1,
    urlPatterns = {
        "/category",
        "/addToCart",
        "/viewCart",
        "/updateCart",
        "/checkout",
        "/purchase",
        "/chooseLanguage"})

public class ControllerServlet extends HttpServlet {

    @EJB
    private CategoryFacade categoryFacade;
    @EJB
    private OrderManager orderManager;
    @Override
    public void init() throws ServletException {

        // store category list in servlet context
        getServletContext().setAttribute("categories", categoryFacade.findAll());
    }

    /**
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {

        String userPath = request.getServletPath();

        // if category page is requested
        if (userPath.equals("/category")) {
            // get categoryId from request
            String categoryId = request.getQueryString();

            if (categoryId != null) {
                // get selected category
                Category selectedCategory = categoryFacade.find(Short.parseShort(categoryId));

                 // place selected category in request scope
                 request.setAttribute("selectedCategory", selectedCategory);
                // get all products for selected category
                Collection<Product> categoryProducts = selectedCategory.getProductCollection(); 

                // place category products in request scope
                request.setAttribute("categoryProducts", categoryProducts);
            }

        // if cart page is requested
        } else if (userPath.equals("/viewCart")) {
            // TODO: Implement cart page request

            userPath = "/cart";

        // if checkout page is requested
        } else if (userPath.equals("/checkout")) {
            // TODO: Implement checkout page request

        // if user switches language
        } else if (userPath.equals("/chooseLanguage")) {
            // TODO: Implement language request

        }

        // use RequestDispatcher to forward request internally
        String url = "/WEB-INF/view" + userPath + ".jsp";

        try {
            System.out.println("Redirecting to : "+url);
            request.getRequestDispatcher(url).forward(request, response);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
我想知道这对于JavaEE项目来说是否是一个好的实践?我正在考虑采用JavaEE作为一个项目的框架,该项目涉及一个小的程序员团队。我认为这个ControllerServlet鼓励他们在其中加入很多业务逻辑。这门课预计会持续很长时间,有很多if/else if。。。将来


那么,对于在大型项目中工作的这样一个ControllerServlet,您有什么建议呢?

您正确地认为,如果您正在处理许多不同的操作,controller servlet将很快变得难以管理。按照您所勾勒出的天真方法,您将得到一大堆ifcase语句

典型的解决方案是前端控制器模式,它将url映射分派到实际处理请求的其他代码。有许多相对简单的解决方案可以做到这一点(有人提到了命令模式),它是大多数web框架的关键部分。我可能不会在2016年编写自己的前端控制器。在支持基于注释的servlet的情况下,我会考虑在每个servlet的一个动作周围构造一个非常简单的应用程序(如微服务);根据需要处理尽可能多的http方法:DELETE、PUT、GET

但是,您可能还需要其他功能,例如模板、可重用的UI组件、奇特的url参数处理、对象到json映射(以及相反的)、子资源映射、内容协商、授权等,考虑可以应用于问题的众多java EE技术之一(JAX-RS、JSF、JSR 371)和每个.</P >的更多实现。 如果你公开一个api,我会考虑一个JAX-RS实现,比如jersey,用于某种类型的应用程序,可能就足够了:可能是一个单页web应用程序,通过ajax调用与后端通信。你可以使用nginx For apache为静态内容提供服务。对于成熟的框架,您可以选择实现JSF标准的基于组件的方法,也可以选择实现mvc1(JSR371)规范的基于操作的方法。您可以在这里了解不同之处:


您提到了在JSF和SpringMVC之间进行选择,前者是基于组件的,后者是基于操作的。目前只有一个JSR371的实现,Ozark,参考。如果这种区别对您的选择很重要,那么您可能会因为缺少JSR371实现而受到阻碍。但在我看来,基于行动的方法确实是未来。

也许。请注意,这个控制器正在映射相关的行为。仅仅因为控制器servlet可以处理许多请求并不会使它太大。Restlets项目使用此模型,非常受欢迎。您也可以链接有问题的教程-如果有详细说明,您可能有兴趣阅读其基本原理。另外:这里没有实际实现的业务逻辑。这将出现在EJB中。业务逻辑!=servlet映射策略。在任何规模的项目上进行映射,这似乎是一个糟糕的想法;你是否需要一个“框架”取决于你实际上在做什么。如果您所做的只是将JSON转储到API使用者,那么只需要简单的映射和序列化。现代JEE对于许多项目来说已经足够了。(我不会使用它,但那只是我自己。)那么你不认为servlet/ejb:s是为这个“设计”的,尤其是新的?我想我不同意这一点。我只是在看发布的示例代码。您需要将这些url端点分派到其他代码。也许ejb路由提供了一种很好的方法来实现这一点。“对我来说,这似乎是一个沉重的负担”。@RobertMoskal是的,设置多个URL到同一个servlet的方式是不可靠的。但是JEE框架已经通过相同的注释机制处理rational映射。仅仅因为你可以做错事并不意味着你必须做错事,也不意味着它不适合现代开发。我已经修改了我的回答,以便更清楚地表明,我的批评只是关于实现你自己的前端控制器,用一个servlet处理许多不同的操作。