springboot 关闭的正确姿势

本贴最后更新于 2935 天前,其中的信息可能已经时移世异

  使用springboot框架生成的项目,不需要部署在服务器上,只需用maven的install命令将项目达成jar包,然后使用java -jar 命令就可以将项目启动起来了(不会用java -jar命令请自行百度)。

  那么问题来了……

  这东西起来以后怎么关?…

  如果使用杀进程的方法,那么你需要人为的去查询pid(会获取指定进程pid然后杀掉的不算)。

  下面的方法可以通过给主函数传参的方式来进行springboot项目的开或关。

 

  上代码

package cn.crm; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ConnectException; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketTimeoutException; import java.security.AccessControlException; import java.util.Random; import javax.sql.DataSource; import org.apache.ibatis.session.SqlSessionFactory; import org.apache.log4j.Logger; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.ExitCodeGenerator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.transaction.PlatformTransactionManager; @EnableAutoConfiguration @SpringBootApplication @ComponentScan @MapperScan("cn.crm.mapper") public class Application { private static Logger logger = Logger.getLogger(Application.class); private static Application app = null; // 是否阻塞 protected boolean await = true; // 关闭端口 private int port = 9876; // 主机地址 private String address = "localhost"; // 系统阻塞socket private volatile ServerSocket awaitSocket = null; // 是否停止等待 private volatile boolean stopAwait = false; // 关闭系统指令 private String startup= "STARTUP"; // 启动系统指令 private String shutdown = "SHUTDOWN"; private Random random = null; @Bean @ConfigurationProperties(prefix="spring.datasource") public DataSource dataSource() { return new org.apache.tomcat.jdbc.pool.DataSource(); } @Bean public SqlSessionFactory sqlSessionFactoryBean() throws Exception { SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean(); sqlSessionFactoryBean.setDataSource(dataSource()); PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath:/mybatis/*.xml")); return sqlSessionFactoryBean.getObject(); } @Bean public PlatformTransactionManager transactionManager() { return new DataSourceTransactionManager(dataSource()); } /** * Start * @throws Exception */ public static void main(String[] args) throws Exception { if (app == null) { app = new Application(); } if (args.length < 3) { logger.info("SpringBoot args error"); return; } String command = args[0]; app.port = Integer.valueOf(args[1]) ; app.address = args[2]; if (app.startup.equals(command)) { app.start(); } if (app.shutdown.equals(command)) { app.stop(); } } private void start() throws Exception { logger.info("------------------------Server startup------------------------"); long t1 = System.nanoTime(); String[] args = new String[]{}; ApplicationContext ctx = SpringApplication.run(Application.class, args); logger.info("SpringBoot Start Success"); long t2 = System.nanoTime(); logger.info("Server startup in " + ((t2 - t1) / 1000000) + " ms"); if (await) { await(); } ExitCodeGenerator exitCodeGenerator = new ExitCodeGenerator() { @Override public int getExitCode() { return 200; } }; SpringApplication.exit(ctx, exitCodeGenerator); logger.info("------------------------Server shutdown------------------------"); } private void await() { try { awaitSocket = new ServerSocket(port, 1, InetAddress.getByName(address)); } catch (IOException e) { logger.error("await: create[" + address + ":" + port + "]: ", e); return; } try { while (!stopAwait) { ServerSocket serverSocket = awaitSocket; if (serverSocket == null) { break; } Socket socket = null; StringBuilder command = new StringBuilder(); try { InputStream stream; long acceptStartTime = System.currentTimeMillis(); try { socket = serverSocket.accept(); socket.setSoTimeout(10 * 1000); stream = socket.getInputStream(); } catch (SocketTimeoutException ste) { logger.error( "Provider.accept.timeout:" + Long.valueOf(System.currentTimeMillis() - acceptStartTime), ste); continue; } catch (AccessControlException ace) { logger.error("Provider.accept security exception: " + ace.getMessage(), ace); continue; } catch (IOException e) { if (stopAwait) { break; } logger.error("Provider.await: accept: ", e); break; } // 读取 int expected = 1024; while (expected < shutdown.length()) { if (random == null) random = new Random(); expected += (random.nextInt() % 1024); } while (expected > 0) { int ch = -1; try { ch = stream.read(); } catch (IOException e) { ch = -1; } if (ch < 32) break; command.append((char) ch); expected--; } } finally { try { if (socket != null) { socket.close(); } } catch (IOException e) { // Ignore } } boolean match = command.toString().equals(shutdown); if (match) { break; } else { } } } finally { ServerSocket serverSocket = awaitSocket; awaitSocket = null; if (serverSocket != null) { try { serverSocket.close(); } catch (IOException e) { // Ignore } } } } private void stop() { try (Socket socket = new Socket(address, port); OutputStream stream = socket.getOutputStream()) { String shutdown = this.shutdown; for (int i = 0; i < shutdown.length(); i++) { stream.write(shutdown.charAt(i)); } stream.flush(); } catch (ConnectException ce) { logger.error("stopServer.connectException [" + address + ":" + port + "]", ce); ce.printStackTrace(); System.exit(1); } catch (IOException e) { logger.error("stopServer.IOException", e); e.printStackTrace(); System.exit(1); } } }

  这样,只要在启动的时候加入启动或停止的参数可以实现启动或停止服务的功能了(注:await方法一直在监听ip和端口是否收到shutdown的命令,接收到shutdown命令后则调用SpringApplication的exit方法,停止服务)。

  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    945 引用 • 1460 回帖 • 2 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • 新人

    让我们欢迎这对新人。哦,不好意思说错了,让我们欢迎这位新人!
    新手上路,请谨慎驾驶!

    52 引用 • 228 回帖 • 1 关注
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖 • 3 关注
  • TextBundle

    TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。

    1 引用 • 2 回帖 • 73 关注
  • Jenkins

    Jenkins 是一套开源的持续集成工具。它提供了非常丰富的插件,让构建、部署、自动化集成项目变得简单易用。

    54 引用 • 37 回帖 • 2 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 487 关注
  • CAP

    CAP 指的是在一个分布式系统中, Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得。

    12 引用 • 5 回帖 • 630 关注
  • 单点登录

    单点登录(Single Sign On)是目前比较流行的企业业务整合的解决方案之一。SSO 的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

    9 引用 • 25 回帖 • 1 关注
  • PHP

    PHP(Hypertext Preprocessor)是一种开源脚本语言。语法吸收了 C 语言、 Java 和 Perl 的特点,主要适用于 Web 开发领域,据说是世界上最好的编程语言。

    179 引用 • 408 回帖 • 486 关注
  • Logseq

    Logseq 是一个隐私优先、开源的知识库工具。

    Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.

    7 引用 • 69 回帖 • 4 关注
  • 书籍

    宋真宗赵恒曾经说过:“书中自有黄金屋,书中自有颜如玉。”

    76 引用 • 389 回帖
  • 设计模式

    设计模式(Design pattern)代表了最佳的实践,通常被有经验的面向对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。

    200 引用 • 120 回帖 • 1 关注
  • Lute

    Lute 是一款结构化的 Markdown 引擎,支持 Go 和 JavaScript。

    27 引用 • 196 回帖 • 26 关注
  • Bootstrap

    Bootstrap 是 Twitter 推出的一个用于前端开发的开源工具包。它由 Twitter 的设计师 Mark Otto 和 Jacob Thornton 合作开发,是一个 CSS / HTML 框架。

    18 引用 • 33 回帖 • 660 关注
  • sts
    2 引用 • 2 回帖 • 221 关注
  • 黑曜石

    黑曜石是一款强大的知识库工具,支持本地 Markdown 文件编辑,支持双向链接和关系图。

    A second brain, for you, forever.

    21 引用 • 204 回帖 • 1 关注
  • HTML

    HTML5 是 HTML 下一个的主要修订版本,现在仍处于发展阶段。广义论及 HTML5 时,实际指的是包括 HTML、CSS 和 JavaScript 在内的一套技术组合。

    108 引用 • 295 回帖
  • gRpc
    11 引用 • 9 回帖 • 88 关注
  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 568 关注
  • 机器学习

    机器学习(Machine Learning)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。

    83 引用 • 37 回帖
  • RESTful

    一种软件架构设计风格而不是标准,提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

    30 引用 • 114 回帖 • 3 关注
  • 小薇

    小薇是一个用 Java 写的 QQ 聊天机器人 Web 服务,可以用于社群互动。

    由于 Smart QQ 从 2019 年 1 月 1 日起停止服务,所以该项目也已经停止维护了!

    34 引用 • 467 回帖 • 760 关注
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖 • 4 关注
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    289 引用 • 4492 回帖 • 658 关注
  • C

    C 语言是一门通用计算机编程语言,应用广泛。C 语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

    85 引用 • 165 回帖
  • 爬虫

    网络爬虫(Spider、Crawler),是一种按照一定的规则,自动地抓取万维网信息的程序。

    106 引用 • 275 回帖
  • 音乐

    你听到信仰的声音了么?

    61 引用 • 512 回帖
  • Google

    Google(Google Inc.,NASDAQ:GOOG)是一家美国上市公司(公有股份公司),于 1998 年 9 月 7 日以私有股份公司的形式创立,设计并管理一个互联网搜索引擎。Google 公司的总部称作“Googleplex”,它位于加利福尼亚山景城。Google 目前被公认为是全球规模最大的搜索引擎,它提供了简单易用的免费服务。不作恶(Don't be evil)是谷歌公司的一项非正式的公司口号。

    49 引用 • 192 回帖