使用Java EE / Wildfly创建单页应用程序:服务器端配置。

5

我希望在客户端使用AngularJS,在服务器端使用Java EE编写单页面应用程序。如果我理解正确,前端的想法是创建一个默认页面(我们将其称为index.html)并实现路由以交换此默认页面的部分内容。因此,每次请求都会加载默认页面,并且路由逻辑会根据上下文路径替换其部分内容:

<!-- index.html -->
<html>
    <body>
        <!-- this block is replaced depending on context -->
        <div ng-view></div>
    </body>
</html>

<!-- page one -->
<div>
    <h1>Page One</h1>
    <a href="/specific">Some specific stuff</a>
</div>

<!-- page two -->
<div>
    <h1>Page Two</h1>
</div>

现在,路由逻辑可能如下:

angular.module('myApp', [])
    .config(['$routeProvider', function ($routeProvider) {
        $routeProvider
            .when('/', {templateUrl: 'pages/pageOne.html'})
            .when('/someSpecific', {templateUrl: 'pageTwo.html'})
            .otherwise({redirectTo: '/'});
    }
]);

问题是,我该如何将此与Java EE和Wildfly服务器实例配对?如果我仅声明index.html为欢迎页并且不做其他任何操作,则直接调用,例如http:// website.org/someSpecificContext将失败,因为没有页面映射到路径(也不应该有),因此不会加载任何页面和Angular代码。如果我通过servlet过滤器从每个可能的子路径重定向到index.html,则路径信息将丢失,因此每个调用都将结束在索引页面。也许这是一个愚蠢的新手问题,但我真的被卡住了,并且会感激任何帮助。

你不会重定向,而是始终提供index.html ...考虑虚拟目录 - charlietfl
charlieftl,你能否告诉我关于服务器方面的这个话题?是服务器还是Java EE应用程序需要预先配置,如何进行配置? - hoefling
我对Java EE一无所知...不过谷歌搜索似乎显示了很多结果。目前为止,您没有使用html5Mode,因此您所有的Angular路径都会有一个#,并且不会对服务器产生任何影响。只有在使用html5Mode并且使用漂亮的URL而没有#时,您才需要配置服务器。以任何您想要的方式提供模板即可。 - charlietfl
我已经在使用html5mode,为了代码简洁性,我没有包含它。我将更新问题,以减少对AngularJS主题的关注。 - hoefling
2个回答

8
我个人使用undertow rewrite handler来实现这个功能。不幸的是,关于此功能的文档很少。您可以在这里这里找到信息。您需要基本上重写那些只有Angular知道的html 5 urls,但是当Angular请求后端数据时,您必须使用服务器端REST组件进行响应。我的REST资源位于/api根路径下。这是要放置在WEB-INF文件夹中的undertow-handlers.conf文件的示例:
regex['(.*/order/?.*?$)'] and not regex['(.*/api.*)'] -> rewrite['/index.html']
regex['(.*/billing/?.*?$)'] and not regex['(.*/api.*)'] -> rewrite['/index.html']

现在这才是我期望的答案。我知道应该有利用现有解决方案而不是重复造轮子的可能性。谢谢,我会在下周一尝试并报告结果。 - hoefling
是的,我使用REST将数据从服务器传输到客户端,并且理想情况下,我只会在服务器端实现REST程序,可能还有一些安全逻辑,但这就是全部,其余的都应该由Angular丰富的客户端处理。这就是为什么我不喜欢自己的解决方案,因为它会向服务器添加不必要的代码,如果您的解决方案运行良好,我会坚持使用它。 - hoefling
您的解决方案具有可移植性,可以在Java EE服务器上使用 :-). 然而,Undertow处理程序提供了非常灵活的解决方案。您可以使用不同类型的处理程序,例如设置HTTP响应头、状态等。 - Franck
1
这是我想出来的一个更短的规则,适用于 Undertow 12.0 并匹配所有非 API 目录:not file and not path-prefix('api') -> rewrite('/index.html') - DustInComp

0

好的,这是我的处理方式。这是与服务器无关的,您只需要更改Java EE项目中的文件:

  • 将所有文件放置在适当的目录中:

    / (项目源根目录)
    |
     -> js/
     -> css/
     -> webpages/
     -> 等等
    
  • 实现一个新的 javax.servlet.Filter

    public class FilterAccess implements Filter {
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            if (!(request instanceof HttpServletRequest)) {
                return;
            }
            HttpServletRequest req = (HttpServletRequest) request;
    
            if (isAllowed(req)) {
                chain.doFilter(request, response);
            } else { // 将每个其他请求转发到 index 页面
                req.getRequestDispatcher("/pages/index.html").forward(request, response);
            }
        }
    
        private boolean isAllowed(HttpServletRequest req) {
            List<String> allowed = Arrays.asList("/webpages", "/js", "/css",...);
            for (String path : allowed) {
                if (req.getServletPath().startsWith(path)) {
                    return true;
                }
            }
            return false;
        }
    }
    
  • web.xml 文件中进行绑定:

    <filter>
        <filter-name>FilterAccess</filter-name>
        <filter-class>package.for.FilterAccess</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>FilterAccess</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    

基本上,这个想法是将每个请求资源的请求转发到主页,如果该资源不在允许的目录之一。您还可以根据需要重新实现isAllowed函数,例如检查请求的URL是否以.js结尾以允许JavaScript文件等。此外,代码不是很干净,可以将允许的路径声明为常量,甚至将它们移动到外部资源文件中等,但无论如何,您都明白了;-)

虽然我还不知道在使用Java EE构建单页面应用程序时是否采用了正确的方法,但我暂时不接受自己的答案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接