简体   繁体   English

如何在eclipse中运行jetty中的多个webapps

[英]How to run multiple webapps in jetty in eclipse

I'm trying to setup a development environment for a gradle multi web-app aplication in eclipse. 我正在尝试在eclipse中为gradle多Web应用程序应用程序设置开发环境。 The application is deployed in production on jetty so thats what I'd like to use in development. 该应用程序部署在码头上的生产中,这就是我想在开发中使用的内容。 I'm having trouble getting eclipse to run all the webapps and be able to debug as well. 我无法让eclipse运行所有的webapps并且能够进行调试。

The solutions I've been able to find online use plugins which can only run single webapps. 我能够在网上找到的解决方案使用的插件只能运行单个webapps。 Or they run the webapps via gradle (gretty) in a server which then causes problems with debugging. 或者他们通过服务器中的gradle(gretty)运行webapps,然后导致调试问题。

My source is a multi project gradle app. 我的来源是一个多项目gradle应用程序。 It compiles properly, there's docker scripts which can run the software. 它编译得很好,有可以运行软件的docker脚本。 In eclipse everything compiles without errors and seems to work fine. 在eclipse中,一切都编译没有错误,似乎工作正常。 I'm at a loss however how to actually run/debug all the webapps at the same time in jetty in eclipse. 我不知道如何在eclipse中同时在jetty中同时运行/调试所有的webapps。 Something I can do with tomcat and websphere. 我可以用tomcat和websphere做些什么。

Can any of you kind peeps suggest me a method to allow me to debug this setup in eclipse? 你们中的任何一个人都可以告诉我一种让我在eclipse中调试这个设置的方法吗? Ideally something I can configure from gradle. 理想情况下,我可以从gradle配置。 Should I build a project that runs an embedded server? 我应该构建一个运行嵌入式服务器的项目吗? (Can this auto detect and use my existing web.xml files?) Or should I proceed with gretty (can this debug via eclipse in a straightforward manner) Or is there some other tool I'm missing? (这可以自动检测并使用我现有的web.xml文件吗?)或者我应该继续使用gretty(可以通过eclipse以简单的方式进行调试)还是有其他工具我不知道?

I can't be the only one with this setup. 我不能成为这个设置的唯一一个。 What is the common solution for this? 这个的常见解决方案是什么?

There's very little information on the internet that specifically adresses this issue. 互联网上的信息很少,专门解决这个问题。 So I'll take the time to answer my own question in the hope it will help someone else. 所以我会花时间回答我自己的问题,希望能帮助别人。

Gretty can't handle this, gretty makes strong presumptions about your app, if you've built it from the get go to adhere to those presumptions you're fine and it can be a great help. Gretty无法处理这个问题,gretty对你的应用程序做出了强有力的假设,如果你从开始构建它来坚持那些假设你很好并且它可以是一个很好的帮助。 But the solution remains slow and inflexible. 但解决方案仍然缓慢且不灵活。

There are no eclipse plugins for jetty, even though jetty is an eclipse (foundation) project, wtp won't help you.. jetty没有eclipse插件,即使jetty是一个eclipse(基础)项目,wtp也无法帮助你。

I eventually took the embedded jetty route. 我最终采用了嵌入式码头路线。 This seemed harder than it really was. 这似乎比实际更难。 But the end result works like a charm. 但最终的结果就像一个魅力。 Extremely fast startup times (Our 12 webapp project went from 30+ seconds to 5 seconds) (Gretty took minutes) The whole application became more clear. 非常快的启动时间(我们的12个webapp项目从30秒到5秒)(Gretty需要几分钟)整个应用程序变得更加清晰。 There is one simple java class that defines what is running. 有一个简单的java类定义了正在运行的内容。 No hard to read XML. 没有难读的XML。

Here's the basic structure 这是基本结构

this.server = new Server(port);

setupAnnotationScanning(server);
setupJAASLoginService(server, config);

HandlerCollection hc = new HandlerCollection(true);
startWebApp(config, hc, "/app1", "app1");

// Root must be defined last or it will interfere with non root webapps
startWebApp(config, hc, "/", "rootapp");

server.setHandler(hc);

Annotated scanning is nice, I want it. 带注释的扫描很好,我想要它。

private static void setupAnnotationScanning(Server server) {
    Configuration.ClassList classlist = Configuration.ClassList.setServerDefault(server);
    classlist.addAfter("org.eclipse.jetty.webapp.FragmentConfiguration", "org.eclipse.jetty.plus.webapp.EnvConfiguration", "org.eclipse.jetty.plus.webapp.PlusConfiguration");
    classlist.addBefore("org.eclipse.jetty.webapp.JettyWebXmlConfiguration", "org.eclipse.jetty.annotations.AnnotationConfiguration");
}

JAAS login service was harder to setup, it presumes a config file on disk, I didn't have that root, and I wanted it from my own bootstrap property service anyway. JAAS登录服务更难设置,它假设磁盘上的配置文件,我没有那个根,我想从我自己的bootstrap属性服务中得到它。

private static void setupJAASLoginService(Server server, BootstrapProperties config) throws Exception {
    JAASLoginService loginService = new JAASLoginService("ldaploginmodule");
    loginService.setName("WebRealm");
    loginService.setConfiguration(setupLDAPConfiguration(config));
    loginService.start();

    server.addBean(loginService);
}

private static javax.security.auth.login.Configuration setupLDAPConfiguration(BootstrapProperties config) {
  // Basically what I do here is make my own implementation of the Configuration and use it
  // The existing class assumes code to be in a very specific file location.
    return new javax.security.auth.login.Configuration() {
        @Override
        public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
            Map<String, Object> options = new HashMap<String, Object>();

            options.put("authenticationMethod", "simple");
            options.put("bindDn", config.get("ldap.bind.user"));
            options.put("bindPassword", config.get("ldap.bind.password"));
            options.put("contextFactory", "com.sun.jndi.ldap.LdapCtxFactory");
            options.put("debug", "true");
            options.put("forceBindingLogin", "true");
            options.put("hostname", config.get("ldap.host"));
            options.put("port", config.get("ldap.port"));
            options.put("roleBaseDn", config.get("ldap.groups.dn") + "," + config.get("ldap.root.dn"));/**/
            options.put("roleMemberAttribute", "uniqueMember");
            options.put("roleNameAttribute", "cn");
            options.put("roleObjectClass", "groupOfUniqueNames");
            options.put("userBaseDn", config.get("ldap.people.dn") + "," + config.get("ldap.root.dn"));/**/
            options.put("userIdAttribute", "uid");
            options.put("userObjectClass", "caUser");
            options.put("userPasswordAttribute", "userPassword");
            options.put("userRdnAttribute", "cn");

            AppConfigurationEntry cfg = new AppConfigurationEntry("org.eclipse.jetty.jaas.spi.LdapLoginModule", LoginModuleControlFlag.REQUIRED, options);
            return new AppConfigurationEntry[] { cfg };
        }
    };
}

You'll probably have to change the options to match your own ldap. 您可能必须更改选项以匹配您自己的ldap。 If you compare the above options to the file they're pretty much one on one mappings. 如果将上述选项与文件进行比较,则它们几乎是一对一的映射。

Now to setup a webapp: 现在设置一个webapp:

Note that I'm starting this class from a folder that is the root of my multiproject folder, the webapps are in subfolders below that root. 请注意,我从一个文件夹启动此类,该文件夹是我的多项目文件夹的根目录,webapps位于该根目录下的子文件夹中。

Also note that appname must refer to a folder name. 另请注意,appname必须引用文件夹名称。 The appnames and folder names where they reside are the same in this setup. 它们所在的应用程序名称和文件夹名称在此设置中是相同的。

private static void startWebApp(BootstrapProperties config, HandlerCollection hc, String contextRoot, String appName) throws Exception {
    boolean isProd = config.getBoolean("isProduction", false);

  // When running a production server you're probably working from warfiles.
  // In dev you're working from eclipse webapp folders (WebContent/webapp/the place where your index.html resides)
    String pathStr = isProd
            ? "dist/webapps/" + appName + ".war"
            : "webapps/" + appName;

    WebAppContext context = new WebAppContext();
    // This is where you can find the webapp on your server http://example.com{/contextRoot}
    context.setContextPath(contextRoot);
    // Optional, but I found it very useful for debugging
    context.addLifeCycleListener(LIFE_CYCLE_LISTENER);

    // Very important if you want JSTL to work, otherwise you get the error:
    // The absolute uri: [http://java.sun.com/jsp/jstl/core] cannot be resolved in
    // either web.xml or the jar files deployed with this application
    // This was very hard to figure out!
    context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*/[^/]*jstl.*\\.jar$");

    if (isProd) {
        // Again production server refers to warfile, simple basic function for jetty.
        context.setWar(pathStr);

    } else {
        // Otherwise things get a little more complicated
        // For me the app and classes folders are in two separate places.
        // But fortunately Jetty still supports that.
        Path path = Paths.get(pathStr);
        Path basePath = path.toRealPath();

        // These are folders in your eclipse projects 
        Path appFolder = basePath.resolve("webapp"); // WebContent also often used
        Path classesPath = basePath.resolve("bin/main"); 

        if (Files.exists(appFolder)) {
            context.setBaseResource(new PathResource(appFolder));
            LOGGER.log(Level.FINE, " webapp " + appFolder);
        }
        if (Files.exists(classesPath)) {
            context.setExtraClasspath(classesPath.toString());
            LOGGER.log(Level.FINE, " classes " + classesPath);
        }

        // A pure webapp project without classes works fine classesPath wont exist and is thus not added.
    }

    // Add to the handler context.
    hc.addHandler(context);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM