1. 程式人生 > >ffmpeg實戰教程(五)libswscale,libavfilter實踐指南

ffmpeg實戰教程(五)libswscale,libavfilter實踐指南

1.libswscale實現YUV轉RGB

libswscale裡面實現了各種影象畫素格式的轉換。

libswscale使用起來很方便,最主要的函式只有3個: 
(1) sws_getContext():使用引數初始化SwsContext結構體。 
(2) sws_scale():轉換一幀影象。 
(3) sws_freeContext():釋放SwsContext結構體。 
其中sws_getContext()也可以用另一個介面函式sws_getCachedContext()取代。

初始化方法

初始化SwsContext除了呼叫sws_getContext()之外還有另一種方法,更加靈活,可以配置更多的引數。該方法呼叫的函式如下所示。 
(1) sws_alloc_context():為SwsContext結構體分配記憶體。 
(2) av_opt_set_XXX():通過av_opt_set_int(),av_opt_set()…等等一系列方法設定SwsContext結構體的值。在這裡需要注意,SwsContext結構體的定義看不到,所以不能對其中的成員變數直接進行賦值,必須通過av_opt_set()這類的API才能對其進行賦值。 
(3) sws_init_context():初始化SwsContext結構體。 
這種複雜的方法可以配置一些sws_getContext()配置不了的引數。比如說設定影象的YUV畫素的取值範圍是JPEG標準(Y、U、V取值範圍都是0-255)還是MPEG標準(Y取值範圍是16-235,U、V的取值範圍是16-240)。

通過av_pix_fmt_desc_get()可以獲得指定畫素格式的AVPixFmtDescriptor結構體。 
通過AVPixFmtDescriptor結構體可以獲得不同畫素格式的一些資訊。例如av_get_bits_per_pixel(),通過該函式可以獲得指定畫素格式每個畫素佔用的位元數(Bit Per Pixel)。

影象拉伸 
SWS_BICUBIC效能比較好;SWS_FAST_BILINEAR在效能和速度之間有一個比好好的平衡。

下面看一下執行效果圖: 
這裡寫圖片描述 
原始碼:



#include <stdio.h>

#define __STDC_CONSTANT_MACROS

#ifdef _WIN32
//Windows extern "C" { #include "libswscale/swscale.h" #include "libavutil/opt.h" #include "libavutil/imgutils.h" }; #else //Linux... #ifdef __cplusplus extern "C" { #endif #include <libswscale/swscale.h> #include <libavutil/opt.h> #include <libavutil/imgutils.h> #ifdef __cplusplus }; #endif
#endif int main(int argc, char* argv[]) { //Parameters FILE *src_file =fopen("ws.yuv", "rb"); const int src_w=1920,src_h=1080; AVPixelFormat src_pixfmt=AV_PIX_FMT_YUV420P; //該函式可以獲得指定畫素格式每個畫素佔用的位元數(Bit Per Pixel),av_pix_fmt_desc_get()可以獲得指定畫素格式的AVPixFmtDescriptor結構體。 int src_bpp=av_get_bits_per_pixel(av_pix_fmt_desc_get(src_pixfmt)); FILE *dst_file = fopen("ws.rgb", "wb"); const int dst_w=1280,dst_h=720; AVPixelFormat dst_pixfmt=AV_PIX_FMT_RGB24; int dst_bpp=av_get_bits_per_pixel(av_pix_fmt_desc_get(dst_pixfmt));//av_pix_fmt_desc_get()可以獲得指定畫素格式的AVPixFmtDescriptor結構體。 //Structures uint8_t *src_data[4]; int src_linesize[4]; uint8_t *dst_data[4]; int dst_linesize[4]; int rescale_method=SWS_BICUBIC; struct SwsContext *img_convert_ctx; uint8_t *temp_buffer=(uint8_t *)malloc(src_w*src_h*src_bpp/8); int frame_idx=0; int ret=0; ret= av_image_alloc(src_data, src_linesize,src_w, src_h, src_pixfmt, 1);//分配資源控制元件 if (ret< 0) { printf( "Could not allocate source image\n"); return -1; } ret = av_image_alloc(dst_data, dst_linesize,dst_w, dst_h, dst_pixfmt, 1); if (ret< 0) { printf( "Could not allocate destination image\n"); return -1; } //----------------------------- img_convert_ctx =sws_alloc_context();//為SwsContext結構體分配記憶體。 //Show AVOption av_opt_show2(img_convert_ctx,stdout,AV_OPT_FLAG_VIDEO_PARAM,0); //Set Value av_opt_set_int(img_convert_ctx,"sws_flags",SWS_BICUBIC|SWS_PRINT_INFO,0); av_opt_set_int(img_convert_ctx,"srcw",src_w,0); av_opt_set_int(img_convert_ctx,"srch",src_h,0); av_opt_set_int(img_convert_ctx,"src_format",src_pixfmt,0); //'0' for MPEG (Y:0-235);'1' for JPEG (Y:0-255) av_opt_set_int(img_convert_ctx,"src_range",1,0); av_opt_set_int(img_convert_ctx,"dstw",dst_w,0); av_opt_set_int(img_convert_ctx,"dsth",dst_h,0); av_opt_set_int(img_convert_ctx,"dst_format",dst_pixfmt,0); av_opt_set_int(img_convert_ctx,"dst_range",1,0); sws_init_context(img_convert_ctx,NULL,NULL);//對SwsContext中的各種變數進行賦值 while(1) { if (fread(temp_buffer, 1, src_w*src_h*src_bpp/8, src_file) != src_w*src_h*src_bpp/8){ break; } switch(src_pixfmt){ case AV_PIX_FMT_GRAY8:{ memcpy(src_data[0],temp_buffer,src_w*src_h); break; } case AV_PIX_FMT_YUV420P:{ memcpy(src_data[0],temp_buffer,src_w*src_h); //Y memcpy(src_data[1],temp_buffer+src_w*src_h,src_w*src_h/4); //U memcpy(src_data[2],temp_buffer+src_w*src_h*5/4,src_w*src_h/4); //V break; } case AV_PIX_FMT_YUV422P:{ memcpy(src_data[0],temp_buffer,src_w*src_h); //Y memcpy(src_data[1],temp_buffer+src_w*src_h,src_w*src_h/2); //U memcpy(src_data[2],temp_buffer+src_w*src_h*3/2,src_w*src_h/2); //V break; } case AV_PIX_FMT_YUV444P:{ memcpy(src_data[0],temp_buffer,src_w*src_h); //Y memcpy(src_data[1],temp_buffer+src_w*src_h,src_w*src_h); //U memcpy(src_data[2],temp_buffer+src_w*src_h*2,src_w*src_h); //V break; } case AV_PIX_FMT_YUYV422:{ memcpy(src_data[0],temp_buffer,src_w*src_h*2); //Packed break; } case AV_PIX_FMT_RGB24:{ memcpy(src_data[0],temp_buffer,src_w*src_h*3); //Packed break; } default:{ printf("Not Support Input Pixel Format.\n"); break; } } sws_scale(img_convert_ctx, src_data, src_linesize, 0, src_h, dst_data, dst_linesize);//轉換畫素 printf("Finish process frame %5d\n",frame_idx); frame_idx++; switch(dst_pixfmt){ case AV_PIX_FMT_GRAY8:{ fwrite(dst_data[0],1,dst_w*dst_h,dst_file); break; } case AV_PIX_FMT_YUV420P:{ fwrite(dst_data[0],1,dst_w*dst_h,dst_file); //Y fwrite(dst_data[1],1,dst_w*dst_h/4,dst_file); //U fwrite(dst_data[2],1,dst_w*dst_h/4,dst_file); //V break; } case AV_PIX_FMT_YUV422P:{ fwrite(dst_data[0],1,dst_w*dst_h,dst_file); //Y fwrite(dst_data[1],1,dst_w*dst_h/2,dst_file); //U fwrite(dst_data[2],1,dst_w*dst_h/2,dst_file); //V break; } case AV_PIX_FMT_YUV444P:{ fwrite(dst_data[0],1,dst_w*dst_h,dst_file); //Y fwrite(dst_data[1],1,dst_w*dst_h,dst_file); //U fwrite(dst_data[2],1,dst_w*dst_h,dst_file); //V break; } case AV_PIX_FMT_YUYV422:{ fwrite(dst_data[0],1,dst_w*dst_h*2,dst_file); //Packed break; } case AV_PIX_FMT_RGB24:{ fwrite(dst_data[0],1,dst_w*dst_h*3,dst_file); //Packed break; } default:{ printf("Not Support Output Pixel Format.\n"); break; } } } sws_freeContext(img_convert_ctx); free(temp_buffer); fclose(dst_file); av_freep(&src_data[0]); av_freep(&dst_data[0]); return 0; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182

2.使用libavfilter為視音訊新增特效功能

關鍵函式如下所示:

avfilter_register_all():註冊所有AVFilter。
avfilter_graph_alloc():為FilterGraph分配記憶體。
avfilter_graph_create_filter():建立並向FilterGraph中新增一個Filter。
avfilter_graph_parse_ptr():將一串通過字串描述的Graph新增到FilterGraph中。
avfilter_graph_config():檢查FilterGraph的配置。
av_buffersrc_add_frame():向FilterGraph中加入一個AVFrame。

av_buffersink_get_frame():從FilterGraph中取出一個AVFrame。

程式中提供了幾種特效:

//const char *filter_descr = "lutyuv='u=128:v=128'";
    //const char *filter_descr = "boxblur";
    //const char *filter_descr = "hflip";
    //const char *filter_descr = "hue='h=60:s=-3'";
    //const char *filter_descr = "crop=2/3*in_w:2/3*in_h";
    //const char *filter_descr = "drawbox=x=100:y=100:w=100:h=100:color=pink@0.5";
    const char *filter_descr = "drawtext=fontfile=arial.ttf:fontcolor=red:fontsize=50:text='Shuo.Wang'";
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

輸入ws.yuv,輸出ws_output.yuv

原生效果如下: 
這裡寫圖片描述

const char *filter_descr = “lutyuv=’u=128:v=128’”; 
這裡寫圖片描述

const char *filter_descr = “drawtext=fontfile=arial.ttf:fontcolor=red:fontsize=50:text=’Shuo.Wang’”; 
這裡寫圖片描述

原始碼如下:


#include <stdio.h>

#define __STDC_CONSTANT_MACROS

#ifdef _WIN32
#define snprintf _snprintf
//Windows
extern "C"
{
#include "libavfilter/avfiltergraph.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#include "libavutil/avutil.h"
#include "libavutil/imgutils.h"
};
#else
//Linux...
#ifdef __cplusplus
extern "C"
{
#endif
#include <libavfilter/avfiltergraph.h>
#include <libavfilter/buffersink.h>
#include <libavfilter/buffersrc.h>
#include <libavutil/avutil.h>
#include <libavutil/imgutils.h>
#ifdef __cplusplus
};
#endif
#endif




int main(int argc, char* argv[])
{
    int ret;
    AVFrame *frame_in;
    AVFrame *frame_out;
    unsigned char *frame_buffer_in;
    unsigned char *frame_buffer_out;

    AVFilterContext *buffersink_ctx;
    AVFilterContext *buffersrc_ctx;
    AVFilterGraph *filter_graph;
    static int video_stream_index = -1;

    //Input YUV
    FILE *fp_in=fopen("ws.yuv","rb+");
    if(fp_in==NULL){
        printf("Error open input file.\n");
        return -1;
    }
    int in_width=1920;
    int in_height=1080;

    //Output YUV
    FILE *fp_out=fopen("ws_output.yuv","wb+");
    if(fp_out==NULL){
        printf("Error open output file.\n");
        return -1;
    }

    //const char *filter_descr = "lutyuv='u=128:v=128'";
    //const char *filter_descr = "boxblur";
    //const char *filter_descr = "hflip";
    //const char *filter_descr = "hue='h=60:s=-3'";
    //const char *filter_descr = "crop=2/3*in_w:2/3*in_h";
    //const char *filter_descr = "drawbox=x=100:y=100:w=100:h=100:color=pink@0.5";
    const char *filter_descr = "drawtext=fontfile=arial.ttf:fontcolor=red:fontsize=50:text='Shuo.Wang'";

    avfilter_register_all();//註冊所有AVFilter。

    char args[512];
    AVFilter *buffersrc  = avfilter_get_by_name("buffer");
    AVFilter *buffersink = avfilter_get_by_name("ffbuffersink");
    AVFilterInOut *outputs = avfilter_inout_alloc();
    AVFilterInOut *inputs  = avfilter_inout_alloc();
    enum PixelFormat pix_fmts[] = { PIX_FMT_YUV420P, PIX_FMT_NONE };
    AVBufferSinkParams *buffersink_params;

    filter_graph = avfilter_graph_alloc();//為FilterGraph分配記憶體。

    /* buffer video source: the decoded frames from the decoder will be inserted here. */
    snprintf(args, sizeof(args),
        "video_size=%dx%d:pix_fmt=%d:time_base=%d/%d:pixel_aspect=%d/%d",
        in_width,in_height,PIX_FMT_YUV420P,
        1, 25,1,1);

    //建立並向FilterGraph中新增一個Filter。
    ret = avfilter_graph_create_filter(&buffersrc_ctx, buffersrc, "in",
        args, NULL, filter_graph);
    if (ret < 0) {
        printf("Cannot create buffer source\n");
        return ret;
    }

    /* buffer video sink: to terminate the filter chain. */
    buffersink_params = av_buffersink_params_alloc();
    buffersink_params->pixel_fmts = pix_fmts;
    ret = avfilter_graph_create_filter(&buffersink_ctx, buffersink, "out",
        NULL, buffersink_params, filter_graph);
    av_free(buffersink_params);
    if (ret < 0) {
        printf("Cannot create buffer sink\n");
        return ret;
    }

    /* Endpoints for the filter graph. */
    outputs->name       = av_strdup("in");
    outputs->filter_ctx = buffersrc_ctx;
    outputs->pad_idx    = 0;
    outputs->next       = NULL;

    inputs->name       = av_strdup("out");
    inputs->filter_ctx = buffersink_ctx;
    inputs->pad_idx    = 0;
    inputs->next       = NULL;

    //將一串通過字串描述的Graph新增到FilterGraph中。
    if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_descr,
        &inputs, &outputs, NULL)) < 0)
        return ret;
    //檢查FilterGraph的配置。
    if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0)
        return ret;

    frame_in=av_frame_alloc();
    frame_buffer_in=(unsigned char *)av_malloc(av_image_get_buffer_size(PIX_FMT_YUV420P, in_width,in_height,1));
    av_image_fill_arrays(frame_in->data, frame_in->linesize,frame_buffer_in,
        PIX_FMT_YUV420P,in_width, in_height,1);

    frame_out=av_frame_alloc();
    frame_buffer_out=(unsigned char *)av_malloc(av_image_get_buffer_size(PIX_FMT_YUV420P, in_width,in_height,1));
    av_image_fill_arrays(frame_out->data, frame_out->linesize,frame_buffer_out,
        PIX_FMT_YUV420P,in_width, in_height,1);

    frame_in->width=in_width;
    frame_in->height=in_height;
    frame_in->format=PIX_FMT_YUV420P;

    while (1) {

        if(fread(frame_buffer_in, 1, in_width*in_height*3/2, fp_in)!= in_width*in_height*3/2){
            break;
        }
        //input Y,U,V
        frame_in->data[0]=frame_buffer_in;
        frame_in->data[1]=frame_buffer_in+in_width*in_height;
        frame_in->data[2]=frame_buffer_in+in_width*in_height*5/4;
        //向FilterGraph中加入一個AVFrame。
        if (av_buffersrc_add_frame(buffersrc_ctx, frame_in) < 0) {
            printf( "Error while add frame.\n");
            break;
        }

        /* pull filtered pictures from the filtergraph  從FilterGraph中取出一個AVFrame。*/
        ret = av_buffersink_get_frame(buffersink_ctx, frame_out);
        if (ret < 0)
            break;

        //output Y,U,V
        if(frame_out->format==PIX_FMT_YUV420P){
            for(int i=0;i<frame_out->height;i++){
                fwrite(frame_out->data[0]+frame_out->linesize[0]*i,1,frame_out->width,fp_out);
            }
            for(int i=0;i<frame_out->height/2;i++){
                fwrite(frame_out->data[1]+frame_out->linesize[1]*i,1,frame_out->width/2,fp_out);
            }
            for(int i=0;i<frame_out->height/2;i++){
                fwrite(frame_out->data[2]+frame_out->linesize[2]*i,1,frame_out->width/2,fp_out);
            }
        }
        printf("Process 1 frame!\n");
    }

    fclose(fp_in);
    fclose(fp_out);

    av_frame_free(&frame_in);
    av_frame_free(&frame_out);
    avfilter_graph_free(&filter_graph);

    return 0;
}

相關推薦

ffmpeg實戰教程libswscalelibavfilter實踐指南

1.libswscale實現YUV轉RGBlibswscale裡面實現了各種影象畫素格式的轉換。libswscale使用起來很方便,最主要的函式只有3個: (1) sws_getContext():使用引數初始化SwsContext結構體。 (2) sws_scale():轉

ffmpeg實戰教程Mp4mkv等格式解碼為h264和yuv資料

FFmpeg有非常強大的功能包括視訊採集功能、視訊格式轉換、視訊抓圖、給視訊加水印等。而網上對這些功能的使用大多是基於命令列的。這不利於我們深入學習定製化ffmpeg,今後我將寫一系列的用程式碼實現這些功能的教程供大家學習。這系列的前部分我打算寫在windows

機器學習實戰教程:樸素貝葉斯實戰篇之新浪新聞分類

原文連結: Jack-Cui,https://cuijiahua.com/blog/2017/11/ml_5_bayes_2.html 一、前言 上篇文章機器學習實戰教程(四):樸素貝葉斯基礎篇之言論過濾器講解了樸素貝葉斯的基礎知識。本篇文章將在此基礎上進行擴充套件,你將看到以下內容: 拉普拉

ffmpeg實戰教程格式轉換如MP4轉MKV等

知識延伸:I,P,B幀和PTS,DTS的關係基本概念:I frame :幀內編碼幀 又稱intra picture,I 幀通常是每個 GOP(MPEG 所使用的一種視訊壓縮技術)的第一個幀,經過適度地壓縮,做為隨機訪問的參考點,可以當成圖象。I幀可以看成是一個影象經過壓縮後的

ffmpeg實戰教程Android CMake avi解碼後SurfaceView顯示

#include <jni.h> #include <android/log.h> #include <android/native_window.h> #include <android/native_window_jni.h> extern "C" { #

ffmpeg實戰教程十一手把手教你實現直播功能不依賴第三方SDK

先上圖: 推流的手機 拉流的網頁和VL播放器 拉流的手機客戶端 對於nginx伺服器的搭建之前有寫過: 這篇也建議看一下: 下面開始實現手機直播功能 1

深度學習實戰教程1--手機上跑目標檢測模型YOLO從DarkNet到Caffe再到NCNN完整打通

https://github.com/lwplw 這篇打算就直入主題了,YOLO是什麼、DarkNet是什麼、Caffe是什麼、NCNN又是什麼…等等這一系列的基礎科普這裡就完全不說了,牽扯實在太多,通過其他帖子有一定的積累後,看這篇就相對容易了。 本文核心:把一個目標檢測模型跑

【Oracle 叢集】ORACLE DATABASE 11G RAC 知識圖文詳細教程之RAC 特殊問題和實戰經驗

在需要將一個 LUN (邏輯單元號)對映給多個節點、為叢集提供一個共享的儲存卷時,同一個儲存 LUN 在各個主機端的 LUNID 必須是相同的。比如:  (一) 在為多個 ESX 節點建立一個 VMFS 卷的時候 (二) 在雙機 HA 叢集建立共享儲存的時候 時間一致性 叢集模式下,各

IOS 初級開發入門教程TextField與ReturnKey實戰練習

前言看完前面4章的內容,基本對IOS開發有一些認識了,這章我們繼續動手去實踐一下,學習文字和鍵盤的相關知識,以及通過一個互動式的案例演示文字與鍵盤的使用。系列文章:UIKit繼承結構我們通過這個UIKit繼承結構圖,我們試著找到本章要學習的TextFiled與TextView

Python入門系列教程函數

st3 python入門 test print 缺省 .com 教程 技術 log 全局變量 修改全局變量 a=100 def test(): global a a=200 print a 多個返回值 缺省參數 d

java教程SSH框架-配置

jar 集成 相同 onf -i ret 順序 cati lin 前言:從這篇博客開始我將繼續講述Java教程:SSH篇。主要內容環繞SSH框架分析與搭建,今天先簡介一下SSH的配置。 SSH配置順序是: spring-->hibern

ActiveReports 9實戰教程1: 手把手搭建好開發環境Visual Studio 2013 社區版

line tool mmu tin style textbox ble mil nts ActiveReports 9剛剛公布3天。微軟就公布了 Visual Studio Community 2013 開發環境。Visual Studio Community 2013

微信公眾平臺開發教程自定義菜單

打開鏈接 delete toolbar 推送 優化 pcl reader 接口查詢 robot 應大家強烈要求,將自定義菜單功能課程提前。 一、概述: 如果只有輸入框,可能太簡單,感覺像命令行。自定義菜單,給我們提供了很大的靈活性,更符合用戶的操作習慣。在一個小小的微信對話

python基礎教程

() 文件名 nal cnblogs 文件 求長 元素 fin 查詢 字符串基本操作   所有標準的序列操作(索引、分片、乘法、判斷成員資格、求長度、取最小值和最大值)對字符串同樣適用,前面已經講述的這些操作。但是,請註意字符串都是不可變的。 字符串的方法: 字符串從s

JXLS 2.4.0系列教程——更進一步的應用和bug修復

erl dir 問題 create sna 過程 idl es2017 cal 註:本文代碼建立於前面寫的代碼。不過不看也不要緊。   前面的文章把JXLS 2.4.0 的基本使用寫了一遍,現在講講一些更進一步的使用方法。我只寫一些我用到過的方法,更多的高級使用方法請參

jQuery EasyUI快速入門實戰教程-入門

jquery javascript easyui 1、jQuery EasyUI概述jQuery EasyUI是一組基於jQuery的UI插件集合體,而jQuery EasyUI的目標就是幫助web開發者更輕松的打造出功能豐富並且美觀的UI界面。開發者不需要編寫復雜的javascript,也不需要

Spring Boot參考教程Spring Boot配置使用之配置類用法

expr web程序 成功 驗證 pan hub parameter lan fix 4.2. SpringBoot配置使用之配置類使用 Spring Boot的大部分自動配置都可以滿足應用要求,但如果想精確的控制應用,或者想覆蓋自動配置,使用配置類是另一種很好的選擇,強調

Spring Boot實戰筆記-- Spring高級話題Spring Aware

ktr mea 框架 .com cat 分享 aware war uic 一、Spring Aware   Spring 依賴註入的最大亮點就是你所有的 Bean 對 Spring容器的存在是沒有意識的。即你可以將你的容器替換成其他的容器,如Google Guice,這時

Linux系列教程——Linux鏈接命令和權限管理命令

密碼 mission pos link 掩碼 Owner 最大的 linux系統 passwd   前一篇博客我們講解了Linux文件和目錄處理命令,還是老生常淡,對於新手而言,我們不需要完全記住命令的詳細語法,記住該命令能完成什麽功能,然後需要的時候去查就好了,用的多了我

Spring Cloud Config教程客戶端使用

home 本地 snap 遠程 html local nap parent path 要在應用程序中使用這些功能,只需將其構建為依賴於spring-cloud-config-client的Spring引導應用程序(例如,查看配置客戶端或示例應用程序的測試用例)。添加依賴關