我正在尝试为Eclipse中的gradle多Web应用程序设置开发环境。该应用程序已部署在码头上的生产环境中,因此这就是我想在开发中使用的东西。我无法通过Eclipse来运行所有Web应用程序,也无法进行调试。
我能够找到只能运行单个Web应用程序的在线使用解决方案的解决方案。或者他们通过gradle(gretty)在服务器中运行webapp,这会导致调试问题。
我的来源是一个多项目gradle应用。它可以正确编译,有可以运行该软件的docker脚本。在Eclipse中,所有内容均可正确编译,并且工作正常。但是我不知所措,如何在Eclipse中同时运行/调试所有webapp。我可以用tomcat和websphere做些什么。
你们当中有人可以给我建议一种让我在Eclipse中调试此设置的方法吗?理想情况下,我可以从gradle进行配置。我应该建立一个运行嵌入式服务器的项目吗? (这可以自动检测并使用我现有的web.xml文件吗?)还是应该继续使用gretty(可以通过Eclipse以一种直接的方式进行调试)还是缺少其他工具?
我不是唯一一个使用此设置的人。常见的解决方案是什么?
答案 0 :(得分:0)
互联网上很少有专门解决此问题的信息。因此,我将花点时间回答我自己的问题,希望它会对其他人有所帮助。
Gretty无法处理这个问题,gretty对您的应用程序有很强的假设,如果您从头开始构建它就可以坚持这些假设,那么您就很好了,这可能是一个很大的帮助。但是解决方案仍然缓慢且僵化。
即使jetty是一个eclipse(基础)项目,也没有用于jetty的eclipse插件,但是wtp不会帮助您。
我最终选择了嵌入式码头路线。这似乎比实际困难。但是最终结果却像魅力一样。极快的启动时间(我们的12个webapp项目从30多秒缩短到5秒)(Gretty花了几分钟)整个应用程序变得更加清晰。有一个简单的java类定义正在运行的内容。不难阅读XML。
这是基本结构
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);
带注释的扫描很好,我想要。
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登录服务很难设置,它假定磁盘上有一个配置文件,我没有该根目录,无论如何我都希望从我自己的引导属性服务中获取它。
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 };
}
};
}
您可能必须更改选项以匹配您自己的ldap。如果将上述选项与文件进行比较,它们几乎是一对一的映射。
现在设置网络应用程序:
请注意,我是从作为多项目文件夹根目录的文件夹开始此类的,Web应用程序位于该根目录下的子文件夹中。
还请注意,appname必须引用文件夹名称。在此设置中,它们所驻留的应用程序名称和文件夹名称是相同的。
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);
}