chinese直男口爆体育生外卖, 99久久er热在这里只有精品99, 又色又爽又黄18禁美女裸身无遮挡, gogogo高清免费观看日本电视,私密按摩师高清版在线,人妻视频毛茸茸,91论坛 兴趣闲谈,欧美 亚洲 精品 8区,国产精品久久久久精品免费

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

Spring Boot+Filter實(shí)現(xiàn)Gzip壓縮超大json對(duì)象

jf_ro2CN3Fa ? 來(lái)源:芋道源碼 ? 作者:芋道源碼 ? 2022-12-01 10:18 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群


1. 業(yè)務(wù)背景

是這樣的,業(yè)務(wù)背景是公司的內(nèi)部系統(tǒng)有一個(gè)廣告保存接口,需要ADX那邊將投放的廣告數(shù)據(jù)進(jìn)行保存供后續(xù)使用。 廣告數(shù)據(jù)大概長(zhǎng)這樣:

  • adName是廣告名字
  • adTag是廣告渲染的HTML代碼,超級(jí)大數(shù)據(jù)庫(kù)中都是用text類型來(lái)存放的,我看到最大的adTag足足有60kb大小…
{
"adName":"",
"adTag":""
}

因此,對(duì)與請(qǐng)求數(shù)據(jù)那么大的接口我們肯定是需要作一個(gè)優(yōu)化的否則太大的數(shù)據(jù)傳輸有以下幾個(gè)弊端:

  • 占用網(wǎng)絡(luò)帶寬,而有些云產(chǎn)品就是按照帶寬來(lái)計(jì)費(fèi)的,間接浪費(fèi)了錢
  • 傳輸數(shù)據(jù)大導(dǎo)致網(wǎng)絡(luò)傳輸耗時(shí)

為了克服這幾個(gè)問(wèn)題團(tuán)隊(duì)中的老鳥產(chǎn)生一個(gè)想法:

請(qǐng)求廣告保存接口時(shí)先將Json對(duì)象字符串進(jìn)行GZIP壓縮,那請(qǐng)求時(shí)傳入的就是壓縮后的數(shù)據(jù),而GZIP的壓縮效率是很高的,因此可以大大減小傳輸數(shù)據(jù),而當(dāng)數(shù)據(jù)到達(dá)廣告保存接口前再將傳來(lái)的數(shù)據(jù)進(jìn)行解壓縮,還原成JSON對(duì)象就完成了整個(gè)GZIP壓縮數(shù)據(jù)的請(qǐng)求以及處理流程。

其實(shí)這樣做也存在著弊端:

  • 請(qǐng)求變復(fù)雜了

    • 接口調(diào)用方那邊需要對(duì)數(shù)據(jù)進(jìn)行壓縮
    • 接口執(zhí)行方那邊需要對(duì)拿到的數(shù)據(jù)進(jìn)行解壓
  • 需要額外占用更多的CPU計(jì)算資源

  • 可能會(huì)影響到原有的其他接口

對(duì)于以上幾點(diǎn)基于我們公司當(dāng)前的業(yè)務(wù)可以這樣解決:

  • 對(duì)與需要占用而外的CPU計(jì)算資源來(lái)說(shuō),公司的內(nèi)部系統(tǒng)屬于IO密集型應(yīng)用,因此用一些CPU資源來(lái)?yè)Q取更快的網(wǎng)絡(luò)傳輸其實(shí)是很劃算的
  • 使用過(guò)濾器在請(qǐng)求數(shù)據(jù)到達(dá)Controller之前對(duì)數(shù)據(jù)進(jìn)行解壓縮處理后重新寫回到Body中,避免影響Controller的邏輯,代碼零侵入
  • 而對(duì)于改造接口的同時(shí)是否會(huì)影響到原來(lái)的接口這一點(diǎn)可以通過(guò) HttpHeader 的Content-Encoding=gzip屬性來(lái)區(qū)分是否需要對(duì)請(qǐng)求數(shù)據(jù)進(jìn)行解壓縮

那廢話少說(shuō),下面給出實(shí)現(xiàn)方案

基于 Spring Boot + MyBatis Plus + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

  • 項(xiàng)目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 視頻教程:https://doc.iocoder.cn/video/

2. 實(shí)現(xiàn)思路

前置知識(shí):
  • Http 請(qǐng)求結(jié)構(gòu)以及Content-Encoding 屬性
  • gzip壓縮方式
  • Servlet Filter
  • HttpServletRequestWrapper
  • Spring Boot
  • Java 輸入輸出流

實(shí)現(xiàn)流程圖:

e6600140-711c-11ed-8abf-dac502259ad0.png
核心代碼:

創(chuàng)建一個(gè)SpringBoot項(xiàng)目,先編寫一個(gè)接口,功能很簡(jiǎn)單就是傳入一個(gè)Json對(duì)象并返回,以模擬將廣告數(shù)據(jù)保存到數(shù)據(jù)庫(kù)

/**
*@ClassName:ProjectController
*@Authorzhangjin
*@Date2022/3/2420:41
*@Description:
*/
@Slf4j
@RestController
publicclassAdvertisingController{

@PostMapping("/save")
publicAdvertisingsaveProject(@RequestBodyAdvertisingadvertising){
log.info("獲取內(nèi)容"+advertising);
returnadvertising;
}
}

/**
*@ClassName:Project
*@Authorzhangjin
*@Date2022/3/2420:42
*@Description:
*/
@Data
publicclassAdvertising{
privateStringadName;
privateStringadTag;
}

編寫并注冊(cè)一個(gè)攔截器

/**
*@ClassName:GZIPFilter
*@Authorzhangjin
*@Date2022/3/260:36
*@Description:
*/
@Slf4j
@Component
publicclassGZIPFilterimplementsFilter{

privatestaticfinalStringCONTENT_ENCODING="Content-Encoding";
privatestaticfinalStringCONTENT_ENCODING_TYPE="gzip";

@Override
publicvoidinit(FilterConfigfilterConfig)throwsServletException{
log.info("initGZIPFilter");
}

@Override
publicvoiddoFilter(ServletRequestservletRequest,ServletResponseservletResponse,FilterChainfilterChain)throwsIOException,ServletException{
longstart=System.currentTimeMillis();
HttpServletRequesthttpServletRequest=(HttpServletRequest)servletRequest;

StringencodeType=httpServletRequest.getHeader(CONTENT_ENCODING);
if(CONTENT_ENCODING_TYPE.equals(encodeType)){
log.info("請(qǐng)求:{}需要解壓",httpServletRequest.getRequestURI());
UnZIPRequestWrapperunZIPRequestWrapper=newUnZIPRequestWrapper(httpServletRequest);
filterChain.doFilter(unZIPRequestWrapper,servletResponse);
}
else{
log.info("請(qǐng)求:{}無(wú)需解壓",httpServletRequest.getRequestURI());
filterChain.doFilter(servletRequest,servletResponse);
}
log.info("耗時(shí):{}ms",System.currentTimeMillis()-start);
}

@Override
publicvoiddestroy(){
log.info("destroyGZIPFilter");
}
}

/**
*@ClassName:FilterRegistration
*@Authorzhangjin
*@Date2022/3/260:36
*@Description:
*/
@Configuration
publicclassFilterRegistration{

@Resource
privateGZIPFiltergzipFilter;

@Bean
publicFilterRegistrationBeangzipFilterRegistrationBean(){
FilterRegistrationBeanregistration=newFilterRegistrationBean<>();
//Filter可以new,也可以使用依賴注入Bean
registration.setFilter(gzipFilter);
//過(guò)濾器名稱
registration.setName("gzipFilter");
//攔截路徑
registration.addUrlPatterns("/*");
//設(shè)置順序
registration.setOrder(1);
returnregistration;
}
}

實(shí)現(xiàn)RequestWrapper實(shí)現(xiàn)解壓和寫回Body的邏輯

/**
*@ClassName:UnZIPRequestWrapper
*@Authorzhangjin
*@Date2022/3/2611:02
*@Description:JsonString經(jīng)過(guò)壓縮后保存為二進(jìn)制文件->解壓縮后還原成JsonString轉(zhuǎn)換成byte[]寫回body中
*/
@Slf4j
publicclassUnZIPRequestWrapperextendsHttpServletRequestWrapper{

privatefinalbyte[]bytes;

publicUnZIPRequestWrapper(HttpServletRequestrequest)throwsIOException{
super(request);
try(BufferedInputStreambis=newBufferedInputStream(request.getInputStream());
ByteArrayOutputStreambaos=newByteArrayOutputStream()){
finalbyte[]body;
byte[]buffer=newbyte[1024];
intlen;
while((len=bis.read(buffer))>0){
baos.write(buffer,0,len);
}
body=baos.toByteArray();
if(body.length==0){
log.info("Body無(wú)內(nèi)容,無(wú)需解壓");
bytes=body;
return;
}
this.bytes=GZIPUtils.uncompressToByteArray(body);
}catch(IOExceptionex){
log.info("解壓縮步驟發(fā)生異常!");
ex.printStackTrace();
throwex;
}
}

@Override
publicServletInputStreamgetInputStream()throwsIOException{
finalByteArrayInputStreambyteArrayInputStream=newByteArrayInputStream(bytes);
returnnewServletInputStream(){

@Override
publicbooleanisFinished(){
returnfalse;
}

@Override
publicbooleanisReady(){
returnfalse;
}

@Override
publicvoidsetReadListener(ReadListenerreadListener){

}

publicintread()throwsIOException{
returnbyteArrayInputStream.read();
}
};
}

@Override
publicBufferedReadergetReader()throwsIOException{
returnnewBufferedReader(newInputStreamReader(this.getInputStream()));
}

}

附上壓縮工具類

publicclassGZIPUtils{

publicstaticfinalStringGZIP_ENCODE_UTF_8="UTF-8";

/**
*字符串壓縮為GZIP字節(jié)數(shù)組
*@paramstr
*@return
*/
publicstaticbyte[]compress(Stringstr){
returncompress(str,GZIP_ENCODE_UTF_8);
}

/**
*字符串壓縮為GZIP字節(jié)數(shù)組
*@paramstr
*@paramencoding
*@return
*/
publicstaticbyte[]compress(Stringstr,Stringencoding){
if(str==null||str.length()==0){
returnnull;
}
ByteArrayOutputStreamout=newByteArrayOutputStream();
GZIPOutputStreamgzip;
try{
gzip=newGZIPOutputStream(out);
gzip.write(str.getBytes(encoding));
gzip.close();
}catch(IOExceptione){
e.printStackTrace();
}
returnout.toByteArray();
}

/**
*GZIP解壓縮
*@parambytes
*@return
*/
publicstaticbyte[]uncompress(byte[]bytes){
if(bytes==null||bytes.length==0){
returnnull;
}
ByteArrayOutputStreamout=newByteArrayOutputStream();
ByteArrayInputStreamin=newByteArrayInputStream(bytes);
try{
GZIPInputStreamungzip=newGZIPInputStream(in);
byte[]buffer=newbyte[256];
intn;
while((n=ungzip.read(buffer))>=0){
out.write(buffer,0,n);
}
}catch(IOExceptione){
e.printStackTrace();
}
returnout.toByteArray();
}

/**
*解壓并返回String
*@parambytes
*@return
*/
publicstaticStringuncompressToString(byte[]bytes)throwsIOException{
returnuncompressToString(bytes,GZIP_ENCODE_UTF_8);
}

/**
*
*@parambytes
*@return
*/
publicstaticbyte[]uncompressToByteArray(byte[]bytes)throwsIOException{
returnuncompressToByteArray(bytes,GZIP_ENCODE_UTF_8);
}

/**
*解壓成字符串
*@parambytes壓縮后的字節(jié)數(shù)組
*@paramencoding編碼方式
*@return解壓后的字符串
*/
publicstaticStringuncompressToString(byte[]bytes,Stringencoding)throwsIOException{
byte[]result=uncompressToByteArray(bytes,encoding);
returnnewString(result);
}

/**
*解壓成字節(jié)數(shù)組
*@parambytes
*@paramencoding
*@return
*/
publicstaticbyte[]uncompressToByteArray(byte[]bytes,Stringencoding)throwsIOException{
if(bytes==null||bytes.length==0){
returnnull;
}
ByteArrayOutputStreamout=newByteArrayOutputStream();
ByteArrayInputStreamin=newByteArrayInputStream(bytes);
try{
GZIPInputStreamungzip=newGZIPInputStream(in);
byte[]buffer=newbyte[256];
intn;
while((n=ungzip.read(buffer))>=0){
out.write(buffer,0,n);
}
returnout.toByteArray();
}catch(IOExceptione){
e.printStackTrace();
thrownewIOException("解壓縮失??!");
}
}

/**
*將字節(jié)流轉(zhuǎn)換成文件
*@paramfilename
*@paramdata
*@throwsException
*/
publicstaticvoidsaveFile(Stringfilename,byte[]data)throwsException{
if(data!=null){
Stringfilepath="/"+filename;
Filefile=newFile(filepath);
if(file.exists()){
file.delete();
}
FileOutputStreamfos=newFileOutputStream(file);
fos.write(data,0,data.length);
fos.flush();
fos.close();
System.out.println(file);
}
}

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實(shí)現(xiàn)的后臺(tái)管理系統(tǒng) + 用戶小程序,支持 RBAC 動(dòng)態(tài)權(quán)限、多租戶、數(shù)據(jù)權(quán)限、工作流、三方登錄、支付、短信、商城等功能

  • 項(xiàng)目地址:https://github.com/YunaiV/yudao-cloud
  • 視頻教程:https://doc.iocoder.cn/video/

3. 測(cè)試效果

注意一個(gè)大坑:千萬(wàn)不要直接將壓縮后的byte[]當(dāng)作字符串進(jìn)行傳輸,否則你會(huì)發(fā)現(xiàn)壓縮后的請(qǐng)求數(shù)據(jù)竟然比沒(méi)壓縮后的要大得多!一般有兩種傳輸壓縮后的byte[]的方式:

  • 將壓縮后的byet[]進(jìn)行base64編碼再傳輸字符串,這種方式會(huì)損失掉一部分GZIP的壓縮效果,適用于壓縮結(jié)果要存儲(chǔ)在Redis中的情況
  • 將壓縮后的byte[]以二進(jìn)制的形式寫入到文件中,請(qǐng)求時(shí)直接在body中帶上文件即可,用這種方式可以不損失壓縮效果

Postman測(cè)試Gzip壓縮數(shù)據(jù)請(qǐng)求:

  • 請(qǐng)求頭指定數(shù)據(jù)壓縮方式:
e66cba2a-711c-11ed-8abf-dac502259ad0.png
  • Body帶上壓縮后的byte[]寫入的二進(jìn)制文件
e67736f8-711c-11ed-8abf-dac502259ad0.png
  • 執(zhí)行請(qǐng)求,服務(wù)端正確處理了請(qǐng)求并且請(qǐng)求size縮小了將近一半,效果還是很不錯(cuò)的,這樣GZIP壓縮數(shù)據(jù)的請(qǐng)求的處理就完成了,完整的項(xiàng)目代碼在下方
e69f980a-711c-11ed-8abf-dac502259ad0.png

4. Demo地址

  • https://gitee.com/wx_1bceb446a4/gziptest


審核編輯 :李倩


聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    341

    瀏覽量

    15579
  • 傳輸數(shù)據(jù)
    +關(guān)注

    關(guān)注

    1

    文章

    127

    瀏覽量

    16432
  • 大數(shù)據(jù)
    +關(guān)注

    關(guān)注

    64

    文章

    8996

    瀏覽量

    142470

原文標(biāo)題:Spring Boot + Filter 實(shí)現(xiàn) Gzip 壓縮超大 json 對(duì)象,傳輸耗時(shí)大大減少

文章出處:【微信號(hào):芋道源碼,微信公眾號(hào):芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    ulog_tag_lvl_filter_set()函數(shù)無(wú)法實(shí)現(xiàn)按照文檔說(shuō)明那樣實(shí)現(xiàn)按模塊過(guò)濾,怎么解決?

    ulog_tag_lvl_filter_set()函數(shù)無(wú)法實(shí)現(xiàn)按照文檔說(shuō)明那樣實(shí)現(xiàn)按模塊過(guò)濾,比如過(guò)濾掉所有drv.xxx的日志
    發(fā)表于 10-10 07:30

    基于FPGA的壓縮算法加速實(shí)現(xiàn)

    本設(shè)計(jì)中,計(jì)劃實(shí)現(xiàn)對(duì)文件的壓縮及解壓,同時(shí)優(yōu)化壓縮中所涉及的信號(hào)處理和計(jì)算密集型功能,實(shí)現(xiàn)對(duì)其的加速處理。本設(shè)計(jì)的最終目標(biāo)是證明在充分并行化的硬件體系結(jié)構(gòu) FPGA 上
    的頭像 發(fā)表于 07-10 11:09 ?1825次閱讀
    基于FPGA的<b class='flag-5'>壓縮</b>算法加速<b class='flag-5'>實(shí)現(xiàn)</b>

    不用聯(lián)網(wǎng)不用編程,PLC通過(guò)智能網(wǎng)關(guān)快速實(shí)現(xiàn)HTTP協(xié)議JSON格式與MES等系統(tǒng)平臺(tái)雙向數(shù)據(jù)通訊

    進(jìn)行解析后將數(shù)據(jù)寫入到PLC,實(shí)現(xiàn)PLC與HTTP服務(wù)端雙向通訊;作為服務(wù)端時(shí)根據(jù)客戶端URL中的路徑查找所配置的數(shù)據(jù),打包成JSON文件后返回給客戶端。
    的頭像 發(fā)表于 05-13 14:40 ?713次閱讀
    不用聯(lián)網(wǎng)不用編程,PLC通過(guò)智能網(wǎng)關(guān)快速<b class='flag-5'>實(shí)現(xiàn)</b>HTTP協(xié)議<b class='flag-5'>JSON</b>格式與MES等系統(tǒng)平臺(tái)雙向數(shù)據(jù)通訊

    通過(guò)Boot swap實(shí)現(xiàn)瑞薩RL78/F24 MCU固件升級(jí)

    本文主要說(shuō)明如何使用已有的程序更新flash中的固件。使用這種方法代碼閃存分為兩個(gè)區(qū)域:執(zhí)行區(qū)域和臨時(shí)區(qū)域。瑞薩flash驅(qū)動(dòng)程序RL78 RFD Type02用于對(duì)flash進(jìn)行重新編程并執(zhí)行boot swapping。本次說(shuō)明主要以RL78/F24為例展開boot s
    的頭像 發(fā)表于 02-26 09:25 ?1916次閱讀
    通過(guò)<b class='flag-5'>Boot</b> swap<b class='flag-5'>實(shí)現(xiàn)</b>瑞薩RL78/F24 MCU固件升級(jí)

    深度解析Nginx Gzip指令:優(yōu)化網(wǎng)站性能與加速加載速度的關(guān)鍵工具

    快,當(dāng)然相比較之下體驗(yàn)會(huì)更好。 IT成本上 對(duì)這個(gè)場(chǎng)景來(lái)說(shuō)的成本主要是帶寬成本, 數(shù)據(jù)不壓縮那么傳輸這些數(shù)據(jù)相應(yīng)的帶寬肯定更大,對(duì)比之下壓縮耗費(fèi)的CPU資源在帶寬費(fèi)用上不值一提。 所以你有什么理由不用壓縮呢? 背景 當(dāng)然Ngin
    的頭像 發(fā)表于 02-12 11:06 ?636次閱讀

    ADMV8505: 225 MHz to 520 MHz, Digitally Tunable, Band-Pass Filter Data Sheet adi

    電子發(fā)燒友網(wǎng)為你提供ADI(ADI)ADMV8505: 225 MHz to 520 MHz, Digitally Tunable, Band-Pass Filter Data Sheet相關(guān)產(chǎn)品
    發(fā)表于 01-15 18:54
    ADMV8505: 225 MHz to 520 MHz, Digitally Tunable, Band-Pass <b class='flag-5'>Filter</b> Data Sheet adi

    think-cell——使用JSON數(shù)據(jù)實(shí)現(xiàn)自動(dòng)化(二)

    26.4 遠(yuǎn)程提供模板 還可以通過(guò)遠(yuǎn)程服務(wù)器提供帶有 think-cell 圖表的模板文件。在這種情況下,鍵的值是 URL 而不是本地路徑,如上面的遠(yuǎn)程 JSON 示例所示。URL 可以指定為協(xié)議
    的頭像 發(fā)表于 01-03 10:12 ?516次閱讀
    think-cell——使用<b class='flag-5'>JSON</b>數(shù)據(jù)<b class='flag-5'>實(shí)現(xiàn)</b>自動(dòng)化(二)

    think-cell——使用JSON數(shù)據(jù)實(shí)現(xiàn)自動(dòng)化(一)

    您可以使用 JSON 中的數(shù)據(jù)來(lái)復(fù)制最初作為模板創(chuàng)建的圖表,并為其提供新的數(shù)據(jù)表。您可以控制使用特定模板構(gòu)建新演示文稿的順序。模板也可以多次使用。 PowerPoint 模板和 JSON 數(shù)據(jù)都可以
    的頭像 發(fā)表于 01-02 13:37 ?603次閱讀
    think-cell——使用<b class='flag-5'>JSON</b>數(shù)據(jù)<b class='flag-5'>實(shí)現(xiàn)</b>自動(dòng)化(一)

    校園點(diǎn)餐訂餐外賣跑腿Java源碼

    創(chuàng)建一個(gè)校園點(diǎn)餐訂餐外賣跑腿系統(tǒng)是一個(gè)復(fù)雜的項(xiàng)目,涉及到前端、后端、數(shù)據(jù)庫(kù)設(shè)計(jì)等多個(gè)方面。在這里,我可以提供一個(gè)簡(jiǎn)化的Java后端示例,使用Spring Boot框架來(lái)搭建一個(gè)基本的API服務(wù)。這個(gè)
    的頭像 發(fā)表于 12-24 14:55 ?810次閱讀
    校園點(diǎn)餐訂餐外賣跑腿Java源碼

    HarmonyOS Next 應(yīng)用元服務(wù)開發(fā)-分布式數(shù)據(jù)對(duì)象遷移數(shù)據(jù)權(quán)限與基礎(chǔ)數(shù)據(jù)

    設(shè)備文件訪問(wèn)實(shí)現(xiàn)文件的遷移,難以獲取文件同步完成的時(shí)間。為了保證更高的成功率,文件的遷移不建議繼續(xù)通過(guò)該方式實(shí)現(xiàn),推薦使用分布式數(shù)據(jù)對(duì)象攜帶資產(chǎn)的方式。開發(fā)者此前通過(guò)跨設(shè)備文件訪問(wèn)實(shí)現(xiàn)
    發(fā)表于 12-24 09:40

    SSM框架的源碼解析與理解

    SSM框架(Spring + Spring MVC + MyBatis)是一種在Java開發(fā)中常用的輕量級(jí)企業(yè)級(jí)應(yīng)用框架。它通過(guò)整合Spring、Spring MVC和MyBatis三
    的頭像 發(fā)表于 12-17 09:20 ?1257次閱讀

    SSM開發(fā)環(huán)境的搭建教程 SSM與Spring Boot的區(qū)別

    SSM開發(fā)環(huán)境的搭建教程 SSM(Spring+SpringMVC+MyBatis)開發(fā)環(huán)境的搭建涉及多個(gè)步驟,以下是詳細(xì)的教程: 創(chuàng)建Maven項(xiàng)目 : 使用Maven工具創(chuàng)建一個(gè)新的Maven
    的頭像 發(fā)表于 12-16 18:13 ?1681次閱讀

    Spring 應(yīng)用合并之路(二):峰回路轉(zhuǎn),柳暗花明

    提醒下,決定拋開 Spring Boot 內(nèi)置的父子容器方案,完全自己實(shí)現(xiàn)父子容器。 如何加載 web 項(xiàng)目? 現(xiàn)在的難題只有一個(gè):如何加載 web 項(xiàng)目?加載完成后,如何持續(xù)持有 web 項(xiàng)目?經(jīng)過(guò)思考后,可以創(chuàng)建一個(gè)
    的頭像 發(fā)表于 12-12 11:22 ?1296次閱讀

    Spring事務(wù)實(shí)現(xiàn)原理

    這些操作。 spring事務(wù)有編程式事務(wù)和聲明式事務(wù)兩種實(shí)現(xiàn)方式。編程式事務(wù)是通過(guò)編寫代碼來(lái)管理事務(wù)的提交、回滾、以及事務(wù)的邊界。這意味著開發(fā)者需要在代碼中顯式地調(diào)用事務(wù)的開始、提交和回滾。聲明式事務(wù)是通過(guò)配置來(lái)管理事務(wù),您可以使用注解或XML配置來(lái)
    的頭像 發(fā)表于 11-08 10:10 ?1336次閱讀
    <b class='flag-5'>Spring</b>事務(wù)<b class='flag-5'>實(shí)現(xiàn)</b>原理

    請(qǐng)問(wèn)Pre-Filter PBTL和Post-Filter PBTL相比有什么優(yōu)缺點(diǎn)?

    Pre-Filter PBTL和Post-Filter PBTL 相比有什么優(yōu)缺點(diǎn)
    發(fā)表于 10-18 06:54