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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

开源项目工时系统_SpringBoot 微信点餐开源系统!综合运用项目,值得一看!

發(fā)布時間:2023/12/19 windows 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 开源项目工时系统_SpringBoot 微信点餐开源系统!综合运用项目,值得一看! 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

作者:Tommmmm來源:www.jianshu.com/p/ae14101989f2

架構

前后端分離:

Nginx 與 Tomcat 的關系在這篇文章,幾分鐘可以快速了解:

https://www.jianshu.com/p/22dcb7ef9172

補充:

  • setting.xml 文件的作用:settings.xml 是 maven 的全局配置文件。而 pom.xml 文件是所在項目的局部配置。Settings.xml 中包含類似本地倉儲位置、修改遠程倉儲服務器、認證信息等配置。

  • maven 的作用:借助 Maven,可將 jar 包僅僅保存在 “倉庫” 中,有需要該文件時,就引用該文件接口,不需要復制文件過來占用空間

注:這個 “倉庫” 應該就是本地安裝 maven 的目錄下的 Repository 的文件夾

分布式鎖

線程鎖:當某個方法或代碼使用鎖,在同一時刻僅有一個線程執(zhí)行該方法或該代碼段。線程鎖只在同一 JVM 中有效,因為線程鎖的實現(xiàn)在根本上是依靠線程之間共享內(nèi)存實現(xiàn)的。如 synchronized

進程鎖:為了控制同一操作系統(tǒng)中多個進程訪問某個共享資源。

分布式鎖:當多個進程不在同一個系統(tǒng)中,用分布式鎖控制多個進程對資源的訪問。

分布式鎖一般有三種實現(xiàn)方式:

  • 數(shù)據(jù)庫樂觀鎖;

  • 基于 Redis 的分布式鎖;

  • 基于 ZooKeeper 的分布式鎖。

  • 樂觀鎖的實現(xiàn):使用版本標識來確定讀到的數(shù)據(jù)與提交時的數(shù)據(jù)是否一致。提交后修改版本標識,不一致時可以采取丟棄和再次嘗試的策略。

    CAS:可以閱讀這篇文章:

    https://www.jianshu.com/p/456bb1ea9627

    分布式鎖基于 Redis 的實現(xiàn):(本系統(tǒng)鎖才用的)

    基本命令:

    • SETNX(SET if Not exist):當且僅當 key 不存在,將 key 的值設為 value ,并返回 1;若給定的 key 已經(jīng)存在,則 SETNX 不做任何動作,并返回 0。

    • GETSET:將給定 key 的值設為 value ,并返回 key 的舊值。先根據(jù) key 獲取到舊的 value,再 set 新的 value。

    • EXPIRE 為給定 key 設置生存時間, 當 key 過期時,它會被自動刪除。

    加鎖方式:

    這里的 jedis 是 Java 對 Redis 的集成

    jedis.set(String?key,?String?value,?String?nxxx,?String?expx,?int?time)

    錯誤的加鎖方式 1:

    如果程序在執(zhí)行完 setnx() 之后突然崩潰,導致鎖沒有設置過期時間。那么將會發(fā)生死鎖。

    Long?result?=?jedis.setnx(Key,?value);

    ????if?(result?==?1)?{

    ????????//?若在這里程序突然崩潰,則無法設置過期時間,將發(fā)生死鎖

    ????????jedis.expire(Key,?expireTime);

    ????}

    錯誤的加鎖方式 2:

    分布式鎖才用(Key,過期時間)的方式,如果鎖存在,那么獲取它的過期時間,如果鎖的確已經(jīng)過期了,那么獲得鎖,并且設置新的過期時間

    錯誤分析:不同的客戶端之間需要同步好時間。

    ?long?expires?=?System.currentTimeMillis()?+?expireTime;

    ????String?expiresStr?=?String.valueOf(expires);

    ????//?如果當前鎖不存在,返回加鎖成功

    ????if?(jedis.setnx(lockKey,?expiresStr)?==?1)?{

    ????????return?true;

    ????}

    ????//?如果鎖存在,獲取鎖的過期時間

    ????String?currentValueStr?=?jedis.get(lockKey);

    ????if?(currentValueStr?!=?null?&&?Long.parseLong(currentValueStr)?System.currentTimeMillis())?{

    ????????//?鎖已過期,獲取上一個鎖的過期時間,并設置現(xiàn)在鎖的過期時間

    ????????String?oldValueStr?=?jedis.getSet(lockKey,?expiresStr);

    ????????if?(oldValueStr?!=?null?&&?oldValueStr.equals(currentValueStr))?{

    ????????????//?考慮多線程并發(fā)的情況,只有一個線程的設置值和當前值相同,它才有權利加鎖

    ????????????return?true;

    ????????}

    ????}

    ????//?其他情況,一律返回加鎖失敗

    ????return?false;

    解鎖:判斷鎖的擁有者后可以使用 jedis.del(lockKey) 來釋放鎖。

    分布式鎖基于 Zookeeper 的實現(xiàn)

    Zookeeper 簡介:Zookeeper 提供一個多層級的節(jié)點命名空間(節(jié)點稱為 znode),每個節(jié)點都用一個以斜杠(/)分隔的路徑表示,而且每個節(jié)點都有父節(jié)點(根節(jié)點除外)。

    例如,/foo/doo 這個表示一個 znode,它的父節(jié)點為 / foo,父父節(jié)點為 /,而 / 為根節(jié)點沒有父節(jié)點。

    client 不論連接到哪個 Server,展示給它都是同一個視圖,這是 zookeeper 最重要的性能。

    Zookeeper 的核心是原子廣播,這個機制保證了各個 Server 之間的同步。實現(xiàn)這個機制的協(xié)議叫做 Zab 協(xié)議。Zab 協(xié)議有兩種模式,它們分別是恢復模式(選主)和廣播模式(同步)。*當服務啟動或者在領導者崩潰后,Zab 就進入了恢復模式*,當領導者被選舉出來,且大多數(shù) Server 完成了和 leader 的狀態(tài)同步以后,恢復模式就結束了。狀態(tài)同步保證了 leader 和 Server 具有相同的系統(tǒng)狀態(tài)。

    為了保證事務的順序一致性,zookeeper 采用了遞增的事務 id 號(zxid)來標識事務,實現(xiàn)中 zxid 是一個 64 位的數(shù)字。

    Zookeeper 的分布式鎖原理

    獲取分布式鎖的流程:

  • 在獲取分布式鎖的時候在 locker 節(jié)點 (locker 節(jié)點是 Zookeeper 的指定節(jié)點) 下創(chuàng)建臨時順序節(jié)點,釋放鎖的時候刪除該臨時節(jié)點。

  • 客戶端調(diào)用 createNode 方法在 locker 下創(chuàng)建臨時順序節(jié)點,然后調(diào)用 getChildren(“l(fā)ocker”) 來獲取 locker 下面的所有子節(jié)點,注意此時不用設置任何 Watcher。

  • 客戶端獲取到所有的子節(jié)點 path 之后,如果發(fā)現(xiàn)自己創(chuàng)建的子節(jié)點序號最小,那么就認為該客戶端獲取到了鎖。

  • 如果發(fā)現(xiàn)自己創(chuàng)建的節(jié)點并非 locker 所有子節(jié)點中最小的,說明自己還沒有獲取到鎖,此時客戶端需要找到比自己小的那個節(jié)點,然后對其調(diào)用 exist() 方法,同時對其注冊事件監(jiān)聽器。

  • 之后,讓這個被關注的節(jié)點刪除,則客戶端的 Watcher 會收到相應通知,此時再次判斷自己創(chuàng)建的節(jié)點是否是 locker 子節(jié)點中序號最小的,如果是則獲取到了鎖,如果不是則重復以上步驟繼續(xù)獲取到比自己小的一個節(jié)點并注冊監(jiān)聽。

  • 我的解釋:

    A 在 Locker 下創(chuàng)建了 Noden —> 循環(huán) (每次獲取 Locker 下的所有子節(jié)點 —> 對這些節(jié)點按節(jié)點自增號排序順序 —> 判斷自己創(chuàng)建的 Noden 是否是第一個節(jié)點 —> 如果是則獲得了分布式鎖 —> 如果不是監(jiān)聽上一個節(jié)點 Node_n-1 等它釋放掉分布式鎖。)

    @ControllerAdvice 處理全局異常
    Mybatis 注解方式的使用:
    @insert 用注解方式寫 SQL 語句

    分布式系統(tǒng)的下的 Session

    1、分布式系統(tǒng):多節(jié)點,節(jié)點發(fā)送數(shù)據(jù)交互,不共享主內(nèi)存,但通過網(wǎng)絡發(fā)送消息合作。

    分布式:不同功能模塊的節(jié)點

    集群:相同功能的節(jié)點

    2、Session 與 token

    服務端在 HTTP 頭里設置 SessionID 而客戶端將其保存在 cookie

    而使用 Token 時需要手動在 HTTP 頭里設置,服務器收到請求后取出 cookie 進行驗證。

    都是一個用戶一個標志

    3、分布式系統(tǒng)中的 Session 問題:

    高并發(fā):通過設計保證系統(tǒng)能夠同時并行處理很多請求。

    當高并發(fā)量的請求到達服務端的時候通過負載均衡的方式分發(fā)到集群中的某個服務器,這樣就有可能導致同一個用戶的多次請求被分發(fā)到集群的不同服務器上,就會出現(xiàn)取不到 session 數(shù)據(jù)的情況。

    根據(jù)訪問不同的 URL,負載到不同的服務器上去

    三臺機器,A1 部署類目,A2 部署商品,A3 部署單服務

    通用方案:用 Redis 保存 Session 信息,服務器需要時都去找 Redis 要。登錄時保存好 key-value,登出時讓他失效

    垂直擴展:IP 哈希 IP 的哈希值相同的訪問同一臺服務器

    session 的一致性:只要用戶不重啟瀏覽器,每次 http 短連接請求,理論上服務端都能定位到 session,保持會話。

    Redis 作為分布式鎖

    高并發(fā):通過設計保證系統(tǒng)能夠同時并行處理很多請求。

    同步:Java 中的同步指的是通過人為的控制和調(diào)度,保證共享資源的多線程訪問成為線程安全。

    線程的 Block 狀態(tài):

    a. 調(diào)用 join() 和 sleep() 方法,sleep() 時間結束或被打斷

    b.wait(),使該線程處于等待池, 直到 notify()/notifyAll():不釋放資源

    此外,在 runnable 狀態(tài)的線程是處于被調(diào)度的線程,Thread 類中的 yield 方法可以讓一個 running 狀態(tài)的線程轉入 runnable。

    Q:為什么 wait,notify 和 notifyAll 必須與 synchronized 一起使用?Obj.wait()、Obj.notify 必須在 synchronized(Obj){…} 語句塊內(nèi)。

    A:wait 就是說線程在獲取對象鎖后,主動釋放對象鎖,同時本線程休眠。

    Q:Synchronized:

    A:Synchronized 就是非公平鎖,它無法保證等待的線程獲取鎖的順序。

    公平和非公平鎖的隊列都基于鎖內(nèi)部維護的一個雙向鏈表,表結點 Node 的值就是每一個請求當前鎖的線程。公平鎖則在于每次都是依次從隊首取值。

    ReentrantLock 重入性:

    重入鎖可以看這兩篇文章,都比較簡單

    https://www.jianshu.com/p/587a4559442b
    https://www.jianshu.com/p/1c52f17efaab

    Spring + Redis 緩存的兩個重要注解:

    • @cacheable 只會執(zhí)行一次,當標記在一個方法上時表示該方法是支持緩存的,Spring 會在其被調(diào)用后將其返回值緩存起來,以保證下次利用同樣的參數(shù)來執(zhí)行該方法時可以直接從緩存中獲取結果。

    • @cacheput:與 @Cacheable 不同的是使用 @CachePut 標注的方法在執(zhí)行前不會去檢查緩存中是否存在之前執(zhí)行過的結果,而是每次都會執(zhí)行該方法,并將執(zhí)行結果以鍵值對的形式存入指定的緩存中。

    對數(shù)據(jù)庫加鎖(樂觀鎖 與 悲觀鎖)

    悲觀鎖依賴數(shù)據(jù)庫實現(xiàn):

    select?*?from?account?where?name=”Erica”?for?update

    這條 sql 語句鎖定了 account 表中所有符合檢索條件(name=”Erica”)的記錄,使該記錄在修改期間其它線程不得占有。

    代碼層加鎖:

    String?hql?="from?TUser?as?user?where?user.;

    Query?query?=?session.createQuery(hql);

    query.setLockMode("user",LockMode.UPGRADE);?//加鎖

    List?userList?=?query.list();//執(zhí)行查詢,獲取數(shù)據(jù)

    其它

    @Data 類似于自動生成了 Getter()、Setter()、ToString() 等方法。

    JAVA1.8 的新特性 StreamAPI:Collectors 中提供了將流中的元素累積到匯聚結果的各種方式

    List<Menu>?menus=Menu.getMenus.stream().collect(Collectors.toList())

    For - each 寫法:

    for each 語句是 java5 新增,在遍歷數(shù)組、集合的時候,for each 擁有不錯的性能。

    public?static?void?main(String[]?args)?{

    ????????String[]?names?=?{"beibei",?"jingjing"};

    ????????for?(String?name?:?names)?{

    ????????????System.out.println(name);

    ????????}

    ????}

    for each 雖然能遍歷數(shù)組或者集合,但是只能用來遍歷,無法在遍歷的過程中對數(shù)組或者集合進行修改。

    BindingResult:一個 @Valid 的參數(shù)后必須緊挨著一個 BindingResult 參數(shù),否則 spring 會在校驗不通過時直接拋出異常。

    @Data

    public?class?OrderForm?{

    ????@NotEmpty(message?=?"姓名必填")

    ????private?String?name;

    }

    后臺:

    @RequestMapping("save")??

    ????public?String?save(?@Valid?OrderForm?order,BindingResult?result)?{??

    ????????//??

    ????????if(result.hasErrors()){??

    ????????????List<ObjectError>?ls=result.getAllErrors();??

    ????????????for?(int?i?=?0;?i?

    ????????????????log.error("參數(shù)不正確,OrderForm={}",?order);

    ????????????????throw?new?SellException(

    ?????????????????…………?,

    ?????????????result.getFeildError.getDefaultMessage()

    ??????????????)

    ????????????????System.out.println("error:"+ls.get(i));??

    ????????????}??

    ????????}??

    ????????return?"adduser";??

    ????}

    result.getFeildError.getDefaultMessage() 可拋出 “姓名必填” 的異常。

    4、List 轉為 Map

    public?class?Apple?{

    ????private?Integer?id;

    ????private?String?name;

    ????private?BigDecimal?money;

    ????private?Integer?num;

    ???/*構造函數(shù)*/

    }

    List<Apple>?appleList?=?new?ArrayList<>();//存放apple對象集合

    Apple?apple1?=??new?Apple(1,"蘋果1",new?BigDecimal("3.25"),10);

    Apple?apple12?=?new?Apple(1,"蘋果2",new?BigDecimal("1.35"),20);

    Apple?apple2?=??new?Apple(2,"香蕉",new?BigDecimal("2.89"),30);

    Apple?apple3?=??new?Apple(3,"荔枝",new?BigDecimal("9.99"),40);

    appleList.add(apple1);

    appleList.add(apple12);

    appleList.add(apple2);

    appleList.add(apple3);

    Map<Integer,?Apple>?appleMap?=?

    appleList.stream().collect(Collectors.toMap(Apple::getId,?a?->?a,(k1,k2)->k1));

    5、Collection 的子類:List、Set

    List:ArrayList、LinkedList 、Vector

    List:有序容器,允許 null 元素,允許重復元素

    Set:元素是無序的,不允許元素

    最流行的是基于 HashMap 實現(xiàn)的 HashSet,由 [hashCode() 和 equals()]保證元素的唯一性。

    可以用 set 幫助去掉 List 中的重復元素,set 的構造方法的參數(shù)可以是 List,構造后是一個去重的 set。

    HashMap 的補充:它不是 Collection 下的

    Map 可以使用 containsKey()/containsValue() 來檢查其中是否含有某個 key/value。

    HashMap 會利用對象的 hashCode 來快速找到 key。

    插入過程:通過一個 hash 函數(shù)確定 Entry 的插入位置 index=hash(key),但是數(shù)組的長度有限,可能會發(fā)生 index 沖突,當發(fā)生了沖突時,會使用頭插法,即為新來的 Entry 指向舊的 Entry,成為一個鏈表。

    每次插入時依次遍歷它的 index 下的單鏈表,如果存在 Key 一致的節(jié)點,那么直接替換,并且返回新的值。

    但是單鏈表不會一直增加元素,當元素個數(shù)超過 8 個時,會嘗試將單鏈表轉化為紅黑樹存儲。

    為何加載因子默認為 0.75?*(0.75 開始擴容)*

    答:通過源碼里的 javadoc 注釋看到,元素在哈希表中分布的桶頻率服從參數(shù)為 0.5 的泊松分布。

    源碼地址:

    https://github.com/923310233/wxOrder

    (完)

    歷史推薦

    1、作為阿里的面試官,我有話想說:面試,面試官比候選人還難!

    2、計算機仿真程序告訴你為什么現(xiàn)在不能出門(5分鐘視頻)

    3、Java程序員最常用的20%技術總結

    4、一只蝙蝠的自述在朋友圈火了

    公眾號ID|javabaiwen

    小編微信|204998835

    _

    每天分享技術干貨

    視頻 | 電子書 | 面試題?|?開發(fā)經(jīng)驗

    總結

    以上是生活随笔為你收集整理的开源项目工时系统_SpringBoot 微信点餐开源系统!综合运用项目,值得一看!的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 欧美在线播放一区二区 | 丰满白嫩尤物一区二区 | 国产情侣激情自拍 | 欧美亚洲另类图片 | 国产一区二区视频在线观看 | 狠狠操婷婷 | 91久久色 | 黄色网址av| 摸摸摸bbb毛毛毛片 午夜爽爽影院 | 欧美视频你懂的 | 草草影院网址 | 亚洲av无一区二区三区怡春院 | 美女裸体跪姿扒开屁股无内裤 | 青青在线观看视频 | 中文字幕av无码一区二区三区 | 国内精品久久久久久久 | 亚洲最大色网站 | 色婷婷成人 | 99国产精品无码 | 国产色吧 | av免费片 | 91丝袜美女 | ass亚洲熟妇毛耸耸pics | 中文字幕中文在线 | 永久免费汤不热视频 | 国产成人自拍偷拍 | 天天激情综合 | 日免费视频 | aaa亚洲 | 91色爱| 免费色片网站 | 男女啪啪免费网站 | 99re超碰| 亚欧中文字幕 | 日韩精品区 | 国产精品一区二区性色av | 精品中出| 日本人做受免费视频 | 日本久久久久久久久久 | 中文不卡视频 | 欧美激情首页 | 激情福利社| 成年人av在线 | 狠狠操狠狠摸 | 精品久久伊人 | av免费在线播放 | 午夜精品福利在线观看 | 丁香花完整视频在线观看 | 一区二区三区在线视频播放 | 爆乳2把你榨干哦ova在线观看 | 边打电话边做 | 光棍福利视频 | 青青草国产精品 | 女人做爰全过程免费观看美女 | 久久久久久久久国产精品 | 色综合综合 | 天天影视综合 | 久久精品视频免费播放 | 黄色一级视屏 | 在线观看亚洲精品视频 | 狠狠婷婷 | 国产香蕉视频在线播放 | 精品无码一区二区三区爱欲 | 久久观看最新视频 | 污污内射在线观看一区二区少妇 | 91丨九色丨蝌蚪丨丝袜 | 夜夜嗨影院| 黄色网一级片 | 那个网站可以看毛片 | 国产高清一区在线观看 | 久久精品一区二区 | 国产偷自拍 | 黄色一级影片 | 午夜免费福利小电影 | 免费看一级黄色大全 | 日本黄色免费网址 | 精品国产色 | 毛片在线观看网站 | 免费黄色一级 | 一区二区美女视频 | 最新国产三级 | 超碰97在线免费 | 青青色在线视频 | a级在线视频| 久久亚洲在线 | 激情五月色婷婷 | 青青草免费av | 91九色在线视频 | 中文字幕色站 | 亚洲综合激情在线 | 久久综合99 | 日本色中色 | 婷婷综合五月 | 亚洲熟妇av一区二区三区漫画 | 亚洲国产中文字幕在线观看 | 国产伦精品视频一区二区三区 | 黄网站色视频免费观看 | 国产偷亚洲偷欧美偷精品 | 国产精品毛片在线 |