主頁 > 後端開發 > SpringBoot2.x系列(二)生產環境日志及預警

SpringBoot2.x系列(二)生產環境日志及預警

2020-12-08 13:05:06 後端開發

在生產環境中,要求對日志進行分類切割及ERR例外類能及時預警,便于及時發現線上問題,

一、技術要求:

(1).日志按照以天為單位存盤,超過一定大小后要另起檔案,便于查閱,日志可設定過期時間,過期后系統可自動洗掉,避免海量存盤空間

(2) 出現線上ERROR級別例外,需要通過釘釘或者郵件及時預警

(3)把ERROR級別例外資訊存盤到資料庫,方便線上查詢

(4)要能方便區分除生產環境及開發環境,開發環境不需要郵件及釘釘預警

二、技術解決思路

對應生產環境例外錯誤預警,大概有兩種解決方

(1)采用全域攔截器,攔截所有例外,在攔截器里實作存盤、推送等操作,這個需要考慮并發

(2)采用日志系統自帶的相關功能及擴展

本論文介紹通過日志擴展來解決問題

Spring Boot 2.*默認采用了slf4j+logback的形式 ,slf4j是個通用的日志門面,logback就是個具體的日志框架了,我們記錄日志的時候采用slf4j的方法去記錄日志,底層的實作就是根據參考的不同日志jar去判定了,所以Spring Boot也能自動適配JCL、JUL、Log4J等日志框架,它的內部邏輯就是通過特定的JAR包去適配各個不同的日志框架,

logback日志集成了郵件發送、資料庫存盤、日志檔案分類存盤等功能,釘釘推送預警沒有集成,需要去擴展

分環境撰寫組態檔,springboot已有解決方案,通過application.yml里面配置不同的對應檔案,logback可讀取當前的環境引數:

解決步驟

1.在resources檔案夾力創建logback-spring.xml檔案,并在yml檔案里宣告

:注意默認檔案名是logback-spring.xml,可省略

yml檔案里宣告

#日志資訊
logging:
  config: classpath:logback-spring.xml #如果不配置config,默認查找logback-spring.xml
  path: D:/log

2.在logback.xml里配置控制臺日志和檔案輸出

<!-- 控制面板輸出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <!--格式化輸出:%d表示日期,%thread表示執行緒名,%-5level:級別從左顯示5個字符寬度%msg:日志訊息,%n是換行符-->
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n</pattern>
    </encoder>
</appender>

<!-- 按照每天生成日志檔案 -->
<appender name="FILE"  class="ch.qos.logback.core.rolling.RollingFileAppender">
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!--日志檔案輸出的檔案名-->
        <FileNamePattern>${LOG_HOME}/%d{yyyy-MM-dd}/MIXPAY_%d{yyyy-MM-s}.log</FileNamePattern>
        <!--日志檔案保留天數-->
        <MaxHistory>50</MaxHistory>
    </rollingPolicy>
    <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
        <!--格式化輸出:%d表示日期,%thread表示執行緒名,%-5level:級別從左顯示5個字符寬度%msg:日志訊息,%n是換行符-->
        <pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{50} - %msg%n</pattern>
    </encoder>
    <!--日志檔案最大的大小-->
    <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
        <MaxFileSize>50MB</MaxFileSize>
    </triggeringPolicy>
</appender>

<!--輸出配置 -->

<root level="INFO">
    <!-- 控制面板輸出 -->
    <appender-ref ref="STDOUT"/>
    <!-- 按照每天生成日志檔案 -->
    <appender-ref ref="FILE"/>
 

</root>

3.配置插入資料庫

pom.xml檔案引入資料庫相關驅動

<!--spring-jdbc驅動 -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-jdbc</artifactId>
</dependency>


<!--druid 資料庫連接池 -->
<dependency>
  <groupId>com.alibaba</groupId>
  <artifactId>druid-spring-boot-starter</artifactId>
  <version>1.1.10</version>
</dependency>

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>5.1.48</version>
</dependency>

yml里配置相關鏈接,這里日志資料庫雖然用不到,但不配置要報啟動錯誤

spring:
  profiles:
    active: prod
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: org.gjt.mm.mysql.Driver
    platform: mysql
    url: jdbc:mysql://127.0.0.1:3306/pmlog?useUnicode=true&characterEncoding=UTF-8&useSSL=true
    username: root
    password: 111111
    initialSize: 5
    minIdle: 5
    maxActive: 20
    maxWait: 60000
    timeBetweenEvictionRunsMillis: 60000
    minEvictableIdleTimeMillis: 300000
    validationQuery: SELECT1FROMDUAL
    testWhileIdle: true
    testOnBorrow: false
    testOnReturn: false
    filters: stat,wall,log4j
    logSlowSql: truelog

在logback.xml檔案里配置

<!--連接資料庫配置-->
<appender name="db_classic_mysql_pool" class="ch.qos.logback.classic.db.DBAppender">
    <connectionSource class="ch.qos.logback.core.db.DataSourceConnectionSource">
        <dataSource class="com.alibaba.druid.pool.DruidDataSource">
            <driverClassName>org.gjt.mm.mysql.Driver</driverClassName>
            <url>jdbc:mysql://127.0.0.1:3306/pmlog?useUnicode=true&amp;characterEncoding=UTF-8&amp;useSSL=true</url>
            <username>root</username>
            <password>111111</password>
        </dataSource>
    </connectionSource>

    <!--這里設定日志級別為error-->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <level>error</level>
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>

</appender>
<root level="INFO">
  
    <!-- 資料庫輸出 -->
    <appender-ref ref="db_classic_mysql_pool"/>
  

</root>

初始化資料庫表

BEGIN;

DROP TABLE IF EXISTS logging_event_property;

DROP TABLE IF EXISTS logging_event_exception;

DROP TABLE IF EXISTS logging_event;

COMMIT;

BEGIN;

CREATE TABLE logging_event

(

timestmp BIGINT NOT NULL,

formatted_message TEXT NOT NULL,

logger_name VARCHAR(254) NOT NULL,

level_string VARCHAR(254) NOT NULL,

thread_name VARCHAR(254),

reference_flag SMALLINT,

arg0 VARCHAR(254),

arg1 VARCHAR(254),

arg2 VARCHAR(254),

arg3 VARCHAR(254),

caller_filename VARCHAR(254) NOT NULL,

caller_class VARCHAR(254) NOT NULL,

caller_method VARCHAR(254) NOT NULL,

caller_line CHAR(4) NOT NULL,

event_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY

);

COMMIT;

BEGIN;

CREATE TABLE logging_event_property

(

event_id BIGINT NOT NULL,

mapped_key VARCHAR(254) NOT NULL,

mapped_value TEXT,

PRIMARY KEY(event_id, mapped_key),

FOREIGN KEY (event_id) REFERENCES logging_event(event_id)

);

COMMIT;

BEGIN;

CREATE TABLE logging_event_exception

(

event_id BIGINT NOT NULL,

i SMALLINT NOT NULL,

trace_line VARCHAR(254) NOT NULL,

PRIMARY KEY(event_id, i),

FOREIGN KEY (event_id) REFERENCES logging_event(event_id)

);

COMMIT;

4.配置發送到郵件

pom.xml引入mail包

<dependency>
  <groupId>org.codehaus.janino</groupId>
  <artifactId>janino</artifactId>
  <version>3.1.2</version>
</dependency>
<!-- email -->
<dependency>
  <groupId>javax.mail</groupId>
  <artifactId>mail</artifactId>
  <version>1.4.5</version>
</dependency>
<!-- email END-->

logback.xml配置郵件資訊

<!--郵件發送-->
<appender name="email" class="ch.qos.logback.classic.net.SMTPAppender">
    <!--smtp 服務器-->
    <smtpHost>smtp.qiye.aliyun.com</smtpHost>
    <!--port-->
    <smtpPort>25</smtpPort>
    <!-- 發給誰的郵件串列,多個人用逗號分隔 -->
    <to>jiangzengkui@lpcollege.com</to>
    <!--發件人,添加郵箱和上面的username保持一致-->
    <from>jyj_stuff@lpcollege.com</from>
    <subject>${ACTIVE_PROFILE_NAME}: %logger - %msg</subject>
    <!--發件人的郵箱-->
    <username>jyj_stuff@lpcollege.com</username>
    <!--發件人的郵箱密碼-->
    <password>F4efK7mpnrz5Etkg</password>
    <SSL>false</SSL>
    <!--是否異步-->
    <asynchronousSending>true</asynchronousSending>
    <layout class="ch.qos.logback.classic.PatternLayout">
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
    </layout>
    <cyclicBufferTracker class = "ch.qos.logback.core.spi.CyclicBufferTracker" >
        <bufferSize> 1 </bufferSize>
    </cyclicBufferTracker>
    <!--過濾器-->
    <!-- 這里采用等級過濾器 指定等級相符才發送 -->
    <filter class="ch.qos.logback.classic.filter.LevelFilter">
        <level>ERROR</level>
        <onMatch>ACCEPT</onMatch>
        <onMismatch>DENY</onMismatch>
    </filter>
</appender>
<root level="INFO">
    <appender-ref ref="email"/>

</root>

5.釘釘推送等其他操作

logback沒有像郵件,資料庫一樣集成,只有繼承UnsynchronizedAppenderBase去擴展

注:關于釘釘如何發預警訊息,請參考釘釘和springboot的集成

(1)擴展類:

package com.jyj.soft.comm;



import ch.qos.logback.classic.spi.ILoggingEvent;

import ch.qos.logback.core.UnsynchronizedAppenderBase;



import java.text.SimpleDateFormat;

import java.util.Date;

import java.util.HashMap;

import java.util.Map;



/**

* @class: com.jyj.soft.comm.CustomizeApperder

* @description:

* logback的節點擴展類,獲取輸出,并進行異步處理

* @author: jiangzengkui

* @company: 教育家

* @create: 2020-12-05 09:13

*/

public class CustomizeApperder extends UnsynchronizedAppenderBase<ILoggingEvent> {

@Override



public void append(ILoggingEvent eventObject) {



try {

 //節點輸出內容
            String content = eventObject.getMessage();
            //例外的IP
            String  ip= InetAddress.getLocalHost().getHostAddress();
            String run_machine=SpringContextUtil.getActiveProfile();//運行服務器型別如在yml配置的生存、開發、測驗等環境
            //System.out.println("當前運行環境: " + run_machine);
           // System.out.println("content內容是: " + content);

            System.out.println("服務器IP:"+ip);
            if("prod".equals(run_machine)){//如果是生產環境
                //1.可發郵件

                //2.可釘釘推送

                String title=">生產環境發生例外";
                 String markDown=">**服務器IP:**"+ip+"\n\n";
                  markDown+=">**例外原因:**"+content;
                  RobotUtil.sendMarkdownMsg(RobotUtil.robot_name_test,null,title,markDown);

                //3.可插入資料庫
            }


/** Map<String, String> map = new HashMap<String, String>();



map.put("LOG_LEVEL", eventObject.getLevel().levelStr);



map.put("CONTENT", content.replace("'", "''"));



SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");



map.put("CREATE_DATE", sdf.format(new Date()));

**/



// 拼接SQL陳述句,然后執行



// … …



} catch (Throwable e) {



String errorMsg = e.getLocalizedMessage();



System.out.println(errorMsg);



}



}

}

這里用到一個幫助類SpringContextUtil,通過非注解的方式或者bean實體和配置屬性

package com.jyj.soft.comm;

/**
 * @class: com.jyj.soft.comm.SpringContextUtil
 * @description:
 * 作用:
 *  (1)不通過@Autowired注解來獲得物件實體
 *  (2)直接讀取propertie,yml檔案里的配置值
 * @author: jiangzengkui
 * @company: 教育家
 * @create: 2020-12-05 11:05
 */
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.Map;


/**
 * 獲取Spring的ApplicationContext物件工具,可以用靜態方法的方式獲取spring容器中的bean
 * @author https://blog.csdn.net/chen_2890
 * @date 2019/6/26 16:20
 */
@Component
public class SpringContextUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    /**
     * 系統啟動如tomcat時會執行這個方法
     * @param applicationContext
     * @throws BeansException
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringContextUtil.applicationContext = applicationContext;
    }

    /**
     * 獲取applicationContext
     */
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    /**
     * 通過name獲取 Bean.
     */
    public static Object getBean(String name) {
        Object o = null;
        try {
            o = getApplicationContext().getBean(name);
        } catch (NoSuchBeanDefinitionException e) {
            // e.printStackTrace();
        }
        return o;
    }

    /**
     * 通過class獲取Bean.
     */
    public static <T> T getBean(Class<T> clazz) {
        return getApplicationContext().getBean(clazz);
    }

    /**
     * 通過name,以及Clazz回傳指定的Bean
     */
    public static <T> T getBean(String name, Class<T> clazz) {
        return getApplicationContext().getBean(name, clazz);
    }

    /**
     * 通過name獲取 Bean.
     */
    public static <T> Map<String, T> getBeansOfType(Class<T> clazz) {
        return getApplicationContext().getBeansOfType(clazz);
    }

    /**
     * 獲取組態檔配置項的值
     *
     * @param key 配置項key,注意這個key支撐連寫
     * persoon:
     *   name: jzk
     * 則key是persoon.name,不是name
     */
    public static String getEnvironmentProperty(String key) {
        return getApplicationContext().getEnvironment().getProperty(key);
    }

    /**
     * 獲取spring.profiles.active
     */
    public static String getActiveProfile() {
        return getApplicationContext().getEnvironment().getActiveProfiles()[0];
    }
}

(2)配置logback.xml

<!--自定義節點 -->

<appender name="CustomLog" class="com.jyj.soft.comm.CustomizeApperder">

<!--過濾類 -->

<filter class="ch.qos.logback.classic.filter.ThresholdFilter">

<level>error</level>

</filter>

</appender>

<root level="INFO">
  
    <!--自定義節點 -->
    <appender-ref ref="CustomLog"/>
   
</root>

5.日志在不同的環境運用

比如只有在生產環境推送釘釘預警和郵件等,開發和測驗環境不需要

要用到logback.xml里<springProfile name="xx">這個這個標簽,意思是對yml組態檔里的spring.profiles.active的資料

spring:
  profiles:
    active: prod

logback根據不同的值,呼叫不同的appender,如

<!-- 日志輸出級別 ,就是說在整個專案中,日志級別在info一上的日志都列印, root是根日志列印器,只有一個,負責整個系統的日志輸出  -->
<!--
springProfile name="prod" 對應著yml組態檔spring.profiles.active: dev
-->
<springProfile name="prod"><!--生產環境 -->
<root level="INFO">
    <!-- 控制面板輸出 -->
    <appender-ref ref="STDOUT"/>
    <!-- 按照每天生成日志檔案 -->
    <appender-ref ref="FILE"/>
    <!-- 資料庫輸出 -->
    <appender-ref ref="db_classic_mysql_pool"/>
    <!--自定義節點 -->
    <appender-ref ref="CustomLog"/>
    <!--郵件輸出-->
    <appender-ref ref="email"/>

</root>
</springProfile>

<springProfile name="dev"><!--開發環境 -->
    <root level="debug">
        <!-- 控制面板輸出 -->
        <appender-ref ref="STDOUT"/>

    </root>
</springProfile>

7.其他知識

(1)logback讀取yml組態檔的資料

先宣告,在用{}參考

yml:

persoon:

name: jzk

在logback 里讀取

定義

<springProperty scope="context" name="pro_name" source="persoon.name"/>

參考

<subject>${pro_name}: %logger - %msg</subject>

(3)日志簡寫

每個類都要寫

LoggerFactory.getLogger(SbDemoApplicationTests.class);很麻煩,可以省掉

//標簽
@Slf4j
@RestController
public class HelloCtrol {

    @Autowired
    private Persoon persoon;
    @Autowired
    private Dage dage;

    //訪問路徑及方法
    @RequestMapping(value = "/hello",method = RequestMethod.GET)
    public String hello(){
        dage.h();
//直接用log
        log.error("error================");
        log.warn("warn==============");
        log.info("info==============");
        log.debug("debug===================");
        return "hello, "+persoon.getName()+",address:"+persoon.getAddress();
    }

實作方式

1.使用idea首先需要安裝Lombok插件;

2..在pom檔案加入lombok的依賴

<dependency>

<groupId>org.projectlombok</groupId>

<artifactId>lombok</artifactId>

<version>1.18.0</version>

</dependency>

3.釘釘訊息推送

參考:

https://blog.csdn.net/weixin_41158378/article/details/110749806

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/231577.html

標籤:java

上一篇:【SpringBoot】SpringBoot生成二維碼

下一篇:Java撰寫簡單計算器--實作篇

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more