日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

tomat(16)关闭钩子

發布時間:2023/12/3 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 tomat(16)关闭钩子 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
【0】REAMDE 0)本文部分文字描述轉自:“how tomcat works”,旨在學習“tomat(16)關閉鉤子”的相關知識; 1)problem+solution: 1.1)problem:在很多實際環境中,當用戶關閉應用程序時,并不會按照推薦的方法關閉應用程序,很有可能不做清理工作; 1.2)solution:java 為程序員提供了一種優雅的方法可以在在關閉過程中執行一些代碼,以確保那些負責善后處理的代碼可能能夠執行; 2)在java中,虛擬機會對兩類事件(events)進行響應,然后執行關閉操作: event1)當調用System.exit()方法或程序的最后一個非守護進程線程退出時,應用程序正常退出; event2)用戶突然強制虛擬機中斷運行,例如用戶按 CTRL+C 快捷鍵或在未關閉java程序的case下,從系統中退出; 3)虛擬機在執行關閉操作時,會經過以下兩個階段(stages): stage1)虛擬機啟動所有已經注冊的關閉鉤子,如果有的話。關閉鉤子是先前已經通過 Runtime 類注冊的線程,所有的關閉鉤子會并發執行,直到完成任務;(干貨——關閉鉤子是線程) stage2)虛擬機根據case 調用所有沒有被調用過的 終結期(finalizer); Attention)本文重點說明第一個stage,因為該階段允許程序員告訴虛擬機在應用程序中執行一些清理代碼。 4)創建關閉鉤子很簡單(steps): step1)創建Thread類的一個子類 ; step2)實現你自己的run()方法,當應用程序(正常或突然)關閉時,會調用此方法; step3)在應用程序中,實例化關閉鉤子類; step4)使用當前 Runtime.addShutdownHook() 方法注冊關閉鉤子; 5)看個荔枝(關于 創建鉤子的測試用例): package com.tomcat.chapter16.shutdownhook;public class ShutdownHookDemo {public void start() {System.out.println("Demo");ShutdownHook shutdownHook = new ShutdownHook();Runtime.getRuntime().addShutdownHook(shutdownHook); // 添加一個關閉鉤子.}public static void main(String[] args) {ShutdownHookDemo demo = new ShutdownHookDemo();demo.start();try {System.in.read();} catch (Exception e) {}System.out.println("Normal exit");} }class ShutdownHook extends Thread {public void run() {System.out.println("Shutting down");} } 對以上代碼的分析(Analysis): A1)在實例化ShutdownHookDemo?類后,main()方法會調用start()方法;start()方法會創建一個關閉鉤子,并通過當前運行時注冊它: ShutdownHook shutdownHook = new ShutdownHook();Runtime.getRuntime().addShutdownHook(shutdownHook); // 添加一個關閉鉤子. A2)然后,應用程序會等待用戶輸入: System.in.read(); A3)當用戶按 enter 鍵后,應用程序會退出。虛擬機會執行關閉鉤子,輸入字符串“Shutting down”;

【1】關閉鉤子的荔枝 1)源代碼如下(該應用程序在啟動時會創建一個臨時文件,并在關閉時刪除該臨時文件) public class MySwingAppWithoutShutdownHook extends JFrame { //不帶有關閉鉤子的swingJButton exitButton = new JButton();JTextArea jTextArea1 = new JTextArea();String dir = System.getProperty("user.dir");String filename = "temp.txt";public MySwingApp() {exitButton.setText("Exit");exitButton.setBounds(new Rectangle(304, 248, 76, 37));exitButton.addActionListener(new java.awt.event.ActionListener() {public void actionPerformed(ActionEvent e) {exitButton_actionPerformed(e);}});this.getContentPane().setLayout(null);jTextArea1.setText("Click the Exit button to quit");jTextArea1.setBounds(new Rectangle(9, 7, 371, 235));this.getContentPane().add(exitButton, null);this.getContentPane().add(jTextArea1, null);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setBounds(0, 0, 400, 330);this.setVisible(true);initialize();}private void initialize() {// create a temp fileFile file = new File(dir, filename);try {System.out.println("Creating temporary file");file.createNewFile();} catch (IOException e) {System.out.println("Failed creating temporary file.");}}private void shutdown() {// delete the temp fileFile file = new File(dir, filename);if (file.exists()) {System.out.println("Deleting temporary file.");file.delete();}}void exitButton_actionPerformed(ActionEvent e) {shutdown();System.exit(0);}public static void main(String[] args) {MySwingApp mySwingApp = new MySwingApp();} } 對以上代碼的分析(Analysis):
step1)應用程序會調用其 initialize()方法; step2)initialize()方法會在用戶目錄中創建一個臨時文件,名為 “temp.txt”; step3)當用戶關閉應用程序時,該程序會刪除該臨時文件; 2)problem+solution 2.1)problem:我們希望用戶總是能夠單擊exit 來退出,這動作監聽器就會調用shutdown()方法,可以刪除臨時文件了;但如果用戶通過單擊右上角的關閉按鈕或是通過其他方式強制退出,則臨時文件就無法刪除了; 2.2)solution:使用關閉鉤子來刪除臨時文件;關閉鉤子是一個內部類,這樣它就能夠訪問主類的所有方法;(干貨——關閉鉤子是一個內部類,這樣它就能夠訪問主類的所有方法) 3)帶有關閉鉤子的源代碼如下: public class MySwingAppWithShutdownHook extends JFrame { // 帶有關閉鉤子的swing.JButton exitButton = new JButton();JTextArea jTextArea1 = new JTextArea();String dir = System.getProperty("user.dir");String filename = "temp.txt";public MySwingAppWithShutdownHook() {exitButton.setText("Exit");exitButton.setBounds(new Rectangle(304, 248, 76, 37));exitButton.addActionListener(new java.awt.event.ActionListener() {public void actionPerformed(ActionEvent e) {exitButton_actionPerformed(e);}});this.getContentPane().setLayout(null);jTextArea1.setText("Click the Exit button to quit");jTextArea1.setBounds(new Rectangle(9, 7, 371, 235));this.getContentPane().add(exitButton, null);this.getContentPane().add(jTextArea1, null);this.setDefaultCloseOperation(EXIT_ON_CLOSE);this.setBounds(0,0, 400, 330);this.setVisible(true);initialize();}private void initialize() {// add shutdown hookMyShutdownHook shutdownHook = new MyShutdownHook();Runtime.getRuntime().addShutdownHook(shutdownHook);// create a temp fileFile file = new File(dir, filename);try {System.out.println("Creating temporary file");file.createNewFile();}catch (IOException e) {System.out.println("Failed creating temporary file.");}}private void shutdown() { // highlight line.// delete the temp fileFile file = new File(dir, filename);if (file.exists()) {System.out.println("Deleting temporary file.");file.delete();}}void exitButton_actionPerformed(ActionEvent e) {shutdown();System.exit(0);}public static void main(String[] args) {MySwingAppWithShutdownHook mySwingApp = new MySwingAppWithShutdownHook();}private class MyShutdownHook extends Thread { // highlight line.public void run() {shutdown(); // highlight line.}} } 對以上代碼的分析(Analysis): step1)程序會首先創建一個內部類MyShutdownHook的一個實例,即鉤子類實例,并將注冊該鉤子實例; step2)其他的代碼與MySwingAppWithoutShutdownHook的源代碼類似; Attention)唯一不同的是,當突然關閉應用程序時,該臨時文件總是會被刪除;
【2】tomcat中的關閉鉤子 1)intro:tomcat也是通過關閉鉤子來完成退出過程的; 2)org.apache.catalina.startup.Catalina類:負責啟動管理其他組件的Server對象。一個名為 CatalinaShutdownHook的內部類繼承自 java.lang.Thread類,提供了run()方法的實現,它會調用 Server.stop()方法,執行關閉操作;
Supplement)本文習慣性地給出 Catalina.main()方法的調用過程:
protected void start() { //org.apache.catalina.startup.Catalina.start().//..... // Replace System.out and System.err with a custom PrintStreamSystemLogHandler log = new SystemLogHandler(System.out);System.setOut(log);System.setErr(log);Thread shutdownHook = new CatalinaShutdownHook(); // 創建關閉鉤子// Start the new serverif (server instanceof Lifecycle) {try {server.initialize();((Lifecycle) server).start();try {// Register shutdown hookRuntime.getRuntime().addShutdownHook(shutdownHook); // 添加關閉鉤子.} catch (Throwable t) {// This will fail on JDK 1.2. Ignoring, as Tomcat can run// fine without the shutdown hook.}// Wait for the server to be told to shut downserver.await();} //......}// Shut down the serverif (server instanceof Lifecycle) {try {try {// Remove the ShutdownHook first so that server.stop() // doesn't get invoked twiceRuntime.getRuntime().removeShutdownHook(shutdownHook);} catch (Throwable t) {// This will fail on JDK 1.2. Ignoring, as Tomcat can run// fine without the shutdown hook.}((Lifecycle) server).stop();} //......}}
protected class CatalinaShutdownHook extends Thread { //org.apache.catalina.startup.Catalina.CatalinaShutdownHook // an inner class defined in Catalinapublic void run() {if (server != null) {try {((Lifecycle) server).stop(); // highlight line.} catch (LifecycleException e) {System.out.println("Catalina.stop: " + e);e.printStackTrace(System.out);if (e.getThrowable() != null) {System.out.println("----- Root Cause -----");e.getThrowable().printStackTrace(System.out);}}} }} Supplement) S1)在Catalina實例啟動時,會實例化關閉鉤子,并在一個階段將其添加到 Runtime類中; S2)org.apache.catalina.startup.Catalina 類的源代碼如下所示:(其中Catalina.createStartDigester() 創建了很多規則,規則集參見 tomcat(15)Digester庫) public class Catalina { protected String configFile = "conf/server.xml"; protected boolean debug = false; protected ClassLoader parentClassLoader =ClassLoader.getSystemClassLoader(); protected Server server = null; protected boolean starting = false; protected boolean stopping = false; protected boolean useNaming = true; public static void main(String args[]) {(new Catalina()).process(args);}public void process(String args[]) {setCatalinaHome();setCatalinaBase();try {if (arguments(args))execute();} catch (Exception e) {e.printStackTrace(System.out);}}public void setParentClassLoader(ClassLoader parentClassLoader) {this.parentClassLoader = parentClassLoader;}public void setServer(Server server) {this.server = server;} protected boolean arguments(String args[]) {boolean isConfig = false;if (args.length < 1) {usage();return (false);}for (int i = 0; i < args.length; i++) {if (isConfig) {configFile = args[i];isConfig = false;} else if (args[i].equals("-config")) {isConfig = true;} else if (args[i].equals("-debug")) {debug = true;} else if (args[i].equals("-nonaming")) {useNaming = false;} else if (args[i].equals("-help")) {usage();return (false);} else if (args[i].equals("start")) {starting = true;} else if (args[i].equals("stop")) {stopping = true;} else {usage();return (false);}}return (true);}protected File configFile() {File file = new File(configFile);if (!file.isAbsolute())file = new File(System.getProperty("catalina.base"), configFile);return (file);}protected Digester createStartDigester() {// Initialize the digesterDigester digester = new Digester();digester.setClassLoader(StandardServer.class.getClassLoader());if (debug)digester.setDebug(999);digester.setValidating(false);// Configure the actions we will be usingdigester.addObjectCreate("Server","org.apache.catalina.core.StandardServer","className");digester.addSetProperties("Server");digester.addSetNext("Server","setServer","org.apache.catalina.Server");digester.addObjectCreate("Server/GlobalNamingResources","org.apache.catalina.deploy.NamingResources");digester.addSetProperties("Server/GlobalNamingResources");digester.addSetNext("Server/GlobalNamingResources","setGlobalNamingResources","org.apache.catalina.deploy.NamingResources");digester.addObjectCreate("Server/Listener",null, // MUST be specified in the element"className");digester.addSetProperties("Server/Listener");digester.addSetNext("Server/Listener","addLifecycleListener","org.apache.catalina.LifecycleListener");digester.addObjectCreate("Server/Service","org.apache.catalina.core.StandardService","className");digester.addSetProperties("Server/Service");digester.addSetNext("Server/Service","addService","org.apache.catalina.Service");digester.addObjectCreate("Server/Service/Listener",null, // MUST be specified in the element"className");digester.addSetProperties("Server/Service/Listener");digester.addSetNext("Server/Service/Listener","addLifecycleListener","org.apache.catalina.LifecycleListener");digester.addObjectCreate("Server/Service/Connector","org.apache.catalina.connector.http.HttpConnector","className");digester.addSetProperties("Server/Service/Connector");digester.addSetNext("Server/Service/Connector","addConnector","org.apache.catalina.Connector");digester.addObjectCreate("Server/Service/Connector/Factory","org.apache.catalina.net.DefaultServerSocketFactory","className");digester.addSetProperties("Server/Service/Connector/Factory");digester.addSetNext("Server/Service/Connector/Factory","setFactory","org.apache.catalina.net.ServerSocketFactory");digester.addObjectCreate("Server/Service/Connector/Listener",null, // MUST be specified in the element"className");digester.addSetProperties("Server/Service/Connector/Listener");digester.addSetNext("Server/Service/Connector/Listener","addLifecycleListener","org.apache.catalina.LifecycleListener");// Add RuleSets for nested elementsdigester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));digester.addRuleSet(new EngineRuleSet("Server/Service/"));digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Default"));digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/DefaultContext/"));digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/Default"));digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/DefaultContext/"));digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Context/"));digester.addRule("Server/Service/Engine",new SetParentClassLoaderRule(digester,parentClassLoader));return (digester);} protected Digester createStopDigester() {// Initialize the digesterDigester digester = new Digester();if (debug)digester.setDebug(999);// Configure the rules we need for shutting downdigester.addObjectCreate("Server","org.apache.catalina.core.StandardServer","className");digester.addSetProperties("Server");digester.addSetNext("Server","setServer","org.apache.catalina.Server");return (digester);} protected void execute() throws Exception {if (starting)start();else if (stopping)stop();}protected void setCatalinaBase() {if (System.getProperty("catalina.base") != null)return;System.setProperty("catalina.base",System.getProperty("catalina.home"));} protected void setCatalinaHome() {if (System.getProperty("catalina.home") != null)return;System.setProperty("catalina.home",System.getProperty("user.dir"));} protected void start() {// Setting additional variablesif (!useNaming) {System.setProperty("catalina.useNaming", "false");} else {System.setProperty("catalina.useNaming", "true");String value = "org.apache.naming";String oldValue =System.getProperty(javax.naming.Context.URL_PKG_PREFIXES);if (oldValue != null) {value = value + ":" + oldValue;}System.setProperty(javax.naming.Context.URL_PKG_PREFIXES, value);value = System.getProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY);if (value == null) {System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY,"org.apache.naming.java.javaURLContextFactory");}}// Create and execute our DigesterDigester digester = createStartDigester();File file = configFile();try {InputSource is =new InputSource("file://" + file.getAbsolutePath());FileInputStream fis = new FileInputStream(file);is.setByteStream(fis);digester.push(this);digester.parse(is);fis.close();} catch (Exception e) {System.out.println("Catalina.start using "+ configFile() + ": " + e);e.printStackTrace(System.out);System.exit(1);}// If a SecurityManager is being used, set properties for// checkPackageAccess() and checkPackageDefinitionif( System.getSecurityManager() != null ) {String access = Security.getProperty("package.access");if( access != null && access.length() > 0 )access += ",";elseaccess = "sun.,";Security.setProperty("package.access",access + "org.apache.catalina.,org.apache.jasper.");String definition = Security.getProperty("package.definition");if( definition != null && definition.length() > 0 )definition += ",";elsedefinition = "sun.,";Security.setProperty("package.definition",// FIX ME package "javax." was removed to prevent HotSpot// fatal internal errorsdefinition + "java.,org.apache.catalina.,org.apache.jasper.,org.apache.coyote.");}// Replace System.out and System.err with a custom PrintStreamSystemLogHandler log = new SystemLogHandler(System.out);System.setOut(log);System.setErr(log);Thread shutdownHook = new CatalinaShutdownHook();// Start the new serverif (server instanceof Lifecycle) {try {server.initialize();((Lifecycle) server).start();try {// Register shutdown hookRuntime.getRuntime().addShutdownHook(shutdownHook);} catch (Throwable t) {// This will fail on JDK 1.2. Ignoring, as Tomcat can run// fine without the shutdown hook.}// Wait for the server to be told to shut downserver.await();} catch (LifecycleException e) {System.out.println("Catalina.start: " + e);e.printStackTrace(System.out);if (e.getThrowable() != null) {System.out.println("----- Root Cause -----");e.getThrowable().printStackTrace(System.out);}}}// Shut down the serverif (server instanceof Lifecycle) {try {try {// Remove the ShutdownHook first so that server.stop() // doesn't get invoked twiceRuntime.getRuntime().removeShutdownHook(shutdownHook);} catch (Throwable t) {// This will fail on JDK 1.2. Ignoring, as Tomcat can run// fine without the shutdown hook.}((Lifecycle) server).stop();} catch (LifecycleException e) {System.out.println("Catalina.stop: " + e);e.printStackTrace(System.out);if (e.getThrowable() != null) {System.out.println("----- Root Cause -----");e.getThrowable().printStackTrace(System.out);}}}}protected void stop() {// Create and execute our DigesterDigester digester = createStopDigester();File file = configFile();try {InputSource is =new InputSource("file://" + file.getAbsolutePath());FileInputStream fis = new FileInputStream(file);is.setByteStream(fis);digester.push(this);digester.parse(is);fis.close();} catch (Exception e) {System.out.println("Catalina.stop: " + e);e.printStackTrace(System.out);System.exit(1);}// Stop the existing servertry {Socket socket = new Socket("127.0.0.1", server.getPort());OutputStream stream = socket.getOutputStream();String shutdown = server.getShutdown();for (int i = 0; i < shutdown.length(); i++)stream.write(shutdown.charAt(i));stream.flush();stream.close();socket.close();} catch (IOException e) {System.out.println("Catalina.stop: " + e);e.printStackTrace(System.out);System.exit(1);}} protected void usage() {System.out.println("usage: java org.apache.catalina.startup.Catalina"+ " [ -config {pathname} ] [ -debug ]"+ " [ -nonaming ] { start | stop }");} protected class CatalinaShutdownHook extends Thread {public void run() {if (server != null) {try {((Lifecycle) server).stop();} catch (LifecycleException e) {System.out.println("Catalina.stop: " + e);e.printStackTrace(System.out);if (e.getThrowable() != null) {System.out.println("----- Root Cause -----");e.getThrowable().printStackTrace(System.out);}}} }} } final class SetParentClassLoaderRule extends Rule {public SetParentClassLoaderRule(Digester digester,ClassLoader parentClassLoader) {super(digester);this.parentClassLoader = parentClassLoader;}ClassLoader parentClassLoader = null;public void begin(Attributes attributes) throws Exception {if (digester.getDebug() >= 1)digester.log("Setting parent class loader");Container top = (Container) digester.peek();top.setParentClassLoader(parentClassLoader);} }

總結

以上是生活随笔為你收集整理的tomat(16)关闭钩子的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。