Java IntelliJ IDEA无法杀死我的Dropwizard服务器

Java IntelliJ IDEA无法杀死我的Dropwizard服务器,java,intellij-idea,gradle,dropwizard,Java,Intellij Idea,Gradle,Dropwizard,我有一个使用Dropwizard和Gradle开发的项目。当我想启动服务器时,我可以简单地在IntelliJ IDEA中以runconfiguration的方式运行它 这样做会启动我的服务器,我可以按预期与之交互,即使使用IntelliJ进行调试也没有问题 但是,使用“停止”或“重新运行”按钮似乎不会杀死以前启动的服务器。相反,如果重新运行服务器,则会出现以下异常: 13:45:48: Executing external task 'run'... :compileJava UP-TO-DAT

我有一个使用Dropwizard和Gradle开发的项目。当我想启动服务器时,我可以简单地在IntelliJ IDEA中以runconfiguration的方式运行它

这样做会启动我的服务器,我可以按预期与之交互,即使使用IntelliJ进行调试也没有问题

但是,使用“停止”或“重新运行”按钮似乎不会杀死以前启动的服务器。相反,如果重新运行服务器,则会出现以下异常:

13:45:48: Executing external task 'run'...
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
Connected to the target VM, address: '127.0.0.1:61376', transport: 'socket'
:run
INFO  [2014-12-16 12:46:01,393] io.dropwizard.server.ServerFactory: Starting my-project
Disconnected from the target VM, address: '127.0.0.1:61376', transport: 'socket'
WARN  [2014-12-16 12:46:01,552] org.eclipse.jetty.util.component.AbstractLifeCycle: FAILED org.eclipse.jetty.server.Server@7a6359b0: java.lang.RuntimeException: java.net.BindException: Address already in use
因此,似乎有其他程序保留了我想要使用的地址。然后运行
ps aux
时,我可以看到我的服务器仍在运行,并且它对请求做出响应。只有当我通过终端杀死它,或者当我退出IntelliJ IDEA时,服务器才会被杀死

因为这对开发来说不是很好,所以我在这里寻找一些指导。

如果您没有使用Gradle2.1,请尝试升级到2.1。否则,解决方法是添加属性

GRADLE.system.in.process=false 
进入文件“bin/idea.properties”编辑: 参见Natan的答案,了解真正的解决方案

如果答案不起作用,下面是我使用的解决方法: 应用程序类提供了一个特殊的路由,调用该路由只会终止服务器。为了实现这一点,根据答案,我们在应用程序中设置一个servlet,定义路由,然后监听它

public class MyApplication extends Application<MyConfiguration> {

    private static final Logger LOGGER = LoggerFactory.getLogger(MyApplication.class);

    private Server mServer;

    // ...

    @Override
    public void run(final RecommenderConfiguration configuration,
                final Environment environment) throws ClassNotFoundException {
        // ...

        initializeKillCommand(environment);
    }

    private void initializeKillCommand(Environment environment) {
        ServletEnvironment servletEnvironment = environment.servlets();
        servletEnvironment.addServlet(
                "Terminator",
                new ServerTerminator()
        ).addMapping("/kill");

        LifecycleEnvironment lifecycleEnvironment = environment.lifecycle();
        lifecycleEnvironment.addServerLifecycleListener(
            new ServerLifecycleListener() {
                @Override
                public void serverStarted(Server server) {
                    mServer = server;
                }
            }
        );
    }

    private class ServerTerminator extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            LOGGER.info("Received Shutdown Command");

            resp.setContentType("text/html");
            resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
            resp.getWriter().println();

            // Must initiate shut-down in separate thread to not deadlock here
            new Thread() {
                @Override
                public void run() {
                    try {
                        mServer.stop();
                    } catch (Exception ex) {
                        LOGGER.error("Unable to stop the server");
                    }
                }
           }.start();
        }
    }
}
公共类MyApplication扩展应用程序{
私有静态最终记录器Logger=LoggerFactory.getLogger(MyApplication.class);
专用服务器mServer;
// ...
@凌驾
公共无效运行(最终建议配置),
最终环境)抛出ClassNotFoundException{
// ...
initializeKillCommand(环境);
}
私有void initializeKillCommand(环境){
ServletEnvironment ServletEnvironment=environment.servlets();
ServleteEnvironment.addServlet(
“终结者”,
新服务器终止符()
).addMapping(“/kill”);
LifecycleEnvironment LifecycleEnvironment=environment.lifecycle();
lifecycleEnvironment.addServerLifecycleListener(
新服务器LifecycleListener(){
@凌驾
已启动公用void服务器(服务器){
mServer=服务器;
}
}
);
}
私有类ServerTerminator扩展了HttpServlet{
@凌驾
受保护的void doGet(HttpServletRequest-req,HttpServletResponse-resp)抛出ServletException,IOException{
LOGGER.info(“收到关闭命令”);
分别为setContentType(“文本/html”);
resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
分别为getWriter().println();
//必须在单独的线程中启动关闭,才能在此处不死锁
新线程(){
@凌驾
公开募捐{
试一试{
mServer.stop();
}捕获(例外情况除外){
LOGGER.error(“无法停止服务器”);
}
}
}.start();
}
}
}

实际上,它不会终止原始实例,因此端口仍然是绑定的。我在IntelliJ中通过Gradle运行Spring boot时遇到了这个问题-我最终通过标准命令行Gradle运行服务器,它可以正常启动和停止。不知道为什么IJ没有正确地释放它。目前我也使用终端,但这样你就不能使用调试器-你依赖于控制台输出调试。我在哪里可以找到提到的文件夹bin?在我的例子中,它是“C:\Program Files(x86)\JetBrains\IntelliJ IDEA Community Edition 13.1.4\bin”。idea.properties不存在于我的环境中,在这种情况下,您需要创建它。太棒了!我的gradle版本已经发布,但插入该选项似乎可以完成这项工作。所以我接受了你的答案