<?xml version="1.0" encoding="utf-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>TOOBUG信息安全网</title><link>https://blog.quwenai.cn/</link><description>做好的Java技术社群</description><item><title>【JVM】类加载器（二）：Tomcat 打破双亲委派</title><link>https://blog.quwenai.cn/post/10264.html</link><description>
&lt;p&gt;首先思考一个问题，整个Tomcat容器是一个Java进程，假若Tomcat中同时部署了两个应用，应用A依赖Spring3.0，应用B依赖Spring5.0，那么Tomcat如何决定使用哪个版本的依赖呢。&lt;/p&gt; 
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2025/02/20250222204748174022846828496.png&quot; alt=&quot;image.png&quot;&gt;&lt;br&gt; 所以，按照JDK自带的双亲委派模型是无法解决的，因为ClassLoader#loaderClass默认会检查这个类有没有加载过，保证了类在进程中是唯一的。如果我们想加载两个版本的类，需要打破原有的模型。&lt;/p&gt; 
&lt;h4&gt;
&lt;a id=&quot;1Tomcat__5&quot;&gt;&lt;/a&gt;1.Tomcat 类加载要求&lt;/h4&gt; 
&lt;p&gt;1）隔离：对于 Tomcat 类隔离要满足以下两点：&lt;/p&gt; 
&lt;ul&gt;
&lt;li&gt;Tomcat 上部署的各个 web 应用应该隔离。比如不同的应用可能会依赖相同三方库的不同版本&lt;/li&gt;
&lt;li&gt;Tomcat 自己的类库于所有的 web 应用应该隔离。&lt;/li&gt;
&lt;/ul&gt; 
&lt;p&gt;2）共享：要求部署在同一个 Tomcat 不同的应用程序，相同类库的相同版本是共享的，否则就会出现大量相同的类加载到虚拟机中。&lt;/p&gt; 
&lt;h4&gt;
&lt;a id=&quot;2Tomcat__14&quot;&gt;&lt;/a&gt;2.Tomcat 类加载器结构分析&lt;/h4&gt; 
&lt;p&gt;&lt;strong&gt;1）在双亲委派的结构下，同级间 ClassLoader 相隔离&lt;/strong&gt;&lt;/p&gt; 
&lt;ul&gt;
&lt;li&gt;对于每个 web 应用都创建一个 ClassLoader – WebappClassLoader（加载 /WEB-INF/classes、/WEB-INF/lib）&lt;/li&gt;
&lt;li&gt;对于 Tomcat 的类库单独创建一个 ClassLoader – CatalinaClassLoader （加载 server.loader…)&lt;br&gt; &lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2025/02/20250222204748174022846840864.png&quot; alt=&quot;image.png&quot;&gt;
&lt;/li&gt;
&lt;/ul&gt; 
&lt;p&gt;&lt;strong&gt;2）局部打破双亲委派&lt;/strong&gt;&lt;/p&gt; 
&lt;p&gt;对于 WebappClassLoader，如果直接使用双亲委派，可能会出现问题，举个例子，父 AppClassLoader 已经加载了 commons-lang:1.0，而当前应用依赖的是 2.0，那么就会出现 2.0 无法加载的情况。&lt;/p&gt; 
&lt;p&gt;所以，这里需要重写 WebappClassLoader 的 loadClass 方法，在收到类加载的请求后，**先自己加载（打破双亲委派），**如果 findClass 找不到，再交给父加载器去加载。&lt;br&gt; &lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2025/02/20250222204748174022846870731.png&quot; alt=&quot;image.png&quot;&gt;&lt;/p&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;注：打破双亲委派并不是说没有 parent，而是对于调用 ClassLoader 加载类的顺序。&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;p&gt;&lt;strong&gt;3）抽象公共层 ClassLoader&lt;/strong&gt;&lt;/p&gt; 
&lt;p&gt;首先，到这里又未完全打破双亲委派；然后，双亲委派下 parent 可以实现类加载的共享；所以，Tomcat 还提供了两个类加载器，我们可以把应用共享的依赖放到它们加载的路径下&lt;/p&gt; 
&lt;ul&gt;
&lt;li&gt;CommonClassLoader：Tomcat 应用和全部 web 应用共享（加载 $CATALINA_HOME/lib）&lt;/li&gt;
&lt;li&gt;SharedClassLoader：对于所有的 web 应用共享（加载 shared.loader…)&lt;br&gt; &lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2025/02/20250222204750174022847073651.png&quot; alt=&quot;image.png&quot;&gt;
&lt;/li&gt;
&lt;/ul&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;注：默认情况下，common、cataina、shared 这三个公共的 classloader 其实是同一个，都是 common classloader。而针对每个 webapp，都有自己的 WebappClassLoader 实例来加载每个应用自己的类，该类加载实例的 parent 即是 Shared ClassLoader。&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;p&gt;最后再把这些 ClassLoader 的类关系再来看一下：&lt;br&gt; &lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2025/02/20250222204750174022847027279.png&quot; alt=&quot;image.png&quot;&gt;&lt;/p&gt; 
&lt;h5&gt;&lt;a id=&quot;_45&quot;&gt;&lt;/a&gt;&lt;/h5&gt; 
&lt;h4&gt;
&lt;a id=&quot;3WebappClassLoader__47&quot;&gt;&lt;/a&gt;3.WebappClassLoader 实现分析&lt;/h4&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loadClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loadClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
 
&lt;span class=&quot;token annotation punctuation&quot;&gt;@Override&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;loadClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;boolean&lt;/span&gt; resolve&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;synchronized&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getClassLoadingLock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; clazz &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 1. 首先从当前ClassLoader的本地缓存中加载类，如果找到则返回&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 类中维护了一个resourceEntries的ConcurrentHashMap&lt;/span&gt;
        clazz &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findLoadedClass0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;clazz &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isDebugEnabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;  Returning class from cache&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;resolveClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;clazz&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; clazz&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// 2. 在本地缓存没有的情况下，调用ClassLoader的findLoadedClass方法查看jvm是否已经加载过此类，如果已经加载则直接返回。&lt;/span&gt;
        clazz &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findLoadedClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;clazz &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isDebugEnabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;  Returning class from cache&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;token function&quot;&gt;resolveClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;clazz&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; clazz&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; resourceName &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;binaryNameToPath&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 3. 尝试使用javaSE classLoader来加载，避免web应用覆盖核心jre类&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 这里的javaSE classLoader是ExtClassLoader还是BootstrapClassLoader，要看具体的jvm实现&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;ClassLoader&lt;/span&gt; javaseLoader &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getJavaseClassLoader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;boolean&lt;/span&gt; tryLoadingFromJavaseLoader&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;URL&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;securityManager &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
                &lt;span class=&quot;token class-name&quot;&gt;PrivilegedAction&lt;/span&gt;&lt;span class=&quot;token generics&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;URL&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; dp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PrivilegedJavaseGetResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resourceName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AccessController&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;doPrivileged&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;dp&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
                url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; javaseLoader&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getResource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resourceName&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            tryLoadingFromJavaseLoader &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;url &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Throwable&lt;/span&gt; t&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            tryLoadingFromJavaseLoader &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token keyword&quot;&gt;boolean&lt;/span&gt; delegateLoad &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; delegate &lt;span class=&quot;token operator&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// 4. 判断是否设置了delegate属性,如果设置为true则先使用parent(sharedLoader\commonLoader)加载&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;delegateLoad&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isDebugEnabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;  Delegating to parent classloader1 &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; parent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
                clazz &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; parent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;clazz &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isDebugEnabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                        log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;  Loading class from parent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;token function&quot;&gt;resolveClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;clazz&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; clazz&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;// Ignore&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// 5. 默认是设置delegate是false的,那么就会先用WebAppClassLoader进行加载&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isDebugEnabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
            log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;  Searching local repositories&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            clazz &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;findClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;clazz &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isDebugEnabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;  Loading class from local repository&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;token function&quot;&gt;resolveClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;clazz&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; clazz&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;// Ignore&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// 6. 若是WebappClassLoader在/WEB-INF/classes、/WEB-INF/lib下还是查找不到class&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 那么委托给parent(sharedLoader\commonLoader)去查找该类 &lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 这里满足双亲委派原则&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;delegateLoad&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isDebugEnabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;  Delegating to parent classloader at end: &quot;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; parent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
                clazz &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; parent&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;clazz &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;isDebugEnabled&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                        log&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;  Loading class from parent&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;resolve&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
                        &lt;span class=&quot;token function&quot;&gt;resolveClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;clazz&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; clazz&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;// Ignore&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// 如果上述步骤都未加载到Class，抛ClassNotFoundException&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;throw&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;name&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;Web 应用类加载器默认的加载顺序是（打破了双亲委派规则）：&lt;/p&gt; 
&lt;ol&gt;
&lt;li&gt;先从缓存中加载&lt;/li&gt;
&lt;li&gt;如果没有，则从 JVM 的 Bootstrap 类加载器加载&lt;/li&gt;
&lt;li&gt;如果没有，则从当前类加载器加载（按照 WEB-INF/classes、WEB-INF/lib 的顺序）&lt;/li&gt;
&lt;li&gt;如果没有，则从父类加载器加载，由于父类加载器采用默认的委派模式，所以加载顺序是 AppClassLoader、Common、Shared&lt;/li&gt;
&lt;/ol&gt; 
&lt;p&gt;如果在配置文件中配置了&lt;code&gt;&amp;lt;Loader delegate=&quot;true&quot;/&amp;gt;&lt;/code&gt;，那么就是遵循双亲委派规则，加载顺序如下：&lt;/p&gt; 
&lt;ol&gt;
&lt;li&gt;先从缓存中加载；&lt;/li&gt;
&lt;li&gt;如果没有，则从 JVM 的 Bootstrap 类加载器加载；&lt;/li&gt;
&lt;li&gt;如果没有，则从父类加载器加载，加载顺序是 AppClassLoader、Common、Shared&lt;/li&gt;
&lt;li&gt;如果没有，则从当前类加载器加载（按照 WEB-INF/classes、WEB-INF/lib 的顺序）&lt;/li&gt;
&lt;/ol&gt; 
&lt;h4&gt;
&lt;a id=&quot;4_173&quot;&gt;&lt;/a&gt;4.打破双亲委派的其他例子&lt;/h4&gt; 
&lt;p&gt;Tomcat 其实是整体满足双亲委派，而局部打破了这个规则，最终到依赖隔离的目的。当然了，根据具体的场景，还有将双亲委派打破的更彻底的情况（如阿里的Pandora）。&lt;/p&gt; 
&lt;p&gt;这里还要说的是，通过线程上下文加载器打破双亲委派。&lt;/p&gt; 
&lt;p&gt;比如 JDBC 的 Driver 接口定义在 JDK 中，其实现由各个数据库的服务商来提供（MySQL 驱动包）。DriverManager 类中要加载各个实现了 Driver 接口的类，然后进行管理，但是 DriverManager 位于 JAVA_HOME中jre/lib/rt.jar 包，由 BootStrapClassLoader 加载；而其 Driver 接口的实现类是位于服务商提供的 Jar 包，根据之前说的传递机制，所以也需要 BootStrapClassLoader 去加载这些实现类。我们知道，BootStraClassLoader 默认只负责加载 JAVA_HOME中jre/lib/rt.jar 里所有的 class，所以需要由子类加载器去加载 Driver 实现，这就破坏了双亲委派模型。&lt;/p&gt; 
&lt;p&gt;其中，这个子类加载器是通过 Thread.currentThread().getContextClassLoader() 得到的线程上下文加载器。&lt;/p&gt;
</description><pubDate>Sat, 22 Feb 2025 20:47:50 +0800</pubDate></item><item><title>MYSQL自增主键丢失问题</title><link>https://blog.quwenai.cn/post/10263.html</link><description>
&lt;p&gt;原文链接：https://blog.csdn.net/Seky_fei/article/details/107756788&lt;/p&gt; 
&lt;p&gt;这两天在面试的时候被问到一个问题：在mysql中用自增列作为主键时，先往表里插入5条数据，此时表里数据id为1、2、3、4、5，如果此时删除id=4、5的数据后，再重启数据库，重启成功后向表里insert数据的时候，INNODB、MyISAM引擎下ID分别是从几开始增加？当时被问到这个问题时，一脸懵逼，MD谁有事没事去重启线上数据库嘛。最后还是基础知识不牢固，在此作个笔记。&lt;/p&gt; 
&lt;p&gt;MySQL通常使用的引擎都是INNODB，在建表时，一般使用自增列作为表的主键，这样的表对提高性能有一定的帮助。但是自增列有一个坑，并且这个坑存在了很久，一直到MySQL 8.0版本，才修复了这个坑，这个坑就是表的自增列变量auto_increment在MySQL重启后，有可能丢失。&lt;/p&gt; 
&lt;ul&gt;
&lt;li&gt; &lt;p&gt;&lt;strong&gt;innodb引擎(低版本)：Innodb表中把自增列作为主键ID时，自增列是通过auto-increment计数器实现的，计数器的最大值是记录到内存中的，重启数据库后，会导致auto-increment计数器重置，从而会导致主键ID重置&lt;/strong&gt;。&lt;/p&gt; &lt;/li&gt;
&lt;li&gt; &lt;p&gt;&lt;strong&gt;MyISam引擎：MyISAM表会把自增列(auto-increment计数器)最大值是记录到数据文件里，重启MySQL自增列(计数器)最大值不会丢失，从而使用自增列作为主键ID时也不会丢失&lt;/strong&gt;。&lt;/p&gt; &lt;/li&gt;
&lt;/ul&gt; 
&lt;h4&gt;
&lt;a id=&quot;1innodb_11&quot;&gt;&lt;/a&gt;1.innodb主键重置问题&lt;/h4&gt; 
&lt;p&gt;在 MySQL低版本中，InnoDB表中使用自增的 auto-increment计数器 会把值存放在内存中，不会写入磁盘。一旦MySQL 服务重启，这个值就丢了，InnoDB 引擎会根据表中现有的数据重新计算该计数器的值：获取表中最大的自增主键ID作为auto-increment计数器的最大计数，当insert数据时，在auto-increment计数器最大值上1。&lt;/p&gt; 
&lt;p&gt;先创建一张user表，新增几条数据：&lt;/p&gt; 
&lt;pre&gt;&lt;code&gt;//1.创建user表：自增列作为主键ID
CREATE TABLE `user` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL DEFAULT '',
  `age` int(4) unsigned NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
 
//2.插入5条数据
INSERT INTO `user`(`name`, age) VALUES('刘备1', 21);
INSERT INTO `user`(`name`, age) VALUES('刘备2', 22);
INSERT INTO `user`(`name`, age) VALUES('刘备3', 23);
INSERT INTO `user`(`name`, age) VALUES('刘备4', 24);
INSERT INTO `user`(`name`, age) VALUES('刘备5', 25);
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;&lt;strong&gt;(1)场景一&lt;/strong&gt;&lt;/p&gt; 
&lt;p&gt;&lt;strong&gt;mysql数据库不重启时，innodb自增主键ID会根据auto-increment计数器一直递增。&lt;/strong&gt;&lt;/p&gt; 
&lt;p&gt;向user表里插入5条数据，主键ID按自增列通过auto-increment计数器实现自增。&lt;/p&gt; 
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2025/02/20250222204719174022843924817.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt; 
&lt;p&gt;在user表里删除id为4、5的数据，再向user表中插入一条数据，主键ID是auto-increment的值6。&lt;/p&gt; 
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2025/02/20250222204719174022843967818.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt; 
&lt;p&gt;&lt;strong&gt;(2)场景二&lt;/strong&gt;&lt;/p&gt; 
&lt;p&gt;&lt;strong&gt;mysql数据库重启后，innodb自增主键ID会根据auto-increment计数器的重置而重置。&lt;/strong&gt;&lt;/p&gt; 
&lt;p&gt;在场景一的基础上，在删除id为6、3的数据后，此时auto-increment计数器的值为7，user表里的id最大是2。&lt;/p&gt; 
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2025/02/20250222204719174022843995085.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt; 
&lt;p&gt;然后重启数据库后，auto-increment计数器的值变为3，也就是user表里的自增列ID的最大值2加1。&lt;/p&gt; 
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2025/02/20250222204720174022844034975.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt; 
&lt;p&gt;此时在插入数据时，自增ID会从3开始自增。Innodb表中把自增列作为主键ID时，在mysql重启后就会存在ID重置问题。&lt;strong&gt;删除数据后，再重启，AUTO_INCREMENT会查询表里最大ID并进行重置，重置后和重启前AUTO_INCREMENT计数器的值不同。在MyISAM引擎表中的自增列不会存在这个问题&lt;/strong&gt;。&lt;/p&gt; 
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2025/02/20250222204720174022844019053.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt; 
&lt;h4&gt;
&lt;a id=&quot;2MySQL_80_autoincrement__67&quot;&gt;&lt;/a&gt;2.MySQL 8.0 auto-increment 计数器逻辑&lt;/h4&gt; 
&lt;p&gt;在 MySQL 8.0 中，这个计数器的逻辑变了：每当计数器的值有变，InnoDB 会将其写入 redo log，保存到引擎专用的系统表中。MySQL 正常关闭后重启：从系统表中获取计数器的值。MySQL 故障后重启：从系统表中获取计数器的值；从最后一个检查点开始扫描 redo log 中记录的计数器值；取这两者的最大值作为新值。&lt;/p&gt; 
&lt;h4&gt;
&lt;a id=&quot;3_70&quot;&gt;&lt;/a&gt;3.总结&lt;/h4&gt; 
&lt;p&gt;&lt;strong&gt;（1）如果mysql重启了，那么innodb表在启动后，AUTO_INCREMENT值会自动检测出、并重置为当前表中自增列的最大值+1。&lt;br&gt; （2）假如一个表里AUTO_INCREMENT计数器的值是10，此时执行update table set id = 15 where id = 9后，如果这时再继续插入数据，到了自增ID=15的时候是会报错。但是这个时候继续插入，就不会报错。因为刚才即使报错了，AUTO_INCREMENT的值依旧会增加。&lt;/strong&gt;&lt;/p&gt; 
&lt;p&gt;（3）现在使用的一般都是innodb引擎，如果将myisam引擎转换过来的时候，一定要小心这个引擎在自增id上的不同表现。在主从使用不同引擎的时候,也会出现问题,最好将引擎改完一致性的。&lt;/p&gt;
</description><pubDate>Sat, 22 Feb 2025 20:47:20 +0800</pubDate></item><item><title>【架构】应用架构发展历史</title><link>https://blog.quwenai.cn/post/10258.html</link><description>
&lt;p&gt;任何一个网站在发布初期几乎都不可能立马就拥有庞大的用户流量和海量数据，都是在不停的试错过程中一步一步演变其自身架构，满足其自身业务。比如现在能够抗住双十一这么大流量的淘宝，它的技术最早用的是LAMP（Linux+Apache+Mysql+Php）。&lt;/p&gt; 
&lt;p&gt;随着互联网的发展，网站应用的规模不断扩大，常规的垂直应用架构已无法应对，分布式服务架构以及流动计算架构势在必行，急需一个治理系统确保架构有条不紊的演进。&lt;/p&gt; 
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202144166618210483426.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt; 
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202144166618210467837.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;1_9&quot;&gt;&lt;/a&gt;1.单体架构&lt;/h3&gt; 
&lt;p&gt;实际上，架构越复杂，意味着业务的体量越庞大。 对于一个刚刚起步的项目，我们会选择最简单最快速的方式来实现。而单体架构是最好的选择，目前很多的传统软件行业仍然采用这类的架构。 一般的实施方案是，把所有的功能模块都打包在一个（jar、war），并且部署在一个web容器 下，比如tomcat、weblogic、jboss中运行&lt;/p&gt; 
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202144166618210496054.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt; 
&lt;p&gt;&lt;strong&gt;集群部署方式&lt;/strong&gt;&lt;/p&gt; 
&lt;p&gt;一旦用户量以及流量开始增加，服务器的性能就会遇到瓶颈，这个时候必须要对系统架构做调整以及优化。而在这个阶段主要需要解决的问题是提升业务系统的并行处理能力，降低单机系统负载，以便支撑更多的用户访问操作。&lt;/p&gt; 
&lt;p&gt;集群就是一种很好的方式，它可以把多台独立的服务器通过网络连接进行组合，对外形成一个整体提供服务。当一台服务器的处理能力接近或已超出其容量上限时，我们不会去尝试换一个更高性能的服务器，因为投入产出比不高，一般的做法就是采用集群技术，通过增加新的服务器来分散并发访问流量，只要业务系统能够随意支持服务器的横向扩容，那么从理论上来说就应该无惧任何挑战，从而实现可伸缩性和高可用性架构。&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;2_23&quot;&gt;&lt;/a&gt;2.分布式架构&lt;/h3&gt; 
&lt;p&gt;虽然通过集群可以提升并行处理能力以及对于高可用的实现，但是同时还需要考虑到业务的复杂度，如果仍然把所有的业务逻辑全部耦合在一起放在一个war包中来管理，那对于代码的维护和扩展来说是非常困难的。而且如果某个业务功能出现故障，会导致整个系统不可用。&lt;/p&gt; 
&lt;p&gt;所以这个阶段要做的就是降低业务的耦合度，提升系统的容错性。 因此，这个时候可以对业务进行拆分，简单来说，可以按照系统的业务功能拆分出多个业务模块，比如电上网站，会拆分出：首页、用户、搜索、订单、支付、商品等子系统。 每个子系统由不同的业务团队负责。&lt;/p&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;分布式架构即，将应用不同模块分别部署在不同的服务器上，并通过网络进行通信、协调各模块完成对应的功能。&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202144166618210482033.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt; 
&lt;p&gt;还可以把一些通用的、会被多个上层服务调用的模块独立拆分出来，形成一些共享的基础服务。这些被拆分出来的共享服务相对来说是比较独立，并且可重用。 比如用户管理服务，包含用户注册、用户查询等功能。比如单点登录服务。&lt;/p&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;&lt;strong&gt;分布式与集群&lt;/strong&gt;&lt;br&gt; 分布式是一种应用架构，集群是一种应用部署方式，分布式服务的每一个节点都可以部署成单机或者集群。但在实际开发中，为了避免某个服务节点宕机后，导致所有依赖它的服务都不能正常运行，最终使整个分布式系统不可用，一般都会将服务部署成集群模式。简单说，分布式是以缩短单个任务的执行时间来提升效率的，而集群则是通过提高单位时间内执行的任务数来提升效率。&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;h3&gt;
&lt;a id=&quot;3SOA_38&quot;&gt;&lt;/a&gt;3.SOA架构&lt;/h3&gt; 
&lt;p&gt;SOA（面向服务架构），从语义上说，它与面向过程、面向对象、面向组件一样，是一种软件组建及开发的方式。SOA 集成了独立部署和维护的服务，并允许它们相互通信和协同工作，以构建一个跨不同系统的软件应用。&lt;/p&gt; 
&lt;p&gt;那么它们是如何通信和协同工作的呢？ESB（Enterprise Service Bus，企业服务总线）把企业中各个不同的服务连接在一起。就像计算机总线一样，把计算机的各个不同的设备连接在一起。&lt;/p&gt; 
&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202145166618210512212.png&quot; width=&quot;60%&quot;&gt;&lt;p&gt;采用 SOA 架构后，ESB屏蔽各个系统间的异构性，并有公共的服务路由、异常处理、协议转换等功能，满足不同系统服务间的互联互通。各个服务是相互独立运行的，甚至都不清楚某个服务到底有多少对其他服务的依赖，减少各个服务间的依赖和互相影响，做到了松耦合。&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;4_47&quot;&gt;&lt;/a&gt;4.微服务架构&lt;/h3&gt; 
&lt;p&gt;业务系统实施服务化改造后，原本共享的业务被拆分，形成可复用的服务，可以在最大程度上避免共享业务的重复建设、资源连接瓶颈等问题出现。那么那些被拆分出来的服务，是否也需要以业务功能为维度来进行拆分，使之能够独立进行部署，以降低业务藕合和提升容错性呢？&lt;/p&gt; 
&lt;p&gt;微服务并不是一种新思想的方法。它更像是一种思想的精炼，是一种服务化思想的最佳实践方向而已，所以可以认为微服务其实是在SOA思路下，随着各个企业对于服务化治理上不断的完善，以及对软件的交付链路以及基础设施逐步成熟之下的一种自然的产物。&lt;/p&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;微服务和 SOA 架构的区别？&lt;/p&gt; 
 &lt;ol&gt;
&lt;li&gt;SOA 关注的是服务的&lt;strong&gt;可重用性&lt;/strong&gt;、以及解决企业内部的信息孤岛问题；微服务关注的是&lt;strong&gt;解耦&lt;/strong&gt;，解耦和可重用性在特定的角度来看是一样，但本质上是不同的。解耦是降低业务之间的耦合度（也就是微服务关注的服务粒度），而可重用性关注的是服务的复用&lt;/li&gt;
&lt;li&gt;微服务会使用更轻量级的通信协议，使用Restful风格的API。轻量级协议可以很好的支持跨语言，是的语言生态更加丰富&lt;/li&gt;
&lt;li&gt;微服务会更多的关注Devops的持续交付，因为服务粒度更细使得开发运维变得更加重要。 所以微服务对于容器化技术的结合更加紧密&lt;/li&gt;
&lt;li&gt;总结来讲，就是微服务承继了SOA面向服务拆分的核心思想，并随着演化，去掉了ESB，结合了新兴的DevOps理念和容器化等基础设施发展优势，将服务拆分做的更彻底。所以他们的关系大概如下，是交集的关系。&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt; 
&lt;p&gt;为了避免每个服务都需要自己实现一套分布式系统通信的语义功能，随着技术的发展，一些面向微服务架构的开发框架出现了，如Twitter的Finagle、Facebook的Proxygen以及Spring Cloud等等，这些框架实现了分布式系统通信需要的各种通用语义功能：如负载均衡和服务发现等，因此一定程度上屏蔽了这些通信细节，使得开发人员使用较少的框架代码就能开发出健壮的分布式系统。&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;5ServiceMesh_65&quot;&gt;&lt;/a&gt;5.ServiceMesh&lt;/h3&gt; 
&lt;p&gt;虽然已经有了成熟的微服务框架，但它们也存在一些本质问题：&lt;/p&gt; 
&lt;ul&gt;
&lt;li&gt;虽然框架本身屏蔽了分布式系统通信的一些通用功能实现细节，但开发者却要花更多精力去掌握和管理复杂的框架本身，在实际应用中，去追踪和解决框架出现的问题也绝非易事；&lt;/li&gt;
&lt;li&gt;开发框架通常只支持一种或几种特定的语言，回过头来看文章最开始对微服务的定义，一个重要的特性就是语言无关，但那些没有框架支持的语言编写的服务，很难融入面向微服务的架构体系，想因地制宜的用多种语言实现架构体系中的不同模块也很难做到；&lt;/li&gt;
&lt;li&gt;框架以lib库的形式和服务联编，复杂项目依赖时的库版本兼容问题非常棘手，同时，框架库的升级也无法对服务透明，服务会因为和业务无关的lib库升级而被迫升级；&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因此以Linkerd，Envoy，NginxMesh为代表的代理模式（边车模式）应运而生，这就是第一代Service Mesh，它将分布式服务的通信抽象为单独一层，在这一层中实现负载均衡、服务发现、认证授权、监控追踪、流量控制等分布式系统所需要的功能，作为一个和服务对等的代理服务，和服务部署在一起，接管服务的流量，通过代理之间的通信间接完成服务之间的通信请求，这样上边所说的三个问题也迎刃而解。&lt;/p&gt; 
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202145166618210516571.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt;
</description><pubDate>Wed, 19 Oct 2022 20:21:45 +0800</pubDate></item><item><title>【Java杂记】GUI技术：Swing基本使用及JFormDesigner插件安装使用</title><link>https://blog.quwenai.cn/post/10257.html</link><description>
&lt;p&gt;早期，电脑向用户提供的是单调、枯燥、纯字符状态的“命令行界面（CLI）”。就是到现在，我们还可以依稀看到它们的身影：在Windows中开个DOS窗口，就可看到历史的足迹。后来，Apple公司率先在电脑的操作系统中实现了图形化的用户界面（Graphical User Interface，简称GUI），但由于Apple公司封闭的市场策略，自己完成电脑硬件、操作系统、应用软件一条龙的产品，与其它PC不兼容。这使得Apple公司错过了一次一统全球PC的好机会。&lt;br&gt; 　　&lt;br&gt; 后来，Microsoft公司推出了风靡全球的Windows操作系统，它凭借着优秀的图形化用户界面，一举奠定了操作系统标准的地位。这也造就了世界首富—比尔.盖茨和IT业的泰山北斗微软公司。&lt;/p&gt; 
&lt;p&gt;在这图形用户界面风行于世的今天，一个应用软件没有良好的GUI是无法让用户接受的。而Java语言也深知这一点的重要性，它提供了一套可以轻松构建GUI的工具&lt;/p&gt; 
&lt;p&gt;&lt;strong&gt;GUI开发包&lt;/strong&gt;：&lt;/p&gt; 
&lt;ul&gt;
&lt;li&gt;java.awt 包： 主要提供字体/布局管理器&lt;/li&gt;
&lt;li&gt;javax.swing 包：主要提供各种组件(窗口/按钮/文本框)，商业开发常用&lt;/li&gt;
&lt;li&gt;java.awt.event 包：事件处理，后台功能的实现&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
&lt;a id=&quot;1Swing__12&quot;&gt;&lt;/a&gt;1.Swing 组件&lt;/h2&gt; 
&lt;p&gt;相对于AWT而言Swing包中提供了更多的丰富的、快捷的、强大的GUI组件，而且这些组件都是java语言编写而成，因此Swing不依赖本地平台，可以真正做到跨平台运行。通常而言我们把AWT称之为重量级组件，Swing称之为轻量级软件，一般而言Swing组件都是在AWT组件名称前加J。&lt;/p&gt; 
&lt;p&gt;如图所示：swing组件主要可分为三个部分&lt;br&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202139166618209964072.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;br&gt; 下面就选这些组件中比较常用的进行介绍…&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;11__18&quot;&gt;&lt;/a&gt;1.1 顶层容器（窗口）&lt;/h3&gt; 
&lt;p&gt;常用的有JFrame，JDialog。&lt;/p&gt; 
&lt;table&gt;
&lt;thead&gt;&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;组件&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;1&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;JFrame&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;一个普通的窗口（绝大多数 Swing 图形界面程序使用 JFrame 作为顶层容器）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;2&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;JDialog&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;对话框&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;
&lt;a id=&quot;12__26&quot;&gt;&lt;/a&gt;1.2 中间容器（面板）&lt;/h3&gt; 
&lt;p&gt;JPanel，JOptionPane，JScrollPane，JLayeredPane 等，主要以panel结尾。&lt;/p&gt; 
&lt;table&gt;
&lt;thead&gt;&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;组件&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;1&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;JPanel (相当于div)&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;一般轻量级面板容器组件(作为JFrame中间容器)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;2&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;JScrollPane&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;带滚动条的，可以水平和垂直滚动的面板组件&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;3&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;JSplitPane&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;分隔面板&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;4&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;JTabbedPane&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;选项卡面板&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;5&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;JLayeredPane&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;层级面板&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;
&lt;a id=&quot;13__38&quot;&gt;&lt;/a&gt;1.3 基本组件（按钮，标签等）&lt;/h3&gt; 
&lt;p&gt;JLabel，JButton，JTextField，JPasswordField，JRadioButton 等。&lt;/p&gt; 
&lt;table&gt;
&lt;thead&gt;&lt;tr&gt;
&lt;th align=&quot;center&quot;&gt;&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;组件&lt;/th&gt;
&lt;th align=&quot;center&quot;&gt;描述&lt;/th&gt;
&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;1&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;JLabel&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;标签&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;2&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;JButton&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;按钮&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;3&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;JRadioButton&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;单选按钮&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;4&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;JCheckBox&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;复选框&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;5&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;JToggleButton&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;开关按钮&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;6&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;JTextField&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;文本框&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;7&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;JPasswordField&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;密码框&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;8&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;&lt;strong&gt;JTextArea&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;文本区域&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;9&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;JComboBox&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;下拉列表框&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;10&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;JList&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;列表&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;11&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;JProgressBar&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;进度条&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;center&quot;&gt;12&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;JSlider&lt;/td&gt;
&lt;td align=&quot;center&quot;&gt;滑块&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;
&lt;a id=&quot;2Swing_API_56&quot;&gt;&lt;/a&gt;2.Swing API&lt;/h2&gt; 
&lt;p&gt;现在已经知道了 Swing 中有哪些基本组件，那我们如何编写代码实操呢？下面就介绍一下 Swing 中部分常用组件的Java api…&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;21_Jframe_58&quot;&gt;&lt;/a&gt;2.1 Jframe组件&lt;/h3&gt; 
&lt;table&gt;
&lt;thead&gt;&lt;tr&gt;
&lt;th&gt;JFrame frame = new JFrame(“HelloWorldSwing”);&lt;/th&gt;
&lt;th&gt;创建及设置窗口&lt;/th&gt;
&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;frame.&lt;strong&gt;setBounds&lt;/strong&gt;(600, 300, 500, 400);&lt;/td&gt;
&lt;td&gt;设置窗口的x,y位置，窗口大小x,y.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;frame.&lt;strong&gt;setDefaultCloseOperation&lt;/strong&gt;(JFrame.EXIT_ON_CLOSE);&lt;/td&gt;
&lt;td&gt;设置默认的关闭窗口&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;frame.add(panel)&lt;/td&gt;
&lt;td&gt;添加panel面板到容器&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;frame.&lt;strong&gt;getContentPane().add&lt;/strong&gt;(panel, BorderLayout.NORTH);&lt;/td&gt;
&lt;td&gt;添加面板到主窗口，布局在北面&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;flame.&lt;strong&gt;getContentPane().add&lt;/strong&gt;(scrollPane, BorderLayout.CENTER);&lt;/td&gt;
&lt;td&gt;添加可滚动面板到主窗口，布局在中间&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;frame.&lt;strong&gt;setVisible&lt;/strong&gt;(true);&lt;/td&gt;
&lt;td&gt;这个最好放在最后，不然视图会看不到&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;frame.setDefaultLookAndFeelDecorated(true);&lt;/td&gt;
&lt;td&gt;确保一个漂亮的外观风格&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;frame.pack();&lt;/td&gt;
&lt;td&gt;显示窗口&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;
&lt;a id=&quot;22_Panel_70&quot;&gt;&lt;/a&gt;2.2 Panel组件&lt;/h3&gt; 
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Jpanel&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;JPanel&lt;/span&gt; panel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JPanel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 创建面板容器&lt;/span&gt;
panel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;button&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 添加按钮到面板&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;JScrollPane&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;JScrollPane&lt;/span&gt; scrollPane &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JScrollPane&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 创建可滚动面板&lt;/span&gt;
scrollPane&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setViewportView&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;textArea&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 设置面板内容&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;JOptionPane&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 弹出提示框到panel容器&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;JOptionPane&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showMessageDialog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;panel3&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;没有选中任何文件&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;提示&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JOptionPane&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;WARNING_MESSAGE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;h3&gt;
&lt;a id=&quot;23__92&quot;&gt;&lt;/a&gt;2.3 功能组件&lt;/h3&gt; 
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;JLabel：即要显示的文字&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;JLabel&lt;/span&gt; label &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JLabel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Hello World&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 添加标签&lt;/span&gt;
label&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setFont&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Font&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&quot;宋体“&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Font&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;Bold&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 设置label的字体&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;Jbutton：一般需要添加监听事件ActionEvent，提交后跳转到指定方法&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;JButton&lt;/span&gt; button &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JButton&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;选择文件&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 创建按钮&lt;/span&gt;
button&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;addActionListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ActionListener&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 添加操作按钮后的事件监听器&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;JTextArea：与TextFiled和passwordFiled类似，主要是get与set&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token class-name&quot;&gt;JTextArea&lt;/span&gt; textArea &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JTextArea&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 创建文本区域&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; text &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; textArea&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 获取输入的内容&lt;/span&gt;
textArea&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setText&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;content&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 设置内容&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;ul&gt;&lt;li&gt;&lt;strong&gt;JFileChooser&lt;/strong&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;jfc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setFileSelectionMode&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;JFileChooser&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;FILES_AND_DIRECTORIES &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 设置文件对话框&lt;/span&gt;
jfc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;showSaveDialog&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;frmIpa&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 显示打开的文件对话框&lt;/span&gt;
jfc&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getSelectedFile&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 获取选择器选择的文件&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;h3&gt;
&lt;a id=&quot;Layout_121&quot;&gt;&lt;/a&gt;Layout布局&lt;/h3&gt; 
&lt;p&gt;无论上面哪种组件，都可以设置布局，比如 &lt;code&gt;frame.setLayout(new BorderLayOut())&lt;/code&gt; 或者 &lt;code&gt;panel.setLayout(new FlowLayout())&lt;/code&gt; 再或是 &lt;code&gt;button.setLayout(GridLayout)&lt;/code&gt;。常用布局如下：&lt;/p&gt; 
&lt;table&gt;
&lt;thead&gt;&lt;tr&gt;
&lt;th&gt;所属类包&lt;/th&gt;
&lt;th&gt;布局管理器名称&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Java.awt&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;BorderLayout&lt;/strong&gt;（边界布局）&lt;/td&gt;
&lt;td&gt;容器划分为东、西、南、北、中五个区域，每个区域只能放置一个组件。&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java.awt&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;GridLayout&lt;/strong&gt;（网格布局&lt;/td&gt;
&lt;td&gt;容器的空间划分成M×N列的网格区域, 每个区域只能放置一个组件。其中col与row可以手动设置&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java.awt&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;FlowLayout&lt;/strong&gt;（流式布局）&lt;/td&gt;
&lt;td&gt;组件按照加入的先后顺序按照设置的对齐方式从左向右排列，一行排满到下一行开始继续排列&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java.awt&lt;/td&gt;
&lt;td&gt;GridBagLayout（网格包布局）&lt;/td&gt;
&lt;td&gt;GridLayout的升级版，组件仍然是按照行、列放置，但是每个组件可以占据多个网格&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java.awt&lt;/td&gt;
&lt;td&gt;CardLayout（卡片布局）&lt;/td&gt;
&lt;td&gt;如同一叠牌，每个牌对应一个组件，但每次只能显示其中的一张牌。适用于在一个空间中防止多个组件的情况&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java.swing&lt;/td&gt;
&lt;td&gt;BoxLayout（箱式布局）&lt;/td&gt;
&lt;td&gt;允许在容器中纵向或者横向防止多个控件&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Java.swing&lt;/td&gt;
&lt;td&gt;SprigLayout（弹簧布局）&lt;/td&gt;
&lt;td&gt;根据一组约束条件放置控件&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;无&lt;/td&gt;
&lt;td&gt;空布局&lt;/td&gt;
&lt;td&gt;不使用布局管理器，按照控件自身提供的大小、位置信息放置控件&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;
&lt;a id=&quot;3Swing__136&quot;&gt;&lt;/a&gt;3.Swing 示例&lt;/h2&gt; 
&lt;p&gt;下面通过swing 创建一个窗口，然后添加3个按钮。效果如下&lt;br&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202139166618209960973.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Test&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 创建窗口&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;JFrame&lt;/span&gt; jf &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JFrame&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;测试窗口&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        jf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 设置窗口大小&lt;/span&gt;
        jf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setLocationRelativeTo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        jf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setDefaultCloseOperation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;WindowConstants&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;EXIT_ON_CLOSE&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 设置默认关闭窗口&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// 创建面板，指定布局为null，使用绝对布局&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;JPanel&lt;/span&gt; panel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JPanel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// 创建按钮1&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;JButton&lt;/span&gt; button01 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JButton&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Button01&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        button01&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setLocation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  &lt;span class=&quot;token comment&quot;&gt;// 设置按钮坐标&lt;/span&gt;
        button01&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 设置按钮的宽高&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 将按钮1添加到面板panel中&lt;/span&gt;
        panel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;button01&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// 创建按钮2&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;JButton&lt;/span&gt; button02 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JButton&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Button02&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        button02&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setBounds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// 设置按钮的界限（坐标和宽高）&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 将按钮2添加到面板panel中&lt;/span&gt;
        panel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;button02&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// 将panel添加到窗口Frame中，并设置为可见&lt;/span&gt;
        jf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setContentPane&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;panel&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        jf&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setVisible&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        &lt;span class=&quot;token comment&quot;&gt;// 创建按钮3&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;JButton&lt;/span&gt; button03 &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JButton&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Button03&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 将按钮设置在内容面板右下角，并且设置宽高为 100,50&lt;/span&gt;
        button03&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setBounds&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;panel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getWidth&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; panel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getHeight&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;// 将按钮3添加到面板panel中&lt;/span&gt;
        panel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;button03&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;h2&gt;
&lt;a id=&quot;4JFormDesigner_179&quot;&gt;&lt;/a&gt;4.JFormDesigner插件&lt;/h2&gt; 
&lt;p&gt;JFormDesigner插件提供了GUI编程可视化与代码自动生成&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;41__183&quot;&gt;&lt;/a&gt;4.1 安装&lt;/h3&gt; 
&lt;p&gt;这里放一个我的云盘链接：链接：https://pan.baidu.com/s/1axTxq5LvWDWsBI_XW6NIPQ 提取码：8ofg。具体安装过程我就不写了，放两个参考链接吧：&lt;a href=&quot;https://blog.csdn.net/qq_36084640/article/details/83987661?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2&amp;amp;utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-2&quot;&gt;参考链接1&lt;/a&gt;，&lt;a href=&quot;https://blog.csdn.net/qq_27453555/article/details/88882067?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-3&amp;amp;utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-3&quot;&gt;参考链接2&lt;/a&gt;。&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;42__186&quot;&gt;&lt;/a&gt;4.2 使用&lt;/h3&gt; 
&lt;p&gt;一个示例：&lt;a href=&quot;https://blog.csdn.net/scc95599/article/details/100714388?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-5&amp;amp;utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-5&quot;&gt;设计登录页面&lt;/a&gt;。博主试了，内容没问题，在使用过程中有几点注意：&lt;/p&gt; 
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202140166618210056134.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt; 
&lt;ul&gt;
&lt;li&gt; &lt;p&gt;组件的大小不固定，但是不能手动设置，只能通过frame / panel的组件间距进行设置&lt;/p&gt; 
  &lt;ul&gt;
&lt;li&gt;frame --》Layout Manger 
    &lt;ul&gt;
&lt;li&gt;horizontal gap ：窗口内面板横间距&lt;/li&gt;
&lt;li&gt;vertical gap：窗口内面板纵间距&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;panel --》Layout Manger 
    &lt;ul&gt;
&lt;li&gt;horizontal gap ：面板内组件横间距&lt;/li&gt;
&lt;li&gt;vertical gap：面板内组件纵间距&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;组件 --》Properties 
    &lt;ul&gt;&lt;li&gt;horizontalAlign：设置对齐方式&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;p&gt;显示效果可以预览&lt;/p&gt; 
  &lt;ul&gt;&lt;li&gt; &lt;p&gt;frame --》Properties&lt;/p&gt; 
    &lt;ul&gt;
&lt;li&gt; &lt;p&gt;title：标题&lt;/p&gt; &lt;/li&gt;
&lt;li&gt; &lt;p&gt;minimumSize：预览大小（高度，宽度）&lt;/p&gt; &lt;p&gt;注：若不再额外设置setBound，就默认使用改值&lt;/p&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;p&gt;编码注意&lt;/p&gt; 
  &lt;ul&gt;
&lt;li&gt;要在构造函数手动设置 
    &lt;ul&gt;
&lt;li&gt;setVistalbe(true)，要放在函数最后&lt;/li&gt;
&lt;li&gt;setDefaultCloseOperation(DISPOSE_ON_CLOSE)，设置前台关闭后程序结束&lt;/li&gt;
&lt;li&gt;setBounds(500,500,450,450)，设置大小与显示位置&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;监听事件 
    &lt;ul&gt;
&lt;li&gt;在登录按钮添加监听事件&lt;/li&gt;
&lt;li&gt;在监听事件方法内调用TextField的getText与setText方法进行操作&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
</description><pubDate>Wed, 19 Oct 2022 20:21:40 +0800</pubDate></item><item><title>【Spring】日志：使用 spring 时日志的多种选择</title><link>https://blog.quwenai.cn/post/10256.html</link><description>
&lt;blockquote&gt; 
 &lt;p&gt;前言：由于篇幅所限，关于日志的基础内容请看我的这篇文章 &lt;a href=&quot;https://blog.csdn.net/weixin_43935927/article/details/111056307&quot;&gt;【Java杂记】日志：Java日志体系，从应用场景到发展历史&lt;/a&gt;…&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;p&gt;Spring 底层选择的是 JCL做为日志门面 + JUL 作为日志实现，而 SpringBoot 选择的是 SLF4J 做为日志门面 + Logback 作为日志实现。那我们本篇就来看看在 Spring 中到底可以如何组合使用各种日志框架+日志实现。&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;1spring__JCL_spring__JUL_4&quot;&gt;&lt;/a&gt;1.spring 底层日志框架 JCL+ spring 底层的日志实现 JUL&lt;/h3&gt; 
&lt;p&gt;首先，引入 spring-context 依赖&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
     &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;org.springframework&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
     &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;spring-context&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
     &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;4.3.20.RELEASE&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;然后我们简单写一个测试类，目的是观察系统日志和应用日志&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MainClass&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
	
    &lt;span class=&quot;token comment&quot;&gt;// import java.util.logging.Logger;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Logger&lt;/span&gt; logger &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MainClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
    	&lt;span class=&quot;token comment&quot;&gt;// 打印系统日志&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;AnnotationConfigApplicationContext&lt;/span&gt; context &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MainConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		&lt;span class=&quot;token comment&quot;&gt;// 打印应用日志&lt;/span&gt;
        logger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;let's go&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;下图是控制台打印的日志:&lt;/p&gt; 
&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202133166618209350528.png&quot; width=&quot;80%&quot;&gt;&lt;h3&gt;
&lt;a id=&quot;2spring__JCL___Log4j_35&quot;&gt;&lt;/a&gt;2.spring 底层日志框架 JCL + 引入并配置 Log4j&lt;/h3&gt; 
&lt;p&gt;首先引入 log4j 的依赖&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;org.springframework&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;spring-context&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;4.3.20.RELEASE&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- 引入log4j的依赖后，日志框架在寻找实现时就会优先使用log4j而不是jul --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;log4j&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;log4j&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;1.2.17&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;测试的代码不用变，因为这里我们使用的日志框架还是 JCL，只不过 Logger 的变成了 log4j 的&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MainClass&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
	
    &lt;span class=&quot;token comment&quot;&gt;// import org.apache.log4j.Logger;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 如果这里还是用 JUL 的话，打印出来的用户应用日志还是上图红色的&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Logger&lt;/span&gt; logger &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MainClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;AnnotationConfigApplicationContext&lt;/span&gt; context &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MainConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        logger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;let's go&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;这里还一定注意，我们必须在resource目录下创建一个 &lt;strong&gt;log4j.properties&lt;/strong&gt; 去对 log4j 进行初始配置，如果没有的话，Log4j 就无法正常打印日志。&lt;/p&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;PS：Log4j 启动时会自动去resource目录寻找名为 log4j 的配置文件并加载，相当于一种约定。&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-properties&quot;&gt;#定义LOG输出级别
#CONSOLE 和 FILE 是日志输出地方（也可以取别的名字，但必须大写）
log4j.rootLogger=INFO, CONSOLE, FILE

#定义日志输出目的地为控制台(显示方式：控制台，普通方式）
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
#可以灵活的指定日志输出格式，下面一行是指定具体的格式
log4j.appender.CONSOLE.layout.ConversionPattern=[%p] %d{yyyy-MM-dd HH:mm:ss} - %m%n

log4j.appender.FILE = org.apache.log4j.FileAppender
log4j.appender.FILE.layout = org.apache.log4j.PatternLayout
log4j.appender.FILE.Append = true
log4j.appender.FILE.File=log/info.log
log4j.appender.FILE.layout.ConversionPattern=[%p] %d{yyyy-MM-dd HH:mm:ss} - %m%n

#显示SQL语句日志配置（info不显示，debug显示执行的sql语句）
log4j.logger.com.xupt.yzh=info
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;日志打印结果如下&lt;/p&gt; 
&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202134166618209452431.png&quot; width=&quot;80%&quot;&gt;&lt;h3&gt;
&lt;a id=&quot;3_Slf4j___Log4j_101&quot;&gt;&lt;/a&gt;3.引入日志框架 Slf4j + 引入并配置 Log4j&lt;/h3&gt; 
&lt;p&gt;首先引入 slf4j 及 log4j 的相关依赖&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;org.springframework&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;spring-context&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;4.3.20.RELEASE&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- log4j的日志实现 --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;log4j&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;log4j&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;1.2.17&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- slf4j日志门面 --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;org.slf4j&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;slf4j-api&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;1.7.28&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- 该包是转换包,实现slf4j-api接口，调用log4j的实现 --&amp;gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;org.slf4j&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;slf4j-log4j12&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;1.7.25&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;因为早期 log4j 压根不知道有一slf4j 的日志门面，所以加入适配器 slf4j-log412.jar 实现 slf4j 的接口，真正实现功能调用。&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;p&gt;我们的 log4j.jar 测试代码需要在创建日志 Logger 那变一下，因为日志门面这个中间层从 jcl 变成 slf4j 了&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MainClass&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
 
    &lt;span class=&quot;token comment&quot;&gt;// import org.slf4j.Logger;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// import org.slf4j.LoggerFactory;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// slf4j 是通过 LoggerFactory 去获取 Logger&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Logger&lt;/span&gt; logger &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LoggerFactory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MainClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// private static Logger logger = Logger.getLogger(MainClass.class.getName());&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;AnnotationConfigApplicationContext&lt;/span&gt; context &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MainConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        logger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;let's go&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;因为引入了 Log4j，所以底层调用的还是 log4j，只不过用户使用的日志门面变了&lt;/p&gt; 
&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202134166618209457944.png&quot; width=&quot;80%&quot;&gt;&lt;h3&gt;
&lt;a id=&quot;4_Slf4j___Logback_158&quot;&gt;&lt;/a&gt;4.引入日志框架 Slf4j + 引入并配置 Logback&lt;/h3&gt; 
&lt;p&gt;还是首先引入 slf4j 和 logback 的依赖&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-xml&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;org.springframework&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;spring-context&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;4.3.20.RELEASE&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;ch.qos.logback&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;logback-core&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;1.2.3&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;ch.qos.logback&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;logback-classic&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;1.2.3&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;org.slf4j&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;groupId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;slf4j-api&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;artifactId&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;1.7.28&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;dependency&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;测试代码同上面第三种情况，因为使用的日志门面都是 slf4j&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MainClass&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
 
    &lt;span class=&quot;token comment&quot;&gt;// import org.slf4j.Logger;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// import org.slf4j.LoggerFactory;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// slf4j 是通过 LoggerFactory 去获取 Logger&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Logger&lt;/span&gt; logger &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LoggerFactory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MainClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// private static Logger logger = Logger.getLogger(MainClass.class.getName());&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; args&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;AnnotationConfigApplicationContext&lt;/span&gt; context &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnnotationConfigApplicationContext&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;MainConfig&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

        logger&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;let's go&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        context&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;同 Log4j，这里的 Logback 必须配置。我们在 resource 目下新建一个 logback.xml 去配置日志格式，级别等&lt;/p&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;同 Log4j，Logback 启动时也会自动在 resource 目录下寻找名为 logback 的配置文件去加载。&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-xml&quot;&gt;&lt;span class=&quot;token prolog&quot;&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;configuration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    
	&lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- 设置如何输出到控制台 --&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;appender&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;CONSOLE&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;ch.qos.logback.core.ConsoleAppender&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;encoder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!--格式化输出：%d表示日期，%thread表示线程名，%-5level：级别从左显示5个字符宽度%msg：日志消息，%n是换行符--&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;pattern&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;pattern&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;encoder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;appender&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
	
    &lt;span class=&quot;token comment&quot;&gt;&amp;lt;!-- 日志级别 --&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;root&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;DEBUG&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;&lt;/span&gt;appender-ref&lt;/span&gt; &lt;span class=&quot;token attr-name&quot;&gt;ref&lt;/span&gt;&lt;span class=&quot;token attr-value&quot;&gt;&lt;span class=&quot;token punctuation attr-equals&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;CONSOLE&lt;span class=&quot;token punctuation&quot;&gt;&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;root&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token tag&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;lt;/&lt;/span&gt;configuration&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;日志输出结果如下&lt;/p&gt; 
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202134166618209424133.png&quot; width=&quot;80%&quot;&gt;&lt;br&gt;&lt;/p&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;问题：如果我同时引入了 Log4j 和 Logback，那 slf4j 到底会调用哪个日志实现？log4j &amp;gt; logback &amp;gt; jul&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;h3&gt;
&lt;a id=&quot;5Spring4x__236&quot;&gt;&lt;/a&gt;5.Spring4.x 底层使用的日志技术&lt;/h3&gt; 
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202135166618209549409.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt; 
&lt;p&gt;我们从这里可以看出来，spring4.x 获取的日志对象中，Logger 对象是 JCL 的 ，而他底层搭配的技术点就是先去找 Log4j的日志实现，若没有找到，底层去找 jdk 的日志框架，压根不支持 Logback，Log4j2 的日志技术。&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;6Spring5x__243&quot;&gt;&lt;/a&gt;6.Spring5.x 底层使用的日志技术&lt;/h3&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt; &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LogApi&lt;/span&gt; logApi &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LogApi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;JUL&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
 &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;   
     &lt;span class=&quot;token class-name&quot;&gt;ClassLoader&lt;/span&gt; cl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LogFactory&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getClassLoader&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
     &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;  
         &lt;span class=&quot;token comment&quot;&gt;// 第一步:先尝试去加载 log4j2的日志框架    &lt;/span&gt;
         cl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;loadClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;org.apache.logging.log4j.spi.ExtendedLogger&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
         logApi &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LogApi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;LOG4J&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
     &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  
     &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt; ex1&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;   
         &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;   
             &lt;span class=&quot;token comment&quot;&gt;// 第二步:尝试去加载 LogApi.SLF4J_LAL     &lt;/span&gt;
             cl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;loadClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;org.slf4j.spi.LocationAwareLogger&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; 
             logApi &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LogApi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SLF4J_LAL&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
         &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;   
         &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt; ex2&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;    
             &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;   
                 &lt;span class=&quot;token comment&quot;&gt;// 尝试去加载slf4j的日志实现   &lt;/span&gt;
                 cl&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;loadClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;org.slf4j.Logger&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;   
                 logApi &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;LogApi&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;SLF4J&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;  
             &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;    
             &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt; ex3&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;   
                 &lt;span class=&quot;token comment&quot;&gt;// 使用原生的JUL    &lt;/span&gt;
             &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;   
         &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
     &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;  
 &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;
</description><pubDate>Wed, 19 Oct 2022 20:21:35 +0800</pubDate></item><item><title>【JavaWeb】JDBC：基本操作及封装DBUtil</title><link>https://blog.quwenai.cn/post/10255.html</link><description>
&lt;h2&gt;
&lt;a id=&quot;1_0&quot;&gt;&lt;/a&gt;1.连接数据库及关闭&lt;/h2&gt; 
&lt;p&gt;首先，肯定是引入相应数据库的jar包，然后连接数据库的基本流程：DriverManger -&amp;gt; Connection -&amp;gt; Statement。这里再说一下statement：&lt;/p&gt; 
&lt;ul&gt;
&lt;li&gt;一个statement执行一条sql&lt;/li&gt;
&lt;li&gt;一个Connection可以get多个statement&lt;/li&gt;
&lt;li&gt;PreparedStatement是经过预编译的Statement，更高效&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// 1.注册驱动，将mysql得到驱动加载到JVM&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;com.mysql.jdbc.Driver&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 2.获取连接对象，Connection&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;Connection&lt;/span&gt; conn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DriverManager&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getConnection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;jdbc:mysql://localhost:3306/jdbc&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;123456&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;// 3.获取执行对象Statemet（PreparedStatement）&lt;/span&gt;
&lt;span class=&quot;token class-name&quot;&gt;PreparedStatement&lt;/span&gt; pst &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getPreparedStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 4.crud...&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;// 5.关闭，先开后关&lt;/span&gt;
pst&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;h2&gt;
&lt;a id=&quot;2CRUD_21&quot;&gt;&lt;/a&gt;2.CRUD&lt;/h2&gt; 
&lt;h3&gt;
&lt;a id=&quot;21__executeUpdate_22&quot;&gt;&lt;/a&gt;2.1 增/删/改 (executeUpdate)&lt;/h3&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;testCUD&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SQLException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;// 连接数据库&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;com.mysql.jdbc.Driver&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Connection&lt;/span&gt; conn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DriverManger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getConnection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;jdbc:mysql://localhost:3306/jdbc&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;123456&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;PreparedStatement&lt;/span&gt; pst &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getPreparedStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// 调用 executeUpdate() 进行增删改操作，返回影响的行数&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 注意：当要使用外部传来的参数时，有两种方案：&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//      1.SQL 拼接的方法，即通过 &quot;+&quot; 进行字符串拼接&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//      2.采用占位符 &quot;?&quot; + setObject(index，param)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; row &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pst&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeUpdate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;insert into user values(？,？)&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 注意：这里直接 setObject 其实是偷懒的方法，正常我们应该是说清楚类型，比如 setString()，setInt()...&lt;/span&gt;
    pst&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;张三&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;；
    pst&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;成功插入&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; row &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;行&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// 改&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; row &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pst&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeUpdate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;update user set name='李四' where name='张三'&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;成功删除&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;row&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;行&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// 删&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; row &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pst&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeUpdate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;delete from user where id=1&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;row &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;out&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;成功删除&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;row&lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;行&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    pst&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;h3&gt;
&lt;a id=&quot;22_executeQuery_59&quot;&gt;&lt;/a&gt;2.2 查（executeQuery）&lt;/h3&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;testQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SQLException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;com.mysql.jdbc.Driver&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Connection&lt;/span&gt; conn &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DriverManger&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getConnection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;jdbc:mysql://localhost:3306/jdbc&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;123456&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;PreparedStatement&lt;/span&gt; pst &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getPreparedStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// 调用 executeQuery 进行查询，返回包含结果集的 ResultSet&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 注意：同上面insert一样，这里也是既可采用SQL拼接，也可通过占位符+setObject()&lt;/span&gt;
    &lt;span class=&quot;token class-name&quot;&gt;Resultset&lt;/span&gt; rs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pst&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;select * from user where id=&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    pst&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setInt&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// 从 ResultSet 中获取查询结果，getObject&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 注意：getObject() 是偷懒用法，实际是要确定类型的，比如 getString()、getInt()...&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
        rs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        rs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;age&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    rs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    pst&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    conn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;h2&gt;
&lt;a id=&quot;3DBUtil_85&quot;&gt;&lt;/a&gt;3.封装工具类：DBUtil&lt;/h2&gt; 
&lt;p&gt;现有JDBC存在的问题：&lt;/p&gt; 
&lt;ul&gt;
&lt;li&gt;由于每个dao都需要连接，若每个dao都与数据库建立一个连接开销大 --&amp;gt; 一个连接产生多个statement&lt;/li&gt;
&lt;li&gt;重复代码多，比如添加数据 executeUpdate 后还需要 setObjcet&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以，可以将常用方法封装，提高代码复用。由于是工具类，所以方法都会写成static静态方法，方便调用。&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;com&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;xupt&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;gradutate&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;ghn&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;APP&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;dao&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;token namespace&quot;&gt;java&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DBUtil&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; DRIVER_CLASS_NAME &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;com.mysql.jdbc.Driver&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; URL &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;jdbc:mysql://localhost:3306/graduate_file?useUnicode=true&amp;amp;characterEncoding=utf-8&amp;amp;allowMultiQueries=true&amp;amp;serverTimezone=GMT&amp;amp;useSSL=false&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; USERNAME &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; PASSWORD &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;123456&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Connection&lt;/span&gt; con &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PreparedStatement&lt;/span&gt; pst &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ResultSet&lt;/span&gt; rs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/**
     * 创建连接
     */&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Connection&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getConnection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SQLException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;Class&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;DRIVER_CLASS_NAME&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DriverManager&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getConnection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;URL&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; USERNAME&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; PASSWORD&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/**
     * 获取执行的statement
     */&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PreparedStatement&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createPreparedStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; params&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;throws&lt;/span&gt;
            &lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SQLException&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
        pst &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getConnection&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;prepareStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;params &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; i &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt; params&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;length&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;++&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
                pst&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i &lt;span class=&quot;token operator&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; params&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; pst&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/**
     * 封装增删改操作（executeUpdate），入参sql和参数，不用再setObject
     */&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;saveAndUpdate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; params&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            pst &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createPreparedStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; params&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; pst&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeUpdate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SQLException&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;printStackTrace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;finally&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            &lt;span class=&quot;token function&quot;&gt;closeAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;con&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; pst&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/**
     * 封装查询操作（excuteQuery），但还要手动解析ResultSet（也可以再封装成一个通用方法）
     */&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ResultSet&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt; sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; params&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            pst &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;createPreparedStatement&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;sql&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; params&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            rs &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; pst&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;executeQuery&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; rs&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;ClassNotFoundException&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;SQLException&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;printStackTrace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;/**
     * 关闭所有连接
     */&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;closeAll&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Connection&lt;/span&gt; con&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;PreparedStatement&lt;/span&gt; pst&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ResultSet&lt;/span&gt; rs&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;rs &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
                rs&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;pst &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
                pst&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;con &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
                con&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;SQLException&lt;/span&gt; e&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
            e&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;printStackTrace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt; 
&lt;h2&gt;
&lt;a id=&quot;4DBCP_183&quot;&gt;&lt;/a&gt;4.DBCP连接池&lt;/h2&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-java&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;JDBCUtils&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;//创建BasicDataSource对象&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BasicDataSource&lt;/span&gt; datasource &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;BasicDataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token comment&quot;&gt;//静态代码块,实现必要参数设置&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
		datasource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setDriverClassName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;com.mysql.cj.jdbc.Driver&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		datasource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setUrl&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;jdbc:mysql://localhost:3306/gjp?serverTimezone=GMT&amp;amp;useSSL=false&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		datasource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setUsername&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;root&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		datasource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setPassword&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;123456&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		datasource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setMaxActive&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		datasource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setMaxIdle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		datasource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setMinIdle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
		datasource&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;setInitialSize&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;DataSource&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getDataSource&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;!-- --&gt;&lt;/span&gt;
		&lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; datasource&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    
    &lt;span class=&quot;token comment&quot;&gt;// Connection conn = datasource.getConnection();&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
</description><pubDate>Wed, 19 Oct 2022 20:21:29 +0800</pubDate></item><item><title>Docker 的产生背景</title><link>https://blog.quwenai.cn/post/10254.html</link><description>
&lt;h3&gt;
&lt;a id=&quot;1PaaS__1&quot;&gt;&lt;/a&gt;1.PaaS 面临的问题&lt;/h3&gt; 
&lt;p&gt;PaaS 项目被大家接纳的一个主要原因，就是它提供了一种名叫“应用托管”的能力。&lt;/p&gt; 
&lt;p&gt;PaaS 之所以能够帮助用户大规模部署应用到集群里，是因为它提供了一套应用打包的功能。可偏偏就是这个打包功能，却成了 PaaS 日后不断遭到用户诟病的一个“软肋”。&lt;/p&gt; 
&lt;p&gt;出现这个问题的根本原因是，一旦用上了 PaaS，用户就必须为每种语言、每种框架，甚至每个版本的应用维护一个打好的包。这个打包过程，没有任何章法可循，更麻烦的是，明明在本地运行得好好的应用，却需要做很多修改和配置工作才能在 PaaS 里运行起来。而这些修改和配置，并没有什么经验可以借鉴，基本上得靠不断试错，直到你摸清楚了本地应用和远端 PaaS 匹配的“脾气”才能够搞定。&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;2Docker__9&quot;&gt;&lt;/a&gt;2.Docker 产生&lt;/h3&gt; 
&lt;p&gt;Docker 镜像解决的，恰恰就是打包这个根本性的问题。所谓 Docker 镜像，其实就是一个压缩包。但是这个压缩包里的内容，比 PaaS 的应用可执行文件 + 启停脚本的组合就要丰富多了。实际上，大多数 Docker 镜像是直接由一个完整操作系统的所有文件和目录构成的，所以这个压缩包里的内容跟你本地开发和测试环境用的操作系统是完全一样的。&lt;/p&gt; 
&lt;p&gt;只要有这个压缩包在手，你就可以使用某种技术创建一个“沙盒”，在“沙盒”中解压这个压缩包，然后就可以运行你的程序了。在这个过程中，你完全不需要进行任何配置或者修改，因为这个压缩包赋予了你一种极其宝贵的能力：本地环境和云端环境的高度一致！&lt;/p&gt; 
&lt;p&gt;Docker 项目给 PaaS 世界带来的“降维打击”，其实是提供了一种非常便利的打包机制。这种机制直接打包了应用运行所需要的整个操作系统，从而保证了本地环境和云端环境的高度一致，避免了用户通过“试错”来匹配两种不同运行环境之间差异的痛苦过程。&lt;/p&gt; 
&lt;p&gt;Docker 项目在短时间内迅速崛起的三个重要原因：&lt;/p&gt; 
&lt;ol&gt;
&lt;li&gt;Docker 镜像通过技术手段解决了 PaaS 的根本性问题；&lt;/li&gt;
&lt;li&gt;Docker 容器同开发者之间有着与生俱来的密切关系；&lt;/li&gt;
&lt;li&gt;PaaS 概念已经深入人心的完美契机。&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt; 
 &lt;p&gt;注：除了 Docker 容器，还有 CoreOs 研发的 rkt 容器（CoreOs 是当时 Docker 的第二大代码贡献者，分道扬镳是因为目标定位不同）&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;h3&gt;
&lt;a id=&quot;3_26&quot;&gt;&lt;/a&gt;3.三个应用部署时代&lt;/h3&gt; 
&lt;p&gt;&lt;strong&gt;传统部署时代&lt;/strong&gt;&lt;/p&gt; 
&lt;p&gt;早期，各个组织机构在物理服务器上运行应用程序。无法为物理服务器中的应用程序定义资源边界，这会导致资源分配问题。 例如，如果在物理服务器上运行多个应用程序，则可能会出现一个应用程序占用大部分资源的情况， 结果可能导致其他应用程序的性能下降。 一种解决方案是在不同的物理服务器上运行每个应用程序，但是由于资源利用不足而无法扩展， 并且维护许多物理服务器的成本很高。&lt;/p&gt; 
&lt;p&gt;&lt;strong&gt;虚拟化部署时代&lt;/strong&gt;&lt;/p&gt; 
&lt;p&gt;作为解决方案，引入了虚拟化。虚拟化技术允许你在单个物理服务器的 CPU 上运行多个虚拟机（VM）。 虚拟化允许应用程序在 VM 之间隔离，并提供一定程度的安全，因为一个应用程序的信息 不能被另一应用程序随意访问。&lt;br&gt; 虚拟化技术能够更好地利用物理服务器上的资源，并且因为可轻松地添加或更新应用程序 而可以实现更好的可伸缩性，降低硬件成本等等。&lt;br&gt; 每个 VM 是一台完整的计算机，在虚拟化硬件之上运行所有组件，包括其自己的操作系统。&lt;/p&gt; 
&lt;p&gt;&lt;strong&gt;容器部署时代&lt;/strong&gt;&lt;/p&gt; 
&lt;p&gt;容器类似于 VM，但是它们具有被放宽的隔离属性，可以在应用程序之间共享操作系统（OS）。 因此，容器被认为是轻量级的。容器与 VM 类似，具有自己的文件系统、CPU、内存、进程空间等。 由于它们与基础架构分离，因此可以跨云和 OS 发行版本进行移植。&lt;br&gt; 容器因具有许多优势而变得流行起来。下面列出的是容器的一些好处：&lt;/p&gt; 
&lt;ul&gt;
&lt;li&gt;敏捷应用程序的创建和部署：与使用 VM 镜像相比，提高了容器镜像创建的简便性和效率。&lt;/li&gt;
&lt;li&gt;持续开发、集成和部署：通过快速简单的回滚（由于镜像不可变性），支持可靠且频繁的 容器镜像构建和部署。&lt;/li&gt;
&lt;li&gt;关注开发与运维的分离：在构建/发布时而不是在部署时创建应用程序容器镜像， 从而将应用程序与基础架构分离。&lt;/li&gt;
&lt;li&gt;可观察性：不仅可以显示操作系统级别的信息和指标，还可以显示应用程序的运行状况和其他指标信号。&lt;/li&gt;
&lt;li&gt;跨开发、测试和生产的环境一致性：在便携式计算机上与在云中相同地运行。&lt;/li&gt;
&lt;li&gt;跨云和操作系统发行版本的可移植性：可在 Ubuntu、RHEL、CoreOS、本地、 Google Kubernetes Engine 和其他任何地方运行。&lt;/li&gt;
&lt;li&gt;以应用程序为中心的管理：提高抽象级别，从在虚拟硬件上运行 OS 到使用逻辑资源在 OS 上运行应用程序。&lt;/li&gt;
&lt;li&gt;松散耦合、分布式、弹性、解放的微服务：应用程序被分解成较小的独立部分， 并且可以动态部署和管理 - 而不是在一台大型单机上整体运行。&lt;/li&gt;
&lt;li&gt;资源隔离：可预测的应用程序性能。&lt;/li&gt;
&lt;li&gt;资源利用：高效率和高密度。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202125166618208510908.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;安装 Docker 可以参考这篇文章：&lt;a href=&quot;https://yeasy.gitbook.io/docker_practice/install/ubuntu#ce-shi-docker-shi-fou-an-zhuang-zheng-que&quot;&gt;https://yeasy.gitbook.io/docker_practice/install/ubuntu#ce-shi-docker-shi-fou-an-zhuang-zheng-que&lt;/a&gt;。如果启动失败，执行一下 sudo chmod 666 /var/run/docker.sock&lt;/p&gt; 
&lt;/blockquote&gt;
</description><pubDate>Wed, 19 Oct 2022 20:21:25 +0800</pubDate></item><item><title>【Git】基本使用：核心命令总结（附SourceTree）</title><link>https://blog.quwenai.cn/post/10253.html</link><description>
&lt;p&gt;在上一篇&lt;a href=&quot;https://blog.csdn.net/weixin_43935927/article/details/110290550&quot;&gt;【Git】介绍、与SVN对比、支持的通信协议&lt;/a&gt; 我们介绍了 Git 及它支持的通信协议，这篇我们就来看看如何使用Git。&lt;/p&gt; 
&lt;h2&gt;
&lt;a id=&quot;1Git__1&quot;&gt;&lt;/a&gt;1.Git 核心命令&lt;/h2&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;git 客户端安装（无脑下一步就行）：&lt;/p&gt; 
 &lt;ul&gt;
&lt;li&gt; &lt;p&gt;官方客户端： &lt;a href=&quot;https://git-scm.com/downloads&quot;&gt;httpsd://git-scm.com/downloads&lt;/a&gt;&lt;/p&gt; &lt;/li&gt;
&lt;li&gt; &lt;p&gt;其它客户端：&lt;a href=&quot;https://tortoisegit.org/download&quot;&gt;https://tortoisegit.org/download&lt;/a&gt;&lt;/p&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt; 
&lt;h3&gt;
&lt;a id=&quot;11__9&quot;&gt;&lt;/a&gt;1.1 配置管理&lt;/h3&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;在刚装完git的需要配置 email 和 name，然后才能使用 Git，那怎么配置呢？&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-sh&quot;&gt;#查看所有配置信息
git config -l

#查看系统级别配置（git安装目录下etc）
git config --system --list
#查看全局级别配置（当前用户之下表示的是全局级别的）
git config --global --list
#查看仓库级别配置（当前仓库级别下的.git&amp;gt;config文件）
git config --local --list

#添加配置
#用户信息配置
git config --global user.name &quot;yourusername&quot;
git config --global user.email &quot;youremail@email.com&quot;
#要求 Git 版本 1.9.5 以上
git config --global push.default simple   
#让Git不要管Windows/Unix换行符转换的事  
git config --global core.autocrlf false     

#删除配置
git config --unset user.name
&lt;/code&gt;&lt;/pre&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;注：覆盖优先级为local &amp;gt; global &amp;gt; system。优先读取local，其次是global，最后是system。&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;h3&gt;
&lt;a id=&quot;12_Git_40&quot;&gt;&lt;/a&gt;1.2 本地初始化Git仓库&lt;/h3&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;如何初始化一个 Git 本地仓库 ？&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-cmd&quot;&gt;#当前目录初始化为 git 本地仓库（在同级目录下会出现一个隐藏的.git文件）
git init  &amp;lt;directory&amp;gt;

#删除本地仓库=删除.git文件夹

#基于远程仓库克隆至本地
git clone &amp;lt;remote_url
&lt;/code&gt;&lt;/pre&gt; 
&lt;h3&gt;
&lt;a id=&quot;13__54&quot;&gt;&lt;/a&gt;1.3 本地添加&lt;/h3&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;如何将工作空间的文件添加到暂存区？&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-sh&quot;&gt;#添加指定文件到暂存区
git add &amp;lt;fileName&amp;gt;
#添加指定目录至暂存区
git add &amp;lt;directory&amp;gt;
#添加所有
git add -A

#将指定目录及子目录移除出暂存区（注：本地文件还在）
git rm --cached &amp;lt;target&amp;gt; -r

#查看提交状态。如果还未提交到暂存区的文件会标红，在暂存区的文件会标绿。
git status 

#添加勿略配置文件 .gitignore
&lt;/code&gt;&lt;/pre&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;如果我们不想让某个文件被git管理起来，所以如何让 git 忽略这个文件呢？&lt;/p&gt; 
 &lt;p&gt;在仓库的根目录下创建一个.gitignore 文件，写入不想让git管理的文件。两点注意&lt;/p&gt; 
 &lt;ol&gt;
&lt;li&gt;.gitignore本身就需要忽略，所以此文件也要写进去&lt;/li&gt;
&lt;li&gt;.gitignore 文件中可以使用“#”字符开头表示注释，文件夹路径是用“/”字符，文件名可以使用通配符“*”，另外还可以使用“!”字符表示排除。比如 * .class&lt;/li&gt;
&lt;li&gt;.gitignore只能忽略那些原来没有被追踪的文件，如果某些文件已经被纳入了版本管理中，则修改.gitignore是无效的。那么解决方法就是先把本地缓存删除（改变成未被追踪状态），然后再提交&lt;/li&gt;
&lt;li&gt;每一个文件夹沟可以创建自己的“.gitignore”文件，如果它上层的文件夹也有“.gitignore”文件，这个文件夹也会受到它的影响&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt; 
&lt;h3&gt;
&lt;a id=&quot;14__84&quot;&gt;&lt;/a&gt;1.4 本地提交&lt;/h3&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;如何将暂存区的文件提交到本地仓库？&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-sh&quot;&gt;#提交指定文件到本地仓库
git commit &amp;lt;fileName&amp;gt;
#全部提交
git commit -a 
#-m编写提交注释（注：如果在commit命令中指定了-m，那么就不会再弹出vim让写提交注释了）
git commit &amp;lt;fileName&amp;gt; -m &amp;lt;注释&amp;gt;
#快捷提交至本地仓库
git commit -am '快添加与提交全部暂存区文件'
&lt;/code&gt;&lt;/pre&gt; 
&lt;h3&gt;
&lt;a id=&quot;15__98&quot;&gt;&lt;/a&gt;1.5 日志管理&lt;/h3&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;如何查看我当前库的历史提交信息？&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-sh&quot;&gt;#查看当前分支下所有提交日志
git log
#查看当前分支下所有提交日志
git log {branch}
# 单行显示日志
git log --oneline
# 比较两个版本的区别
git log master..experiment

#以图表的方式显示提交合并网络
git log --pretty=format:'%h %s' --graph
&lt;/code&gt;&lt;/pre&gt; 
&lt;h3&gt;
&lt;a id=&quot;17__115&quot;&gt;&lt;/a&gt;1.7 分支管理&lt;/h3&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;如果我现在有多个开发人员，开发不同模块，都在master上写吗？&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-sh&quot;&gt;#查看当前分支, -avv查看远程分支
git branch [-avv]

#基于当前分支新建分支
git branch &amp;lt;branch name&amp;gt;
#基于提交新建分支
git branch &amp;lt;branch name&amp;gt; &amp;lt;commit id&amp;gt;

#切换分支
git checkout &amp;lt;branch name&amp;gt;

#删除分支（注：删除时必须在其他分支上）
git branch -d {dev}

#合并分支（比如将要将dev分支的内容合并到master分支，那么要在master分支执行该命令）
#注: 如果因冲突导致自动合并失败，此时 status 为mergeing 状态。需要手动修改后重新提交（commit） 
git merge &amp;lt;merge target&amp;gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;分支规范：&lt;/p&gt; 
 &lt;ul&gt;
&lt;li&gt; &lt;p&gt;master分支：主分支。保持稳定&lt;/p&gt; 
   &lt;ul&gt;
&lt;li&gt;不允许直接往这个分支提交代码，只允许往这个分支发起 merge request&lt;/li&gt;
&lt;li&gt;只允许 release 分支和 hotfix 分支进行合流 , 所有在 Master 分支上的 Commit 应该Tag&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;p&gt;develop分支：开发分支。相对稳定的分支，用于日常开发，包括代码优化、功能性开发。&lt;/p&gt; &lt;/li&gt;
&lt;li&gt; &lt;p&gt;feature分支：特性分支。&lt;/p&gt; 
   &lt;ul&gt;
&lt;li&gt;从develop分支拉取，用于下个迭代版本的功能特性开发。&lt;/li&gt;
&lt;li&gt;功能开发完毕合并到develop 分支, 合并完分支后一般会删点这个Feature分支，但是我们也可以保留。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;p&gt;release分支：发布分支。&lt;/p&gt; 
   &lt;ul&gt;
&lt;li&gt; &lt;p&gt;从develop分支拉取，用于回归测试，bug修复&lt;/p&gt; &lt;/li&gt;
&lt;li&gt; &lt;p&gt;发布完成后打tag并合入master和develop， (注：一旦打了Release分支之后不要从Develop分支上合并新的改动到Release分支)&lt;/p&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;p&gt;hotfix分支：热更新分支。&lt;/p&gt; 
   &lt;ul&gt;
&lt;li&gt; &lt;p&gt;从develop分支拉取，用于紧急修复上线版本的问题&lt;/p&gt; &lt;/li&gt;
&lt;li&gt; &lt;p&gt;修复后打tag并合入master和develop&lt;/p&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt; 
&lt;h3&gt;
&lt;a id=&quot;18_tag__165&quot;&gt;&lt;/a&gt;1.8 tag 管理&lt;/h3&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;Commitid不容易记住，能不能用一种比较独特的方式去记住每个版本？答：Commitid相当于IP，Tag相当于域名。&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-sh&quot;&gt;#查看当前仓库的标签列表
git tag
#创建分支
git tag &amp;lt;tag name&amp;gt; &amp;lt;branch name&amp;gt;
#删除分支
git tag -d &amp;lt;tag name&amp;gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;h3&gt;
&lt;a id=&quot;19__178&quot;&gt;&lt;/a&gt;1.9 远程仓库&lt;/h3&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;本地仓库说完了，那如果我不同地区的人要合作开发怎么搞？答：远程仓库，GitHub或Gitee。&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-sh&quot;&gt;#查看远程配置
git remote [-v]
#添加远程仓库地址（注：远程仓库一般命名为origin，不同的远程仓库需要配置不同的名字; url一般多采用http协议）
git remote add &amp;lt;github name&amp;gt; &amp;lt;url&amp;gt;
#删除远程地址
git remote remove &amp;lt;github name&amp;gt; 

#拉取代码到本地
git clone &amp;lt;url&amp;gt;
git clone &amp;lt;url&amp;gt; &amp;lt;filepath&amp;gt;

#上传新分支至远程
git push -u &amp;lt;github name&amp;gt; &amp;lt;branch name&amp;gt;
或
#将本地分支与远程建立关联
git --track --set-upstream-to=&amp;lt;github name&amp;gt;/&amp;lt;remote branch&amp;gt; &amp;lt;local branch&amp;gt;
#直接使用git push 时只会上传的到一个远程仓库的一个分支，是上面 --track 设置的仓库和相应分支
git push 

#拉取远端代码并与当前分支合并= git fetch + git merge
#注：如果不指定参数则是当前本地分支关联的远程分支
git pull &amp;lt;url&amp;gt; &amp;lt;branch&amp;gt;
或
#提取远程仓库(如果服务器有修改，不会到本地)
git fetch
#合并冲突(如果只是本地或远程一端修改的话，就不会冲突)
git merge &amp;lt;branch&amp;gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;另外，无论是推送还是拉代码，需要有这样一个权限，也就是说你目前使用的这台电脑是否安全，如果不安全，人家不会让你去推送，而github采用的是RAS加密方式通讯&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-cmd&quot;&gt;#1. 查看本地是否已经有公钥 
cat ~/.ssh/id_rsa.pub

#2. 如果没有，则在本地中生成一个 ssh key。输入后一直回车即可完成。
ssh-keygen -t rsa -C youremail.com 

#3. 把这个key告诉github/码云
Github Settings -&amp;gt; SSH and GPG keys --&amp;gt; New SSH key --&amp;gt; 将公钥粘贴并保存
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;另外，在向别人的代码库推送代码时必须要先拥有项目的开发者权限&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;110__225&quot;&gt;&lt;/a&gt;1.10 代码回滚&lt;/h3&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;如果线上新提交的代码有问题了，那怎么回退到上一个版本呢？&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-cmd&quot;&gt;#回退
#仅仅只是撤销已提交的版本库，不会修改暂存区和工作区
git reset --soft &amp;lt;commitid&amp;gt;
#仅仅只是撤销已提交的版本库和暂存区，不会修改工作区
git reset --mixed &amp;lt;commitid&amp;gt;
#彻底将工作区、暂存区和版本库记录恢复到指定的版本库
git reset --hard &amp;lt;commitid&amp;gt;

#回滚
git revert -n &amp;lt;commitid&amp;gt;
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;关于回滚，一般步骤是&lt;/p&gt; 
&lt;ol&gt;
&lt;li&gt;使用 git log 命令，查看分支提交历史，确认需要回退的版本&lt;/li&gt;
&lt;li&gt;使用 git reset 或者 git revert 命令，进行版本回退&lt;/li&gt;
&lt;li&gt;使用 git push 命令，推送至远程分支（必须！！否则只能本地回退）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这里就重点说一下 git reset 和 git revert 的区别&lt;/p&gt; 
&lt;p&gt;举个例子，比如在master分支，有以下提交历史（PS：该示例出自&lt;a href=&quot;&quot;&gt;这篇文章&lt;/a&gt;）:&lt;/p&gt; 
&lt;pre&gt;&lt;code&gt;42eae13 (HEAD -&amp;gt; master) 第四次修改
97ea0f9 第三次修改
e50b7c2 第二次修改
3a52650 第一次修改
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;可以看到，master最新版本为第四次修改。&lt;/p&gt; 
&lt;p&gt;如果发现，在第四次修改有错误，需要回滚到第三次修改，就可以用reset命令来回退。&lt;/p&gt; 
&lt;p&gt;执行 git reset --hard 97ea0f9,这个时候，git的提交历史变为:&lt;/p&gt; 
&lt;pre&gt;&lt;code&gt;97ea0f9 (HEAD -&amp;gt; master) 第三次修改
e50b7c2 第二次修改
3a52650 第一次修改
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;可以看到master当前指向97ea0f9这个版本，我们回到了第三次修改。&lt;/p&gt; 
&lt;p&gt;使用 reset 命令，Git 会把要回退版本之后提交的修改都删除掉。要从第四次修改回退到第一次修改，那么会删除第二、三、四次的修改。【注：这里并不是真正的物理删除】&lt;/p&gt; 
&lt;p&gt;那如果发现第三次修改有错误，想要恢复第三次修改，却要保留第四次修改呢？&lt;/p&gt; 
&lt;p&gt;这个时候就可以用revert命令：&lt;/p&gt; 
&lt;pre&gt;&lt;code&gt;git revert -n 97ea0f9
git commit -m &quot;恢复第三次修改&quot;
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;Git提交历史会变成：&lt;/p&gt; 
&lt;pre&gt;&lt;code&gt;33b8b30 (HEAD -&amp;gt; master) Revert &quot;恢复第三次修改&quot;
42eae13 第四次修改
97ea0f9 第三次修改
e50b7c2 第二次修改
3a52650 第一次修改
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;实际上，Git把第三次修改从提交中剔除(还原)了，还保留了第四次修改，并且产生了新的commit_id。&lt;/p&gt; 
&lt;p&gt;在实际生产环境中，代码是基于master分支发布到线上的，会有多人进行提交。可能会碰到自己或团队其他成员开发的某个功能在上线之后有Bug,需要及时做代码回滚的操作。&lt;/p&gt; 
&lt;p&gt;在确认要回滚的版本之后，如果别人没有最新提交，那么就可以直接用reset命令进行版本回退，否则，就可以考虑使用revert命令进行还原修改，不能影响到别人的提交。或者说，除非在非常有把握的情况下，否则不要使用reset强推。&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;_293&quot;&gt;&lt;/a&gt;小结&lt;/h3&gt; 
&lt;p&gt;把常用命令再画个图来总结一下：&lt;br&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202121166618208174272.png&quot; alt=&quot;在这里插入图片描述&quot;&gt;&lt;/p&gt; 
&lt;h2&gt;
&lt;a id=&quot;2_Git_299&quot;&gt;&lt;/a&gt;2.工具使用 Git&lt;/h2&gt; 
&lt;p&gt;一般我们在实际开发更多是用现成IDE自带的GIT工具或者图形化工具去操作Git&lt;/p&gt; 
&lt;ul&gt;
&lt;li&gt;IDEA操作GIT：&lt;a href=&quot;https://juejin.cn/post/6844903926576185358&quot;&gt;IDEA中的Git操作，看这一篇就够了！&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;可视化工具 SourceTree：这里放上我自己用的破解版（链接：&lt;a href=&quot;https://pan.baidu.com/s/1i82Fkeb5ZzuLtdarWSlVDw&quot;&gt;https://pan.baidu.com/s/1i82Fkeb5ZzuLtdarWSlVDw&lt;/a&gt; 提取码：rubp）&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt; 
 &lt;p&gt;后面博主有时间了会再出一篇搭建 Git 私服的教程（先挖个坑）…&lt;/p&gt; 
&lt;/blockquote&gt;
</description><pubDate>Wed, 19 Oct 2022 20:21:21 +0800</pubDate></item><item><title>【项目杂记】Docker 挂载 Nginx 配置注意事项</title><link>https://blog.quwenai.cn/post/10252.html</link><description>
&lt;p&gt;在&lt;a href=&quot;https://blog.csdn.net/weixin_43935927/article/details/113830663&quot;&gt;上一篇文章&lt;/a&gt;我们介绍了如何使用 Docker 及构建 Dockerfile，本篇来记录一下我在使用 Docker 部署 Nginx 是遇到的问题。&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;1_2&quot;&gt;&lt;/a&gt;1.说说挂载&lt;/h3&gt; 
&lt;ul&gt;
&lt;li&gt;挂载含义：&lt;strong&gt;启动时覆盖，运行时新增共享&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;挂载作用：docker 一般是非持久化存储，重启关闭可能导致数据丢失&lt;/li&gt;
&lt;li&gt;挂载内容： 
  &lt;ul&gt;
&lt;li&gt;日志（启动失败时可以查看）&lt;/li&gt;
&lt;li&gt;配置文件（先写好）&lt;/li&gt;
&lt;li&gt;运行数据&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
&lt;a id=&quot;2Docker__Nginx__11&quot;&gt;&lt;/a&gt;2.Docker 挂载 Nginx 两点注意&lt;/h3&gt; 
&lt;p&gt;两点注意：&lt;/p&gt; 
&lt;p&gt;1）我们不是直接挂载 nginx.conf 而是 conf.d 目录下的 server 配置&lt;/p&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;注：先使用原文件，启动后再修改，易报错&lt;/p&gt; 
&lt;/blockquote&gt; 
&lt;p&gt;相应的配置文件如下（只包含 server 部分）&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-text&quot;&gt;server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;2）里面的 proxy_pass 配置转发 IP&lt;/p&gt; 
&lt;ul&gt;
&lt;li&gt;访问主机：主机 IP:8080（比如代理一个 java 程序 43.105.39.120:8080)&lt;/li&gt;
&lt;li&gt;访问其他容器：容器 IP（比如代理 redis 172.17.0.3）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
&lt;a id=&quot;3Docker__Nginx__71&quot;&gt;&lt;/a&gt;3.Docker 挂载 Nginx 命令示例&lt;/h3&gt; 
&lt;p&gt;命令示例：&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-sh&quot;&gt;docker run -d --name mynginx -p 80:80
	   -v /data/logs:/var/nginx/log    // 日志目录
	   -v /data/conf:/etc/nginx/conf.d // 配置目录（挂的是 conf.d 目录）
	   -v /data/data:/data 			   // 数据目录
	   nginx
&lt;/code&gt;&lt;/pre&gt;
</description><pubDate>Wed, 19 Oct 2022 20:21:17 +0800</pubDate></item><item><title>【Docker】网络模式、常用命令，及构建 Dockerfile</title><link>https://blog.quwenai.cn/post/10251.html</link><description>
&lt;h3&gt;
&lt;a id=&quot;1Docker__0&quot;&gt;&lt;/a&gt;1.Docker 网络模式&lt;/h3&gt; 
&lt;blockquote&gt; 
 &lt;p&gt;虚拟机两种联网方式&lt;/p&gt; 
 &lt;ul&gt;
&lt;li&gt;桥接：主机 IP --&amp;gt; (网桥) ==&amp;gt; 同级 IP 【同级网关，可以外访】&lt;/li&gt;
&lt;li&gt;NAT：主机 IP --&amp;gt; (交换机) ==&amp;gt; 下级 IP 【主机网关，只能内访】&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt; 
&lt;ul&gt;
&lt;li&gt;bridge（默认）：NAT 模式，容器是子网；主机隔离，容器互通 
  &lt;ul&gt;
&lt;li&gt;主机访问容器：容器 IP。比如部署应用后，通过 172.17.0.3 访问 redis&lt;/li&gt;
&lt;li&gt;容器访问主机：外网 ip:port。比如 docker 的 nginx 代理主机 8080 端口，就要写 43.107.136.120:8080&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;host：主机容器共网，同一 IP；安全性低&lt;/li&gt;
&lt;li&gt;container：使用其他容器的网路，共享IP和PORT等网络资源&lt;/li&gt;
&lt;li&gt;none：网络关闭&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
&lt;a id=&quot;2Docker__14&quot;&gt;&lt;/a&gt;2.Docker 常用命令&lt;/h3&gt; 
&lt;ul&gt;
&lt;li&gt;docker search ~：搜索镜像&lt;/li&gt;
&lt;li&gt;docker pull ~：拉取镜像&lt;/li&gt;
&lt;li&gt;docker images：查看已有镜像&lt;/li&gt;
&lt;li&gt;docker rmi ~：删除已有镜像&lt;/li&gt;
&lt;li&gt;docker run ~：启动容器 
  &lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-d&lt;/code&gt; --detach=false 指定容器运行于前台还是后台，默认为false&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--name=&quot;&quot;&lt;/code&gt; 指定容器名字，后续可以通过名字进行容器管理，links特性需要使用名字&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-p 主机port:容器port&lt;/code&gt; --publish=[] 指定容器暴露的端口&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-v 主机目录:容器目录&lt;/code&gt; --volume=[] 给容器挂载存储卷，挂载到容器的某个目录&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-e&lt;/code&gt; --env=[] 指定环境变量，容器中可以使用该环境变量&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--net=&quot;bridge&quot;&lt;/code&gt; 容器网络设置&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--privileged=false&lt;/code&gt; 指定容器是否为特权容器，特权容器拥有所有的capabilities&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;docker ps -a：查看所有容器&lt;/li&gt;
&lt;li&gt;docker exec -it ~ bash：进入容器&lt;/li&gt;
&lt;li&gt;docker start()/restart()/stop() ~：容器启动/重启/停止&lt;/li&gt;
&lt;li&gt;docker logs -f ~：查看镜像日志&lt;/li&gt;
&lt;li&gt;docker rm ~：删除容器&lt;/li&gt;
&lt;li&gt;docker inspect ~ | grep IPAddress：查看镜像 IP&lt;/li&gt;
&lt;li&gt;docker build -t ~ .：构建镜像（.当前路径）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
&lt;a id=&quot;3_Dockerfile_36&quot;&gt;&lt;/a&gt;3.构建 Dockerfile&lt;/h3&gt; 
&lt;p&gt;所有镜像其实都是 Dockerfile，只不过像 mysql、redis 这些人家是已经写好并发布到 DockerHub 了而已。&lt;/p&gt; 
&lt;ul&gt;
&lt;li&gt;FROM：基础镜像，当前新镜像是基于哪个镜像的，若在本地不存在，则会到 DockerHub 上下载&lt;/li&gt;
&lt;li&gt;MAINTAINER：镜像维护者的姓名和邮箱地址&lt;/li&gt;
&lt;li&gt;EXPOSE：当前容器对外暴露的端口&lt;/li&gt;
&lt;li&gt;RUN：容器构建时需要运行的命令&lt;/li&gt;
&lt;li&gt;ADD：将宿主机目录下的文件拷贝进镜像并且 ADD 命令会自动处理 URL 和解压 tar 包&lt;/li&gt;
&lt;li&gt;WORKDIR：指定在创建容器后，终端默认登陆进来的工作目录，以及之后的 CMD 命令都是基于这个目录的&lt;/li&gt;
&lt;li&gt;ENV：用来在构建镜像过程中设置环境变量&lt;/li&gt;
&lt;li&gt;VOLUME：容器数据卷，用于数据保存和持久化工作&lt;/li&gt;
&lt;li&gt;CMD：指定一个容器启动时要运行的命令格式 
  &lt;ul&gt;
&lt;li&gt;shell(常规shell命名): CMD (命令)&lt;/li&gt;
&lt;li&gt;exec(执行脚本)：CMD [‘可执行文件’,“参数1”,“参数2”,…]&lt;/li&gt;
&lt;li&gt;DockerFile中可以有多个CMD指令，但只有最后一个生效，可以被docker run之后的参数替换&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;ENTEYPOINT 指定一个容器启动时要运行的命令 
  &lt;blockquote&gt; 
   &lt;p&gt;注：ENTRYPOINT的目地和CMD一样，都是在指定容器启动程序及参数，区别是 ENTRYPOINT 通过把所有的命令追加在一起执行，docker run 之后的参数也会追加在后面执行。可以参考&lt;a href=&quot;https://blog.csdn.net/u010900754/article/details/78526443&quot;&gt;这篇文章&lt;/a&gt;。&lt;/p&gt; 
  &lt;/blockquote&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下面来看张图片（注：图片取自&lt;a href=&quot;https://www.cnblogs.com/edisonchou/p/dockerfile_inside_introduction.html&quot;&gt;这篇博客&lt;/a&gt;）&lt;br&gt;&lt;img src=&quot;https://blog.quwenai.cn/zb_users/upload/2022/10/20221019202112166618207274660.png&quot; alt=&quot;img&quot;&gt;&lt;br&gt; 示例一：基于 CentOS 构建一个带有 Vim 的 CentOS&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-sh&quot;&gt;# 设置 继承容器
FROM centos
# 设置 作者 邮箱
MAINTAINER wcong&amp;lt;1848293548@qq.com&amp;gt;
# 定义变量MYPATH
ENV MYPATH &quot;/usr/local&quot;
# 设置进入容器的初识工作目录
WORKDIR $MYPATH
# 安装 vim
RUN yum install -y vim
# 暴露端口 提示作用
EXPOSE 80
# 打印 测试
CMD echo $MYPATH
CMD echo &quot;this is test ------- success&quot;
CMD /bin/bash
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;示例二：对 SpringBoot 程序构建一个应用镜像&lt;/p&gt; 
&lt;pre&gt;&lt;code class=&quot;prism language-text&quot;&gt;# 基础环境
FROM openjdk:8-jdk-alpine
# 添加文件
ADD forum-1.0-SNAPSHOT.jar /usr/local/java/forum/app.jar
# 挂载数据目录
VOLUME [&quot;/var/xusm&quot;]
# 暴露
EXPOSE 8080
# 启动命令
ENTRYPOINT [&quot;java&quot;,&quot;-jar&quot;,&quot;/usr/local/java/forum/app.jar&quot;]
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;docker build -t ~ .：构建镜像（.当前路径）&lt;/p&gt; 
&lt;h3&gt;
&lt;a id=&quot;4Docker__94&quot;&gt;&lt;/a&gt;4.Docker 安全&lt;/h3&gt; 
&lt;p&gt;1）连接时直接使用容器 IP、端口，关闭服务器响应端口。比如应用部署后，连接 mysql&lt;/p&gt; 
&lt;pre&gt;&lt;code&gt;jdbc:mysql://172.17.0.2/forum?useUnicode=true&amp;amp;characterEncoding=utf8
&lt;/code&gt;&lt;/pre&gt; 
&lt;p&gt;这样，我们就可以关闭服务器 3306 端口，redis 同理&lt;/p&gt; 
&lt;p&gt;2）容器可以设置白名单&lt;/p&gt;
</description><pubDate>Wed, 19 Oct 2022 20:21:12 +0800</pubDate></item></channel></rss>