<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.2">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2022-11-05T18:24:24+00:00</updated><id>/feed.xml</id><title type="html">Zxkun Blog</title><subtitle>Share knowledge of programming.</subtitle><author><name>Xingkun Zhang</name></author><entry><title type="html">随记</title><link href="/life/%E9%9A%8F%E8%AE%B0" rel="alternate" type="text/html" title="随记" /><published>2022-11-05T00:00:00+00:00</published><updated>2022-11-05T00:00:00+00:00</updated><id>/life/%20%E9%9A%8F%E8%AE%B0</id><content type="html" xml:base="/life/%E9%9A%8F%E8%AE%B0">&lt;p&gt;随记。&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;既然是随记，那就随意点吧。&lt;/p&gt;

&lt;p&gt;也不知道是什么时候，总是有一个问题会浮现在脑海。每当大脑有所空闲的时候，它就会自动跳出来，让你再也没有心思去考虑其他的事。为了不去想那个问题，只好把自己深埋到一件事里面，暂时让自己的大脑不去想它，然而一些想法一旦出现，就如同生根的野草，再也无法消灭，反而会随着时间的增加，渐渐布满整片草原，最终遮盖掉土地原有的样貌。&lt;/p&gt;

&lt;p&gt;那个问题是什么呢？其实是一个很简单的问题，我存在的意义到底是什么呢？&lt;/p&gt;

&lt;p&gt;其实有些时候，我还是能找到一些答案的，只是这些答案，都随着时间，渐渐失去了它们的价值。&lt;/p&gt;

&lt;p&gt;比如上大学之前，这个答案很清晰，就是考上一个好的大学，让父母开心。而那时候的我，也是为了这个目标而努力着。至少印象中，也是几乎把所有的时间用来学习。当然，那时候的我其实并没有感觉这有什么枯燥的，因为相比于其他事情，学习也许是最简单的一件事了，只需要待在那，静静地刷题就可以了，相比于其他复杂的事情，我更喜欢这种简简单单的事情。印象中，似乎很小的时候，我也并不想现在这样这么安静，甚至是有些木讷，应该也是有一段时间类似于熊孩子那样，做过一些比较中二的事情。&lt;/p&gt;

&lt;p&gt;只是不知道什么时候起，我开始变得沉默寡言，面对别人的欺凌，也不敢去还手，并因此导致了一条手臂骨折。毕竟当时其实也没有所谓的校园霸凌之说，当你受到欺负了，如果你退缩了，那你只能获得一次又一次变本加厉的对待。印象中的我，似乎求助过父母，不过也许当时的他们，觉得这并不算什么吧，毕竟小孩打打闹闹的，也不算什么。但也许就是从那时候起，我再也没有了所谓的安全感，很多时候，都处于一种高度紧张的状态，只是很多时候，也不知道这种紧张感从何而来，毕竟当初的很多事情，其实都已经没有了印象，只有一些影响特别深刻的事情，在脑海里留下一些印记，但是具体的细节，实际上也记不起来了。如果一件事，你都已经无法记清具体的细节了，那它还会影响你吗？我其实一直都找不到这个问题的答案。曾经的我，无法理解为什么有些人会以伤害他人为乐，现在我想，也许对他们而言，看到自己可以掌控他人的命运，也许就会感到很快乐吧，自己心情不好时，还可以找别人当出气筒，周围还有人附和。所以想一想，发生类似的事情，其实也正常，毕竟你无法保证每个人都内心向善。只是当你时隔多年以后见到它们中的一员，他们却似乎完全忘记了了这些事情，和朋友一样和你打招呼，总是无法去释然的。&lt;/p&gt;

&lt;p&gt;所以你认为的坏人，其实并不会因为他之前的行为付出任何代价，相反，因为自己的能言善辩，他们会过得比你更好。也许就是从那时候起，我就不再相信所谓的恶有恶报了吧。当然，有时候我也在想，我是不是太过小心眼了，毕竟小学的事情而已，毕竟当时他们其实也没有想太多其他的东西。只是我始终无法放下这些事情，即使那些事情现在也只是能记个大概，但是很多时候，它就莫名其妙的出现了，压得你喘不过气来。有时候我想，也许记得更清晰一点，我就能放下这些吧，毕竟对于模糊的事情，人总会无意识地放大它们的伤害，从而成为自己的借口，可惜，这终究只是一个想法罢了。&lt;/p&gt;

&lt;p&gt;渐渐到了初中，也许那是我最快乐的一段时光？至少理论上应该是这样吧，虽然当时像一个土鳖一样来到了那时的学校，但是至少因为学习成绩的原因，得到了一些老师的优待，而且也没有所谓的同学之间相互欺负的现象发生，毕竟每天除了教室就是宿舍，也有比较要好的朋友。可惜关于那三年的记忆，几乎都已经模糊掉。不过我还是能依稀记得当时每周末下午返校之前的情形，我似乎真的想要离开这个世界并做了些尝试，也许当时是害怕成绩下滑从而无法满足父母的期望？不过对于当时的我而言，成绩似乎真的成为了生命中最重要的一件事情。而且由于学校管理的原因，其实也没时间看些所谓的“闲书”之类的，不过过年回家看到那书架上摆的满满的的书，我就知道我肯定当时买过很多书，只是可惜，早已记不清当时的场景。&lt;/p&gt;

&lt;p&gt;也许就是初中毕业开始，我开始突然有些伤感别离。很多时候，其实我希望那些人，那些事情，就永远定格在那一刻，然而实际上，这永远都不可能发生。所以总是会有一种空落落的感觉。&lt;/p&gt;

&lt;p&gt;有时候把太多的希望放到一件事情上，那么最后得到的结果，往往就是失望。因为你见到的人多了，就会发现，其实比你优秀的人多得多，所以当他们认为你还能继续位列前茅时，其实你早就和普通学生一样了。毕竟他们和你一样，都是从前面筛出来的。况且和一无是处的你相比，别人要么能言善道，要么精通其他的事情，要么见过很多其他的风景，别人已经有了一条清晰的路，而你却只能凭自己的感觉，去找寻自己想要的东西。有时候太过在意自己擅长的东西，往往无法得到自己想要的结果。其实更通俗一点来说，也许某些时候，你确实在某些方面领先一些人，但是有些人就是比你优秀。但父母总会觉得，你排名下降了，好像也不像以前那样有底气去和别人夸赞了，尽管他们有时也会假装不在意这些，但其实你知道，这是他们最在意的东西。可惜终究不是以前了，最后你也只是去了所普普通通的本科学校，父母好像也很开心，但你总觉得，自己好像做错了些什么，似乎不应该考这么差的吧。&lt;/p&gt;

&lt;p&gt;也许当年离家这么远，多少也有些赌气的成分在里面，毕竟他们总是让你自己去做决定，其实你内心想的是，他们能不能主动一点，能不能去问一下你自己内心的真实想法，然而什么都没有发生。&lt;/p&gt;

&lt;p&gt;其实很多时候也想偶尔和家里通一下电话，但真等到了那时候，又不知道该说些什么，他们也觉得你很独立，觉得你能处理很多事情。实际上呢，其实很多时候你都摸着石头过河，闹出过很多笑话，但其实很多事情，他们确实知道的也没有你多。可是，总觉得少了些什么。&lt;/p&gt;

&lt;p&gt;其实很多时候也觉得奇怪，到底是为什么，就成了现在这个样子呢？其实对很多亲戚，包括父母，确实会有亲切感，但除此之外，好像就没有什么了，因为自从小学之后，对一些亲戚，见面的时间也只有过年那么几天了，而父母，也只是到时间回家时，一块吃顿饭，然后就得回到了学校的宿舍。上了大学后，回家的时间更是变成了每个学期一次，回家之后，他们也是早出晚归。虽然因为疫情的原因，在家呆了半年多，但是也只是在家上网课，空下的时间就疯狂沉迷于编程，和父母其实也没什么交流，也许他们认为，能供我上大学就可以了，就算是完成任务了，确实，他们完成任务了，但有些时候，我确实会陷入深深的自卑，毕竟我只是个从农村里出来的穷小子罢了。当然，我知道这种想法其实并不好，所以尝试去改变，然而事实证明，我终究还是无法做到和陌生人谈笑自若。因为除了学习和编程之外，我其实找不到其他的话题，况且大学的课程，能过就好，更多的时间其实是做些其他的事情，而我恰恰对所谓的其他事情没有什么兴趣，当然，某些时候也是怕花钱。所以有段时间出去找兼职，然而最后还是待在寝室里面敲代码。&lt;/p&gt;

&lt;p&gt;终于，大学毕业了，虽然他们很好奇我为什么不考研，虽然我嘴上说着也是考验性价比不高。实际上我已经承受不起考研失败的代价了，毕竟考不上双一流那等于白考，错过秋招那我真的不知道该怎么办了。当然更深层次的原因也许是我再也不想问家里人要钱了。依稀记得某个亲戚说谁自从上了大学就没有问家里人要过钱了，靠自己兼职到大学毕业，也许就是从那一刻开始，每次问家里人要钱总是心里会有些负罪感。而且上了大学后，很多想做的事情，很多想要的东西，都需要钱，不过当时的我并不会去逃课，其实就算重来一次，我也不会选择去逃课，所以也没有时间去兼职，也许就是从那时候起，我就已经决定好了毕业后就马上工作吧，因为已经满足了他们的期望，本科毕业了。不然如果读研，到时候还是需要家里供应，而且自己想做一些事情时，终究还是只能放弃。&lt;/p&gt;

&lt;p&gt;所以大学四年，虽然脱离了原来的束缚，但实际上似乎留下了更多的遗憾。很多事情，也许也并不是没有钱去做，也许就只是简简单单的因为我没有勇气罢了。&lt;/p&gt;

&lt;p&gt;毕业之前，一直期待着毕业后能够自己赚钱做自己想要做的事情，不过真到了毕业的时候，又会去伤感错过的人或事。不知道其他人会不会有这样的感觉，但是我却一直想要把某些瞬间永远定格在某一刻。其实一路走来，遇到过很多人，很多时候，就只是想保留那美好的一瞬间，然而最后，终究是没有勇气去继续保持联络，其实更多的是没有太多话题吧，但是总会有些莫名的失落感。&lt;/p&gt;

&lt;p&gt;其实刚毕业后也有过一段时间的失落期，不过很快就认识了更多的人，但其实很快就觉得，自己其实别人格格不入，其实更多时候感觉别人对你的善意，只不过是出于一种习惯罢了。&lt;/p&gt;

&lt;p&gt;其实人真的是一种很奇怪的生物，一旦见的东西多了，就会想更多的事情，也许当时的我，直接辍学其实更好吧，浑浑噩噩的度过一生其实也挺好的，不用想那么多的事情，就和普通人一样，每天关注些鸡毛蒜皮的小事，和旁边的人聊聊家长里短，可是我真的觉得这些东西很没有意义啊。&lt;/p&gt;

&lt;p&gt;况且毕业后也没有想象中的那么顺利，因为身边的人，确实都很优秀啊，凭自己那三脚猫的功夫，真不知道能不能度过半年的试用期。况且又住院做手术，又是要麻烦家里人过来，不过手术还算顺利，也算是一个好的结果了。而且自己工作了，虽然还是在试用期，终于也是有自己可以支配的资金了，虽然不知道未来如何，至少当下能够自力更生了。然而可能上天觉得我可能不配拥有开心这种情绪吧，之后家里人就确诊CML了。还好，控制慢性白血病的一些药已经进了医保，不然，我真不知道该从哪里去筹那么多的钱。其实得到消息的那一刻我真是有点懵，直到第二天，如果不是聊天记录的那张照片，我会以为我是在做梦，毕竟这种概率极小的事情，怎么就让我碰上了。可是千里之外的我，能做什么呢，毕竟试用期都还没过，而失掉了这份工作，下一份工作还不知道什么时候，如果到时候情况恶化，我也许也只能无能狂怒了吧。&lt;/p&gt;

&lt;p&gt;其实本来打算毕业后就安安稳稳的工作，自己之前没有实现的愿望，也借着机会去实现，也趁着这个机会，让自己更加外向一点。可惜事不遂人愿，毕竟敲代码不仅仅是敲代码，相比周围人即使离职依旧能找到更好的公司，我却没有任何的优势可言，家里人只会觉得，你找到了一份喜欢而且还算不错的工作，你也只能假装一切都顺利，可惜每天都在担心是不是在公司的最后一天。&lt;/p&gt;

&lt;p&gt;所以，活着的意义是什么呢？如果今后数十年的生活，就是看着亲人在病痛中被折磨，每天还是要省吃俭用，为后面的手术做准备，也许到时候工作不如意，连自己的生存都成了一个问题。&lt;/p&gt;

&lt;p&gt;世界上也许真的就只有一种病，穷病。我以为我能摆脱掉，然而现实证明，它从来就不会轻易的离开。&lt;/p&gt;

&lt;p&gt;其实在毕业那一刻谢幕，就已经是最完美的了吧，因为憧憬这种情绪，本来就是虚无缥缈的。其实我倒挺希望患病的是我，或者当初做手术出意外也好，因为这也算是一个正当的离去的理由。&lt;/p&gt;

&lt;p&gt;常常看到很多人说自杀的人懦弱，确实，有时候确实是这样，毕竟前路漫漫，如果看不到希望了，那么走下去的意义是什么呢？有时候你发现，其实世界上多你一个不多，少你一个也不少，而你和世界的联系，也只有那么微弱的一丝。即使某一天突然消失了，也不会有人在意，最多感叹一下，之后就消失在记忆里了。&lt;/p&gt;

&lt;p&gt;而你的亲人，对你最后的记忆，反倒是你很独立，确实，在生活上，某种意义上，确实是这样，可这是你想要的吗？生活所迫罢了。&lt;/p&gt;

&lt;p&gt;既然已经这么痛苦了，那么继续痛苦下去的意义是什么呢？&lt;/p&gt;

&lt;p&gt;很多时候，也想做出一些优秀的东西，得到别人的认可，看到自己写的教程帮助到了其他人，也很开心，可惜现实往往不会那么顺心。&lt;/p&gt;

&lt;p&gt;人真的是一种很奇怪的生物啊，有时候明明自己已经陷入泥沼，可是却总可以劝别人继续向前看。&lt;/p&gt;

&lt;p&gt;所以有些时候，想的太多确实不好，可惜某些想法进入脑海后，就再也无法剔除了。&lt;/p&gt;

&lt;p&gt;其实到了现在，最坏的情况也只有一种了，等到那时候，我也许才可以真正下定决心吧，想想也挺开心的，毕竟挣扎了这么久，也算是有个结局了。&lt;/p&gt;

&lt;p&gt;其实很多时候觉得，作者写作，是自己一种情绪的宣泄。确实如此吧，很多事情，只有落实到纸面上后，内心的情绪才会得到释放。虽然现状可能并没有什么改变，但是却可以下定决心做自己已经纠结了很久的事情。其实说到底，终究是内心的表现欲在作怪吧。虽然有些自欺欺人，但其实也算是一种自我安慰，表明自己至少曾经也做过努力。&lt;/p&gt;</content><author><name>Xingkun Zhang</name></author><category term="life" /><category term="idea" /><category term="note" /><summary type="html">随记。</summary></entry><entry><title type="html">上颌骨囊肿治疗历程</title><link href="/life/%E4%B8%8A%E9%A2%8C%E9%AA%A8%E5%9B%8A%E8%82%BF%E6%B2%BB%E7%96%97%E5%8E%86%E7%A8%8B" rel="alternate" type="text/html" title="上颌骨囊肿治疗历程" /><published>2022-09-18T00:00:00+00:00</published><updated>2022-09-18T00:00:00+00:00</updated><id>/life/%20%E4%B8%8A%E9%A2%8C%E9%AA%A8%E5%9B%8A%E8%82%BF%E6%B2%BB%E7%96%97%E5%8E%86%E7%A8%8B</id><content type="html" xml:base="/life/%E4%B8%8A%E9%A2%8C%E9%AA%A8%E5%9B%8A%E8%82%BF%E6%B2%BB%E7%96%97%E5%8E%86%E7%A8%8B">&lt;p&gt;本文主要介绍一下本人上颌骨囊肿的治疗历程，后面如果有人有相同病症的话，也可以以此为依据，根据自己的状况，及时去医院检查。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;1-前言&quot;&gt;1. 前言&lt;/h2&gt;

&lt;p&gt;对于上颌骨囊肿这个名词，可能很多人都没有听说过，但是其实这种病还是比较常见的。顾名思义，上颌骨囊肿其实就是长在上颌骨位置的一个囊肿，这种病大多数时候并不严重，而且囊肿一般也都是良性的。&lt;/p&gt;

&lt;p&gt;有的人囊肿比较小，如果不做检查的话，可能都不会发现在颌骨部位长了一个囊肿，这种情况下不需要做什么处理；对于稍大一点的囊肿，其实在门诊做一些引流，往往也能很快解决，恢复起来也很快。然而很不幸的是，我的囊肿比较大，必须要通过手术才能摘除。&lt;/p&gt;

&lt;h2 id=&quot;2-起因&quot;&gt;2. 起因&lt;/h2&gt;

&lt;p&gt;今年六月份正好毕业，收拾完东西，租好房子后，其实就等着入职了。虽说要处理一些毕业的事情，但实际上也没有多少事，跟着流程来，也都顺利完成了。然而，就在走完入职手续后，我发现我的鼻子左侧的脸颊似乎有点肿，用手摸一摸的话，是能感觉到有个肿块在里面的，我心里顿时凉了半截，心想这是什么情况，早不出现晚不出现，偏偏在我入职后出现这种情况。&lt;/p&gt;

&lt;p&gt;当时脑中出现的第一个想法就是要不先别管了，等到培训结束后再说，毕竟只是看起来有点肿，摸起来也不痛，似乎也没什么太大影响。然而自从我发现这个现象后，就总是忍不住摸脸上肿胀的地方，最后还是忍不住去了小区门口的牙科诊所看了下。然后我一次听到了颌骨囊肿这个词。&lt;/p&gt;

&lt;p&gt;当时诊所的的医生判断囊肿大概是3x2cm，已经算是一个比较大的囊肿了，拍完片子后也发现确实如此。像这么大的囊肿，诊所自然是无法摘除的（当时天真的我以为也许在诊所引流下，把这个包里面的液体引流出来就好了），况且由于诊所没法做病理检测，实际上他们也没法确定这是一个良性的囊肿还是其他更严重的东西。于是就推荐我直接去武大口腔那边挂号看一下，挂的是头颈肿瘤科室的号。&lt;/p&gt;

&lt;p&gt;当时我大脑瞬间一片空白，毕竟我上次去这种大医院，还是小学手臂骨折的时候，况且那时候也只是打了个石膏。这时候突然要我一个人去医院，挂号看病的流程我也不清楚，尤其是这种病听起来似乎还很严重，入职的喜悦也被冲的一干二净，只剩下忧虑。&lt;/p&gt;

&lt;h2 id=&quot;3-初诊&quot;&gt;3. 初诊&lt;/h2&gt;

&lt;p&gt;医院看病的流程其实也挺清晰，基本就是下面几个步骤：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;网上挂号；&lt;/li&gt;
  &lt;li&gt;用身份证（如果没带身份证就需要填个单子），办就诊卡，充值；&lt;/li&gt;
  &lt;li&gt;到对应的科室前台处签到，后面就等叫号就可以了。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;看病的过程也算是一波三折，由于当天临时挂号，排的位置很靠后，轮到我的时候，已经很晚了。专家看完后，觉得可能就是一个普通的囊肿，但是还需要片子确认，然而科室的电脑没有联网，而且诊所拍的片子生成的电子文件也没法在手机上预览，于是只好在医院又拍了一次片子。由于第一次去医院，对各个窗口也不是很熟悉，所以缴费没有那么及时，轮到我拍片的时候，离下班也就半个小时左右，这里提醒去医院看病的小伙伴，一定要及时缴费。&lt;/p&gt;

&lt;p&gt;不过还好，虽然片子还没有打印出来，但是电脑上已经能看到了，最后诊断是上颌骨囊肿。而且比较麻烦的是，由于囊肿已经比较大了，所以只能住院做手术摘除，如果拖的太晚，那涉及到到的五颗牙齿可能都保不住了，除此之外，还有一些其他的问题，不过囊肿的问题是最严重的。然而想到我马上就要参加公司的培训了，所以只能往后推迟一个月。毕竟刚入职就请假，而且还错过公司的培训，那绝对是能够让自己凉透的操作。&lt;/p&gt;

&lt;h2 id=&quot;4-住院前夕&quot;&gt;4. 住院前夕&lt;/h2&gt;

&lt;p&gt;幸好，将近一个月的培训中，并没有出现什么特别的情况，培训也算是圆满结束，只是囊肿似乎越来越大了，感觉有点压迫眼睛（也可能是我的心理作用），幸好培训过程中比较投入，虽然总是忍不住想囊肿的事情，但是由于把自己每天的计划都安排的满满当当的，所以也没有多少闲工夫来思考这些杂事，只是偶尔空闲的时候，心情总是会有些沉重，然而还总是要保持一种积极向上的状态，毕竟培训期间还是要好好表现的，这种割裂感往往才是最让人无力的吧。&lt;/p&gt;

&lt;p&gt;虽然不想请假，但是该请还是要请，毕竟八月份就必须要把手术做了，如果拖到国庆，虽然不用请假了，但是可能那几颗牙也就和我说再见了。&lt;/p&gt;

&lt;p&gt;然而请假也没有那么顺利。&lt;/p&gt;

&lt;p&gt;本来以为八月初就能做手术，然而医院那边却一直没床位，问什么时候有床位，一直不确定。我这住院证都开了一个月了，那我至少相当于提前一个月排队了吧，结果还要等。等也就罢了，连个确定的日期都不给，这让我怎么请假？毕竟这还是一周的长假。本来请这么长的假就已经很不合适了，如果临时请的话，那就更不合适了，况且培训结束后，公司也要安排项目了，你这还有这么长的一个假不确定什么时候请。当时真是压力山大，生怕什么事情做不好。&lt;/p&gt;

&lt;p&gt;最后终于确定了在八月中旬做手术，也赶紧请了假，由于是全麻，需要有家人陪同。然而我家里人都在千里之外，然而这还不是最让人头疼的，如果是外省的人，还需要三天两检，也就是说到达本省后，必须第三天的核酸阴性结果出来后，才能进医院，那时候我才能做手术，如果能安排上的话。&lt;/p&gt;

&lt;p&gt;我头一次感受到了来自疫情的恶意，在此之前，各种核酸检测，层层加码，虽然不是很喜欢，但是也没有怎么抵触，毕竟大家都一样，况且我也不怎么喜欢出去。然而周三开始的假，周一我才知道还有这种政策，毕竟之前我以为的三天两检是落地捡，加上24小时后的核酸检测是阴性就可以了。&lt;/p&gt;

&lt;p&gt;于是马上联系家里人，正好我姐夫在，于是连夜坐飞机赶了过来。之所以这么急是因为医院周末不做手术，如果而且做完手术后也需要恢复，如果真是因为家属没有陪同，导致延期到下一周做手术，那么上一周的假相当于白请。&lt;/p&gt;

&lt;h2 id=&quot;5-住院&quot;&gt;5. 住院&lt;/h2&gt;

&lt;p&gt;就这样，周三上午到了医院办入院手续，结果上午没有床位，只好推迟到了下午，期间也把各种手术前的检查做了一遍，因为来之前通知如果顺利的话，第二天就能安排手术。结果自然是没有那么顺利，不过最终还是安排到了周五手术，这样有一个周末作为缓冲，也能多恢复一下。&lt;/p&gt;

&lt;p&gt;虽然住院之前的经历并不愉快，但是住院后的体验还是很不错的，医院的医生都挺细心的。尤其是术前需要做根管，这样可以最大程度上保证术后也不会脱落。由于我五颗牙都需要做根管，当时通知的时候，已经快中午了，一个下午肯定做不完，但是当医生知道我第二天早上要做手术的时候，硬是从下午两点做到了晚上快九点，中间也没休息，顺利做完五颗牙。这里还是要点一个赞。&lt;/p&gt;

&lt;p&gt;不过做根管的过程也是有些痛苦，毕竟时间很长，想想近七个小时，大部分时间躺在椅子上，时不时还要拍片判断填充物是不是到了正确的位置，再有就是嘴要一直张着。那种经历我这辈子都不想体验第二次。&lt;/p&gt;

&lt;p&gt;相比而言，手术倒还算顺利，毕竟全麻也没什么感觉，手术两个小时就结束了。&lt;/p&gt;

&lt;p&gt;下面是摘除的囊肿的照片。&lt;/p&gt;

&lt;p&gt;高能预警！！！！！！&lt;/p&gt;

&lt;p&gt;—————————————————-华丽的分割线——————————&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../assets/images/resource/2022-09-18- 上颌骨囊肿治疗历程.assets/WechatIMG45.jpeg&quot; alt=&quot;WechatIMG45&quot; /&gt;&lt;/p&gt;

&lt;p&gt;————————分割线———————&lt;/p&gt;

&lt;p&gt;由于是全麻，做完手术后脑袋昏昏沉沉的，直到快到晚上了，才真正清醒过来。手术部位用冰袋冷敷，主要是为了消肿。&lt;/p&gt;

&lt;p&gt;不知道是镇痛泵还是其他缘故，虽然我左侧几乎所有牙齿牙龈部位都有缝线，但我却感觉不到疼痛。但是我后面在网上搜索了一下，镇痛泵其实作用也没有那么大。那应该就是医生手术做的比较好吧，所以不怎么痛。&lt;/p&gt;

&lt;p&gt;看到我做完手术后状态还行，我家里人就回去了，毕竟还要工作的。&lt;/p&gt;

&lt;p&gt;后面几天就是挂吊瓶，一些消炎之类的药，脸也没一开始那么肿了。&lt;/p&gt;

&lt;p&gt;于是到了下周一，上午挂完吊瓶后，就出院了，刚好下午上班。这样算起来，实际上就三天半的假，也算是一切顺利，然而由于社保系统升级，导致社保卡没法办，于是只能先自费垫付。结果这刚上班，还没怎么赚钱，就要家里先贴钱了，这也没谁了，没钱，真是连病都生不起。&lt;/p&gt;

&lt;p&gt;整个住院过程就算是结束了。&lt;/p&gt;

&lt;p&gt;后续就是等待切口的愈合以及颌骨重新长好了。&lt;/p&gt;

&lt;p&gt;住院期间的话，对于短期住院，也不需要准备太多的东西，只要下面这些其实基本就够了：&lt;/p&gt;

&lt;ol&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;洗漱用品&lt;/li&gt;
  &lt;li&gt;毛巾&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;如果是长期住院，比如一周以上，那就需要多准备点东西了。&lt;/p&gt;

&lt;p&gt;此外关于住院、挂号、手术、复查的医生，其实我也挺迷的，因为负责住院的医生、看病的专家、手术的医生、复查的医生，都可以不是一个人……&lt;/p&gt;

&lt;p&gt;只是说看病和做手术的医生是同科室，不知道大医院都这样子还是其他原因导致的。&lt;/p&gt;

&lt;h2 id=&quot;6-复查&quot;&gt;6. 复查&lt;/h2&gt;

&lt;h3 id=&quot;1-伤口发炎&quot;&gt;1. 伤口发炎&lt;/h3&gt;

&lt;p&gt;虽然出院的时候脸还是有点肿，但是医生说慢慢消肿，所以也就没在意。然而一周后，手术部位出现了一个硬块，而且脸更肿了。由于科室周末没有号，只能周一到周五挂号，顿时让我陷入了两难的抉择。毕竟这才刚请完假不久，总不能又请假去复查吧，于是只好挂了上午最早的号，结果医生查房很晚才过来，导致差点上班迟到，不过也确实是发炎了，需要打几天消炎针。当然也是第一次这么晚到公司，鉴于之前实习期员工的传言，又一次感受到了生活的恶意。&lt;/p&gt;

&lt;p&gt;不过还好，打完消炎针后，硬块消失了，只是脸依旧有些肿，可能是一些积液需要时间慢慢吸收吧，&lt;/p&gt;

&lt;h3 id=&quot;2-术后一月复查&quot;&gt;2. 术后一月复查&lt;/h3&gt;

&lt;p&gt;兜兜转转，做完手术也一个多月了，虽然切口都愈合了，一些缝线也渐渐吸收了。但是牙龈部位一直有些肿胀，按一下就瘪下去了，只好先去小诊所看了下（挂号太难了），可能问题不大，也可能是和原来囊肿所在的位置形成了通道，那就比较麻烦了，只好等下周去医院复查了，希望一切顺利吧。&lt;/p&gt;

&lt;p&gt;未完待更。。。&lt;/p&gt;

&lt;hr /&gt;

&lt;h2 id=&quot;7-后记&quot;&gt;7. 后记&lt;/h2&gt;

&lt;p&gt;在口腔的囊肿里面，上颌骨囊肿算是比较好的一种情况了，因为术后的复发率低一些，而下颌骨囊肿，术后的复发率就要高很多。&lt;/p&gt;

&lt;p&gt;此外之前还没怎么注意，上班了后才发现，很多面向社会的机构，都是周一到周五上班，或者很多业务都是周一到周五才能办，这就和正常的上班时间一样，所以要办什么业务只能请假去办，也不知道类似的这些机构，什么时候可以调整一些时间，比如工作日的某天调整到周末，这样也不用非得请假才能去办理业务了，只是现在看来，似乎任重而道远。&lt;/p&gt;</content><author><name>Xingkun Zhang</name></author><category term="life" /><category term="life" /><category term="experience" /><category term="disease" /><summary type="html">本文主要介绍一下本人上颌骨囊肿的治疗历程，后面如果有人有相同病症的话，也可以以此为依据，根据自己的状况，及时去医院检查。</summary></entry><entry><title type="html">C#扩展方法理解</title><link href="/c%23/C-%E6%89%A9%E5%B1%95%E6%96%B9%E6%B3%95%E7%90%86%E8%A7%A3" rel="alternate" type="text/html" title="C#扩展方法理解" /><published>2022-09-06T00:00:00+00:00</published><updated>2022-09-06T00:00:00+00:00</updated><id>/c%23/C#%E6%89%A9%E5%B1%95%E6%96%B9%E6%B3%95%E7%90%86%E8%A7%A3</id><content type="html" xml:base="/c%23/C-%E6%89%A9%E5%B1%95%E6%96%B9%E6%B3%95%E7%90%86%E8%A7%A3">&lt;p&gt;在某些情况下，我们需要为一些类添加方法，对于我们自己编写的类或接口的，我们很容易实现这一点，但是对于一些第三方的类库，我们却很难做到，虽然可以采用继承等方式实现，但这些方法都需要编写更多的代码，而且不够灵活。所以无论是第三方类库，还是我们自己编写的代码，如果我们想要在不破坏原有类型的基础上，添加一些其他的方法，这时候就可以使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C#&lt;/code&gt;的扩展方法实现。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;1-基本使用&quot;&gt;1. 基本使用&lt;/h2&gt;

&lt;div class=&quot;language-c# highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Extension method allow us to extend new method for existing class or interface and we do not need to rewrite them.&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;firstName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PersonHelper&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetFullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FirstName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Rob&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Li&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extensionFullName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetFullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;staticFullName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PersonHelper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetFullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extensionFullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;staticFullName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;比如我们要实现一个获取全名的方法，只需要编写一个静态类，以及编写相应的方法就可以了。&lt;/p&gt;

&lt;p&gt;这里需要注意的是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;person.GetFullName()&lt;/code&gt;在实际使用的时候，会被转化成普通的静态方法调用，即&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PersonHelper.GetFullName(person)&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;2-链式调用与命名空间引入&quot;&gt;2. 链式调用与命名空间引入&lt;/h2&gt;

&lt;div class=&quot;language-c# highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;DefineMain&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;using&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ExtensionMethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MainClass&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;doubleName&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetDoubleString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt; 
            &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;doubleName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// NameName&lt;/span&gt;
            &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetDoubleString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetDoubleString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;//NameNameNameName&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;namespace&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ExtensionMethod&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringHelper&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetDoubleString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;使用扩展方法时，必须导入扩展方法所在的命名空间，这时候才能使用。这和使用相应的类时，导入对应的命名空间是一样的。&lt;/p&gt;

&lt;p&gt;此外扩展方法支持链式调用，比如&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;name.GetDoubleString()&lt;/code&gt;的返回类型依旧是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;string&lt;/code&gt;，所以依旧可以继续使用扩展方法。&lt;/p&gt;

&lt;h2 id=&quot;3-优先级&quot;&gt;3. 优先级&lt;/h2&gt;

&lt;p&gt;如果扩展方法方法名与实例的方法名一样，在参数数量一致的情况下，总是会优先调用实例的方法，即使扩展方法参数的类型比实例方法的参数类型更加具体&lt;/p&gt;

&lt;div class=&quot;language-c# highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Person&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;MyName&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetLastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PersonHelper&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;No Param&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&quot;No Param &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetLastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&quot;LastName &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;person&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// MyName&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Lucy&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// No Param Lucy&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetLastName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Jack&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Jack&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;但是，如果多个扩展方法方法签名一样，参数类型更加具体的方法优先级更高&lt;/p&gt;

&lt;div class=&quot;language-c# highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringHelper&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; string&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StringHelperCopy&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;$&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; object&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Rob&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// Rob string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;4-总结&quot;&gt;4. 总结&lt;/h2&gt;

&lt;h3 id=&quot;1-扩展方法形式&quot;&gt;1. 扩展方法形式&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;必须被定义在非嵌套、非泛型静态类的内部；&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;方法的第一个参数为this，第一个参数的类型为要扩展的类型；&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;2-注意事项&quot;&gt;2. 注意事项&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;使用时，必须使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using&lt;/code&gt; 引入扩展方法所在的命名空间；&lt;/li&gt;
  &lt;li&gt;实例方法与扩展方法，方法签名，参数一致时，即使扩展方法的参数类型更加具体，也会优先调用实例的方法；&lt;/li&gt;
  &lt;li&gt;扩展方法与扩展方法，方法签名，参数一致时，优先调用参数更加具体的扩展方法。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;3-理解&quot;&gt;3. 理解&lt;/h3&gt;

&lt;p&gt;对于实例方法，即使方法没有参数，实际上也会有一个隐藏的参数，也就是this，即实例本身；扩展方法之所以用this加对象类型作为方法的第一次参数，实际上也是为了引入实例对象，只不过相当于是显示指定的this这个默认的参数。&lt;/p&gt;

&lt;h2 id=&quot;5-参考资料&quot;&gt;5. 参考资料&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;《C# 8.0核心技术指南》&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Xingkun Zhang</name></author><category term="C#" /><category term="C#" /><category term="extension method" /><summary type="html">在某些情况下，我们需要为一些类添加方法，对于我们自己编写的类或接口的，我们很容易实现这一点，但是对于一些第三方的类库，我们却很难做到，虽然可以采用继承等方式实现，但这些方法都需要编写更多的代码，而且不够灵活。所以无论是第三方类库，还是我们自己编写的代码，如果我们想要在不破坏原有类型的基础上，添加一些其他的方法，这时候就可以使用C#的扩展方法实现。</summary></entry><entry><title type="html">Mapstruct基本使用</title><link href="/java/Mapstruct%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8" rel="alternate" type="text/html" title="Mapstruct基本使用" /><published>2022-07-30T00:00:00+00:00</published><updated>2022-07-30T00:00:00+00:00</updated><id>/java/Mapstruct%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8</id><content type="html" xml:base="/java/Mapstruct%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8">&lt;p&gt;在日常的项目开发过程中，数据的存储结构和我们想要得到的数据结构往往是不一样的，为了让数据可以更好的传输，我们往往需要对获得的原始数据进行一些封装，将封装好的数据进行传输，在Java中，大多数的工具类常常使用反射的方式对对象的属性进行提取，这样就会降低程序的运行速度。而Mapstruct则是根据接口生成对应的属性转换类。这样只会增加程序编译的时间，由于在程序运行过程中是调用的转换类对对象的属性进行转换，因此和反射相比，可以大大加快程序的运行速度。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;1-基本使用&quot;&gt;1. 基本使用&lt;/h2&gt;

&lt;p&gt;假设需要进行转换的类为&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Data&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numberOfSeats&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CarType&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;转换后的类为&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CarDto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seatCount&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CarType&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;如果要进行转换，需要定义一个接口来编写转换的逻辑&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Mapper&lt;/span&gt; 
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CarMapper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
 
    &lt;span class=&quot;nc&quot;&gt;CarMapper&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;INSTANCE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Mappers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getMapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CarMapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; 
 
    &lt;span class=&quot;nd&quot;&gt;@Mapping&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;numberOfSeats&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;seatCount&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;CarDto&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;carToCarDto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Car&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt; 
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;使用&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;shouldMapCarToDto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;//given&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;Car&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Morris&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CarType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;SEDAN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
 
    &lt;span class=&quot;c1&quot;&gt;//when&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;CarDto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;carDto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CarMapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;INSTANCE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;carToCarDto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
 
    &lt;span class=&quot;c1&quot;&gt;//then&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;carDto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isNotNull&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;carDto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getMake&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isEqualTo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Morris&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;carDto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getSeatCount&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isEqualTo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assertThat&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;carDto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;isEqualTo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;SEDAN&quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;只要字段名一样，Mapstruct就会尝试进行转换，比如将枚举类的枚举类型转化为字符串，如果无法转换就会报错。&lt;/p&gt;

&lt;h2 id=&quot;2-在spring中的使用&quot;&gt;2. 在Spring中的使用&lt;/h2&gt;

&lt;p&gt;Mapstruct也可以使用依赖注入的方式进行使用，从而可以被Spring的容器所管理，具体的使用过程如下&lt;/p&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Component&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@AllArgsConstructor&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GoodListConvert&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GoodMapper&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;goodMapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Named&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;getGoodResponse&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;GoodResponse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getGoodResponse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Orders&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;orders&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;orders&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getGoodsList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;goodMapper:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;goodsToGoodResponse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Collectors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Mapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;componentModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;spring&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unmappedSourcePolicy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ReportingPolicy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;IGNORE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;GoodMapper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;nc&quot;&gt;GoodResponse&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;goodsToGoodResponse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Goods&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;goods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nd&quot;&gt;@Mapper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;componentModel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;spring&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;unmappedSourcePolicy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ReportingPolicy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;IGNORE&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;uses&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;GoodListConvert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;DeliveryTypesConvert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;TotalPriceConvert&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;OrderMapper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Mapping&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;totalPrice&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qualifiedByName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;sumTotalPrice&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Mapping&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;goodsList&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qualifiedByName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;getGoodResponse&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@Mapping&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;deliveryTypes&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qualifiedByName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;getDeliveryTypes&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;.&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nc&quot;&gt;OrderResponse&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ordersToOrderResponse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Orders&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;orders&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;参考资料&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https://mapstruct.org/&quot;&gt;Mapstruct官网&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;</content><author><name>Xingkun Zhang</name></author><category term="java" /><category term="java" /><category term="mapstruct" /><category term="bean" /><summary type="html">在日常的项目开发过程中，数据的存储结构和我们想要得到的数据结构往往是不一样的，为了让数据可以更好的传输，我们往往需要对获得的原始数据进行一些封装，将封装好的数据进行传输，在Java中，大多数的工具类常常使用反射的方式对对象的属性进行提取，这样就会降低程序的运行速度。而Mapstruct则是根据接口生成对应的属性转换类。这样只会增加程序编译的时间，由于在程序运行过程中是调用的转换类对对象的属性进行转换，因此和反射相比，可以大大加快程序的运行速度。</summary></entry><entry><title type="html">Gradle Could not initialize class问题解决</title><link href="/gradle/Gradle-Could-not-initialize-class%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3" rel="alternate" type="text/html" title="Gradle Could not initialize class问题解决" /><published>2022-07-26T00:00:00+00:00</published><updated>2022-07-26T00:00:00+00:00</updated><id>/gradle/Gradle%20Could%20not%20initialize%20class%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3</id><content type="html" xml:base="/gradle/Gradle-Could-not-initialize-class%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86%B3">&lt;p&gt;使用项目路径下的gradlew命令构建项目时，出现报错提示Could not initialize class org.codehaus.groovy.runtime.InvokerHelper&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;1-问题描述&quot;&gt;1. 问题描述&lt;/h2&gt;

&lt;p&gt;使用项目路径下的gradlew命令构建项目时，出现报错提示&lt;/p&gt;

&lt;p&gt;Could not initialize class org.codehaus.groovy.runtime.InvokerHelper&lt;/p&gt;

&lt;h2 id=&quot;2-解决方法&quot;&gt;2. 解决方法&lt;/h2&gt;

&lt;blockquote&gt;
  &lt;p&gt;For Mac&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;找到项目路径下的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gradle/wrapper/gradle-wrapper.properties&lt;/code&gt;路径，查看构建项目使用的gradle版本。&lt;/p&gt;

    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;distributionUrl=https\://services.gradle.org/distributions/gradle-5.3-bin.zip&lt;/code&gt;里面的5.3即gradle的版本。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;下载与Gradle版本对应的JDK版本，对应Gradle需要的JDK版本可以从官网查看&lt;/p&gt;

    &lt;p&gt;https://docs.gradle.org/current/userguide/compatibility.html&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;以openJDK为例，在openJDK官网，下载满足要求的JDK版本(Mac版本)&lt;/p&gt;

    &lt;p&gt;https://jdk.java.net/archive/&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;解压后，将其移动到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Library/Java/JavaVirtualMachines/&lt;/code&gt;路径下(以17.0.2为例)&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo mv&lt;/span&gt; ~/Downloads/jdk-17.0.2.jdk /Library/Java/JavaVirtualMachines/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;编辑.zshrc文件，配置JAVA_HOME&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;vim ~/.zshhrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;添加&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;JAVA_HOME&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;$(&lt;/span&gt;/usr/libexec/java_home &lt;span class=&quot;nt&quot;&gt;-v&lt;/span&gt; 17.0.2&lt;span class=&quot;si&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;export &lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;PATH&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;$PATH&lt;/span&gt;:&lt;span class=&quot;k&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;JAVA_HOME&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;}&lt;/span&gt;/bin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;运行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;echo $JAVA_HOME&lt;/code&gt;，此时&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JAVA_HOME&lt;/code&gt;的路径以及java版本就和我们预期的一致了，这样gradlew就可以找到对应的JDK版本&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;3-解析&quot;&gt;3. 解析&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;为什么要复制到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Library/Java/JavaVirtualMachines/&lt;/code&gt;路径下，而不是自己指定一个位置，直接设置&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JAVA_HOME&lt;/code&gt;路径？&lt;/p&gt;

    &lt;p&gt;在Mac OS X 10.5之后， &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/libexec/&lt;/code&gt; 路径下多了一个叫java_home的文件，这是Mac上专门用来管理&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JAVA_HOME&lt;/code&gt;的文件，我们可以靠它得到不同版本的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JAVA_HOME&lt;/code&gt;，而&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/libexec/java_home&lt;/code&gt;会自动映射到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Library/Java/JavaVirtualMachines/jdk-17.0.2.jdk/Contents/Home&lt;/code&gt;这个路径下，其中&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jdk-17.0.2.jdk&lt;/code&gt;为JDK的版本。&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;/usr/libexec/java_home &lt;span class=&quot;nt&quot;&gt;-V&lt;/span&gt;
Matching Java Virtual Machines &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;2&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;:
    17.0.2 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;x86_64&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Oracle Corporation&quot;&lt;/span&gt; - &lt;span class=&quot;s2&quot;&gt;&quot;OpenJDK 17.0.2&quot;&lt;/span&gt; /Library/Java/JavaVirtualMachines/jdk-17.0.2.jdk/Contents/Home
    1.8.0_201 &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;x86_64&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;Oracle Corporation&quot;&lt;/span&gt; - &lt;span class=&quot;s2&quot;&gt;&quot;Java SE 8&quot;&lt;/span&gt; /Library/Java/JavaVirtualMachines/jdk1.8.0_201.jdk/Contents/Home
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;运行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/libexec/java_home -V&lt;/code&gt;命令，会得到所有的JDK版本，以&lt;/p&gt;

    &lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;17.0.2 (x86_64) &quot;Oracle Corporation&quot; - &quot;OpenJDK 17.0.2&quot; /Library/Java/JavaVirtualMachines/jdk-17.0.2.jdk/Contents/Home
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;为例，其中&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;17.0.2&lt;/code&gt;为版本，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Library/Java/JavaVirtualMachines/jdk-17.0.2.jdk/Contents/Home&lt;/code&gt;为JDK所在的位置。&lt;/p&gt;

    &lt;p&gt;在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt;文件中配置的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/libexec/java_home -v 17.0.2&lt;/code&gt;实际上就是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Library/Java/JavaVirtualMachines/jdk-17.0.2.jdk/Contents/Home&lt;/code&gt;，如果指定版本，即去掉&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-v 17.0.2&lt;/code&gt;，那么默认配置的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JAVA_HOME&lt;/code&gt;位置就是运行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/libexec/java_home -V&lt;/code&gt;命令后，最后一行显示的那个版本&lt;/p&gt;

    &lt;p&gt;所以如果想要安装多个版本的JDK，就可以通过这种方法来很方便的切换JDK版本。&lt;/p&gt;

    &lt;p&gt;同时，如果没有在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt;中设置&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JAVA_HOME&lt;/code&gt;变量，那么默认的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JAVA_HOME&lt;/code&gt;实际上就是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt; /usr/libexec/java_home&lt;/code&gt;里面指定的版本。&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Library/Java/JavaVirtualMachines/&lt;/code&gt;并不是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/libexec/java_home&lt;/code&gt;的唯一映射路径，它实际上还会映射到&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Library/Internet\ Plug-Ins/JavaAppletPlugin.plugin &lt;/code&gt;，以及用户目录下的几个路径，从这几个路径中获取JDK&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;4-使用asdf快速切换jdk&quot;&gt;4. 使用asdf快速切换JDK&lt;/h2&gt;

&lt;p&gt;安装asdf&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;brew &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;asdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;安装java插件&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;asdf plugin add java
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;修改&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.zshrc&lt;/code&gt;文件，添加&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; /usr/local/opt/asdf/libexec/asdf.sh
 &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt; ~/.asdf/plugins/java/set-java-home.zsh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;使配置文件 立即生效&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ~/.zshrc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;安装JDK&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;asdf &lt;span class=&quot;nb&quot;&gt;install &lt;/span&gt;java adoptopenjdk-17.0.3+7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;设置Java版本为17.0.3&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;asdf global java adoptopenjdk-17.0.3+7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;之后便可以使用java了。&lt;/p&gt;

&lt;h2 id=&quot;参考资料&quot;&gt;参考资料&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://docs.gradle.org/current/userguide/compatibility.html&quot;&gt;Gradle 与 JDK版本对应关系&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://stackoverflow.com/questions/35000729/android-studio-could-not-initialize-class-org-codehaus-groovy-runtime-invokerhel&quot;&gt;Gradle 与JDK版本不对应导致报错&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Mac 扫描到的JDK位置&lt;/p&gt;

    &lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/supercooly/article/details/52252126&quot;&gt;Article1&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;&lt;a href=&quot;https://juejin.cn/post/6871959224314757134&quot;&gt;Article2&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;&lt;a href=&quot;https://blog.csdn.net/caoxiaohong1005/article/details/73611424&quot;&gt;Article3&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;asdf与java插件配置&lt;/p&gt;

    &lt;p&gt;&lt;a href=&quot;https://asdf-vm.com/&quot;&gt;asdf&lt;/a&gt;&lt;/p&gt;

    &lt;p&gt;&lt;a href=&quot;https://github.com/halcyon/asdf-java&quot;&gt;asdf-java&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href=&quot;https://brew.sh/index_zh-cn&quot;&gt;homebrew安装&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;</content><author><name>Xingkun Zhang</name></author><category term="gradle" /><category term="gradle" /><category term="mac" /><category term="java" /><summary type="html">使用项目路径下的gradlew命令构建项目时，出现报错提示Could not initialize class org.codehaus.groovy.runtime.InvokerHelper</summary></entry><entry><title type="html">指定长度与格式密码生成</title><link href="/java/%E6%8C%87%E5%AE%9A%E9%95%BF%E5%BA%A6%E4%B8%8E%E6%A0%BC%E5%BC%8F%E5%AF%86%E7%A0%81%E7%94%9F%E6%88%90" rel="alternate" type="text/html" title="指定长度与格式密码生成" /><published>2022-06-24T00:00:00+00:00</published><updated>2022-06-24T00:00:00+00:00</updated><id>/java/%E6%8C%87%E5%AE%9A%E9%95%BF%E5%BA%A6%E4%B8%8E%E6%A0%BC%E5%BC%8F%E5%AF%86%E7%A0%81%E7%94%9F%E6%88%90</id><content type="html" xml:base="/java/%E6%8C%87%E5%AE%9A%E9%95%BF%E5%BA%A6%E4%B8%8E%E6%A0%BC%E5%BC%8F%E5%AF%86%E7%A0%81%E7%94%9F%E6%88%90">&lt;p&gt;在开发过程中，我们常常需要设置一些初始化账户来供用户操作使用。这时候就需要为账户设置密码，为了让密码尽量随机，可以采用程序随机生成的方式，生成满足一定要求的密码。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;1-常见密码格式&quot;&gt;1. 常见密码格式&lt;/h2&gt;

&lt;h3 id=&quot;密码要求&quot;&gt;密码要求&lt;/h3&gt;

&lt;p&gt;在一些网站的注册中，注册账户时，密码通常具有以下要求：&lt;/p&gt;

&lt;ol&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;/ol&gt;

&lt;h3 id=&quot;密码格式&quot;&gt;密码格式&lt;/h3&gt;

&lt;p&gt;以上四种密码在java中，可以用正则表达式进行验证，这里假设密码的最短长度为8个字符，那么对应的正则表达式如下所示：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,}$&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;^(?=.*[A-Za-z])(?=.*\\d)(?=.*[\\\\!@#$%^&amp;amp;*()_+-=\\[\\]{};':|,.&amp;lt;&amp;gt;/?~`\&quot;])[A-Za-z\\d\\\\!@#$%^&amp;amp;*()_+-=\\[\\]{};':|,.&amp;lt;&amp;gt;/?~`\&quot;]{8,}$&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[\\\\!@#$%^&amp;amp;*()_+-=\\[\\]{};':|,.&amp;lt;&amp;gt;/?~`\&quot;])[a-zA-Z0-9\\\\!@#$%^&amp;amp;*()_+-=\\[\\]{};':|,.&amp;lt;&amp;gt;/?~`\&quot;]{8,}$&quot;&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;特殊字符&quot;&gt;特殊字符&lt;/h3&gt;

&lt;p&gt;一共有33个特殊字符（可以用键盘输入的），其中就包括空格。如果考虑空格，那么密码在校验过程中就会比较繁琐，因此使用剩下的32个特殊字符作为种子，用来随机生成密码。&lt;/p&gt;

&lt;p&gt;在Java中，一些字符的匹配需要转义后才能进行正确的匹配，如：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\\\\&lt;/code&gt;匹配&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\\[&lt;/code&gt;匹配&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;…&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;2设计思路&quot;&gt;2.设计思路&lt;/h2&gt;

&lt;h3 id=&quot;概述&quot;&gt;概述&lt;/h3&gt;

&lt;p&gt;明确了密码的常见格式，以及对应的正则表达式后，就可以进行代码的编写。&lt;/p&gt;

&lt;p&gt;由于需要随机生成密码，所以这里用到了Java内置的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SecureRandom&lt;/code&gt;类，用它来生成随机数。&lt;/p&gt;

&lt;p&gt;由于我们需要生成固定长度、固定格式的密码，这里首先获取密码的长度，之后便可以根据对应格式的格式来生成密码。&lt;/p&gt;

&lt;p&gt;这里举例进行说明。&lt;/p&gt;

&lt;h3 id=&quot;至少包含一个英文字母和一个数字&quot;&gt;至少包含一个英文字母和一个数字&lt;/h3&gt;

&lt;p&gt;首先创建两个数组，分别包含大小写英文字母（LOWER_AND_UPPER_LETTERS），数字（NUMBERS）。&lt;/p&gt;

&lt;p&gt;假设生成密码的长度为8.&lt;/p&gt;

&lt;p&gt;数组创建完毕后，首先生成范围为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1,8)&lt;/code&gt;的随机数，这里假设生成的随机数为6，那么就创建一个循环6次的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for&lt;/code&gt;循环，每一次循环，都在数组NUMBERS中随机取一个数值，这样循环完毕后，就有了6个随机数；&lt;/p&gt;

&lt;p&gt;之后创建一个循环2次的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for&lt;/code&gt;循环，每次循环在数组LOWER_AND_UPPER_LETTERS中随机取一个字符，循环结束后，就有了2个随机字符。&lt;/p&gt;

&lt;p&gt;将循环后得到的两部分字符数组合并为一个字符数组，并调用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Collections.shuffle&lt;/code&gt;方法对数组进行打乱，这样就得到了至少包含一个英文字母和一个数字，且长度为8位的密码。&lt;/p&gt;

&lt;h3 id=&quot;其他格式&quot;&gt;其他格式&lt;/h3&gt;

&lt;p&gt;对于其他格式的密码生成策略，也是采用以上的思路进行生成。比如至少包含一个一个字母，一个数字和一个特殊字符，这时候密码就有三部分：&lt;/p&gt;

&lt;p&gt;假设密码长度为8。&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;第一部分，随机数范围为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1,7)&lt;/code&gt;，假设生成的值为first&lt;/li&gt;
  &lt;li&gt;第二部分，随机数范围为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1,8-first-1)&lt;/code&gt;，假设生成的值为second&lt;/li&gt;
  &lt;li&gt;第三部分，长度为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8-first-second&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;四部分的密码思路如下：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;第一部分，随机数范围为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1,6)&lt;/code&gt;，假设生成的值为first&lt;/li&gt;
  &lt;li&gt;第二部分，随机数范围为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1,8-first-2)&lt;/code&gt;，假设生成的值为second&lt;/li&gt;
  &lt;li&gt;第三部分，随机数范围为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;[1,8-first-second-1)&lt;/code&gt;，假设生成的值为third&lt;/li&gt;
  &lt;li&gt;第四部分，长度为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8-first-second-third&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;之后每一部分都循环对应的次数，每一次循环都随机取给定格式字符数组中的任一个字符，将各个部分合并后，再进行打乱，这样就得到了符合要求的密码。&lt;/p&gt;

&lt;h2 id=&quot;3实现代码&quot;&gt;3.实现代码&lt;/h2&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;com.flywinter.maplebillbackend.utils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.security.SecureRandom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.util.ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.util.Collections&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.util.List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.util.stream.Collectors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;java.util.stream.Stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/**
 * Created by IntelliJ IDEA
 * User:Zhang Xingkun
 * Date:2022/6/23 16:50
 * Description:
 */&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PasswordGenerator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SecureRandom&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RANDOM&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SecureRandom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;NUMBERS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;'0'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'1'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'2'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'3'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'4'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'5'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'6'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'7'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'8'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'9'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;LOWER_LETTERS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;'a'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'b'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'c'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'d'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'e'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'f'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'g'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'h'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'i'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'j'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'k'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'l'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'m'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'n'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'o'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'p'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'q'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'r'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'s'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'t'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'u'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'v'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'w'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'x'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'y'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'z'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UPPER_LETTERS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;'A'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'B'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'C'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'D'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'E'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'F'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'G'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'H'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'I'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'J'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'K'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'L'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'M'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'N'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'O'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'P'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'Q'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'R'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'S'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'T'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'U'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'V'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'W'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'X'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'Y'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'Z'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;LOWER_AND_UPPER_LETTERS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mergeLists&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;LOWER_LETTERS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UPPER_LETTERS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;SPECIAL_CHARACTERS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sc&quot;&gt;'!'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'&quot;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'#'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'$'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'&amp;amp;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'\''&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'('&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;')'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'*'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'+'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;','&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'-'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'.'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'/'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;':'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;';'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'&amp;lt;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'='&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'&amp;gt;'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'?'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'@'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'['&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'\\'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;']'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'^'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'_'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'`'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'{'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'|'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'}'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sc&quot;&gt;'~'&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;PasswordGenerator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * Generate a random password with the given length.
     * Format: ^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[\\!@#$%^&amp;amp;*()_+-=\[\]{};':|,.&amp;lt;&amp;gt;/?~`&quot;])[a-zA-Z0-9\\!@#$%^&amp;amp;*()_+-=\[\]{};':|,.&amp;lt;&amp;gt;/?~`&quot;]{4,}$
     *  at least 4 characters, at least one number, at least one lowercase letter, at least one uppercase letter, at least one special character.
     *  such as 2K,l  @2pL
     * @param length the length of the password
     * @return the generated password
     */&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;generatePassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;generatePassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * Generate a random password with the given length.
     * Format:
     *  useSpecial is true ^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[\\!@#$%^&amp;amp;*()_+-=\[\]{};':|,.&amp;lt;&amp;gt;/?~`&quot;])[a-zA-Z0-9\\!@#$%^&amp;amp;*()_+-=\[\]{};':|,.&amp;lt;&amp;gt;/?~`&quot;]{4,}$
     *   such as 1^Lm
     *  useSpecial is false ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[a-zA-Z\d]{4,}$
     *   such as 1kMn
     * @param length the length of the password
     * @param useSpecialCharacters whether to use special characters
     * @return the generated password
     */&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;generatePassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;useSpecialCharacters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSpecifiedTypeLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;NUMBERS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getRandomLength&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lowerLetters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSpecifiedTypeLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;LOWER_LETTERS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getRandomLength&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lettersSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lowerLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upperAndSpecial&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasSpecialLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;useSpecialCharacters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lettersSize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;UPPER_LETTERS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;passwordList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mergeLists&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lowerLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upperAndSpecial&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getRandomPassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;passwordList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * Generate a random password with the given length.
     * Format:
     *  useSpecial and isCaseSensitive are true that is generatePassword(int length)
     *  usCaseSensitive is true that is generatePassword(int length, boolean useSpecialCharacters)
     *  useCaseSensitive and useSpecialCharacters are false.
     *      It will be at least 3 characters, at least one number, at least one letter(lowercase letter or uppercase letter).
     *      ^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{3,}$
     *      such as 1Km   K2p  KH2
     *  useCaseSensitive is false and useSpecialCharacters are true.
     *      It will be at least 3 characters, at least one number, at least one letter(lowercase letter or uppercase letter), at least one special character.
     *      ^(?=.*[A-Za-z])(?=.*\d)(?=.*[\\!@#$%^&amp;amp;*()_+-=\[\]{};':|,.&amp;lt;&amp;gt;/?~`&quot;])[A-Za-z\d\\!@#$%^&amp;amp;*()_+-=\[\]{};':|,.&amp;lt;&amp;gt;/?~`&quot;]{8,}$
     *      such as 1L,  3o@
     * @param length the length of the password
     * @param useSpecialCharacters whether to use special characters
     * @param isCaseSensitive whether is case sensitive
     * @return the generated password
     */&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;generatePassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;useSpecialCharacters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isCaseSensitive&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isCaseSensitive&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;generatePassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;useSpecialCharacters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSpecifiedTypeLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;NUMBERS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getRandomLength&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;letterAndSpecial&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hasSpecialLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;useSpecialCharacters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;LOWER_AND_UPPER_LETTERS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;passwordList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mergeLists&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;letterAndSpecial&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getRandomPassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;passwordList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * Generate a random password with the given list.
     * @param numbers the list of origin password characters
     * @return the random password
     */&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getRandomPassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;Collections&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;shuffle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;Object:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Collectors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;joining&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * Generate a character list with the special characters or not.
     * @param useSpecialCharacters whether to use special characters
     * @param length the length of the password
     * @param lettersSize the size of the other letters(numbers or English letters)
     * @param englishLetters the list of English letters(lowercase or uppercase or lowercase and uppercase)
     * @return password list with special characters or not
     */&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hasSpecialLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;useSpecialCharacters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lettersSize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;englishLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;specialLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upperLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;useSpecialCharacters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upperLetterLength&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getRandomLength&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lettersSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;upperLetters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSpecifiedTypeLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;englishLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upperLetterLength&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;specialLetterLength&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lettersSize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;upperLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;specialLetters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getSpecifiedTypeLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;SPECIAL_CHARACTERS&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;specialLetterLength&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mergeLists&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;upperLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;specialLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getSpecifiedTypeLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;englishLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lettersSize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * Merge lists.
     * @param lists the lists to merge
     * @return the merged list
     */&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@SafeVarargs&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;mergeLists&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lists&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;of&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lists&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;flatMap&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;List:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;collect&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Collectors&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * Get a random length.
     * @param max the max length
     * @return the random length
     */&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getRandomLength&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;RANDOM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;nextInt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * Get specified length random list from the given list.
     * @param characterList the source list
     * @param size the size of the random list
     * @return the random list
     */&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getSpecifiedTypeLetters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;characterList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;List&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;Character&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmpList&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ArrayList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;tmpList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;characterList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;no&quot;&gt;RANDOM&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;nextInt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;characterList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())));&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tmpList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;4测试类&quot;&gt;4.测试类&lt;/h2&gt;

&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;package&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;com.flywinter.maplebillbackend.utils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.junit.jupiter.api.Test&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;org&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;junit&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;jupiter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;Assertions&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.*;&lt;/span&gt;

&lt;span class=&quot;cm&quot;&gt;/**
 * Created by IntelliJ IDEA
 * User:Zhang Xingkun
 * Date:2022/6/23 16:51
 * Description:
 */&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PasswordGeneratorTest&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;should_generate_password_with_num_lower_upper_special&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PasswordGenerator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;generatePassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;assertTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;matches&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[\\\\!@#$%^&amp;amp;*()_+-=\\[\\]{};':|,.&amp;lt;&amp;gt;/?~`\&quot;])[a-zA-Z0-9\\\\!@#$%^&amp;amp;*()_+-=\\[\\]{};':|,.&amp;lt;&amp;gt;/?~`\&quot;]{8,}$&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;should_throw_error_when_password_length_smaller_than_3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;assertThrows&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;IllegalArgumentException&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PasswordGenerator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;generatePassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;should_generate_password_with_num_lower_upper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PasswordGenerator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;generatePassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;assertTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;matches&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)[a-zA-Z\\d]{8,}$&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;should_generate_password_with_num_lower_or_upper_special&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PasswordGenerator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;generatePassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;assertTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;matches&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;^(?=.*[A-Za-z])(?=.*\\d)(?=.*[\\\\!@#$%^&amp;amp;*()_+-=\\[\\]{};':|,.&amp;lt;&amp;gt;/?~`\&quot;])[A-Za-z\\d\\\\!@#$%^&amp;amp;*()_+-=\\[\\]{};':|,.&amp;lt;&amp;gt;/?~`\&quot;]{8,}$&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;should_generate_password_with_num_lower_or_upper&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PasswordGenerator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;generatePassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;assertTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;matches&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;should_generate_password_with_num_lower_or_upper_16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PasswordGenerator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;generatePassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;assertTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;matches&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{16}$&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;


    &lt;span class=&quot;nd&quot;&gt;@Test&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;should_generate_password_with_num_lower_upper_special_12_and_encode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PasswordGenerator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;generatePassword&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;assertTrue&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;matches&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[\\\\!@#$%^&amp;amp;*()_+-=\\[\\]{};':|,.&amp;lt;&amp;gt;/?~`\&quot;])[a-zA-Z0-9\\\\!@#$%^&amp;amp;*()_+-=\\[\\]{};':|,.&amp;lt;&amp;gt;/?~`\&quot;]{12,}$&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bCryptPasswordEncoder&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BCryptPasswordEncoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;final&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bCryptPasswordEncoder&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;password: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;encode: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//        password: P42F1_6r$2$711&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//        encode: $2a$10$we1KwoVzwkchAMfvRJ2NdurNk3.KzcnDcrEfrD17uT3itfnEaNVdG&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;5备注&quot;&gt;5.备注&lt;/h2&gt;

&lt;h3 id=&quot;随机数&quot;&gt;随机数&lt;/h3&gt;

&lt;p&gt;关于随机数，实际上Java内部实现的随机数大部分是伪随机数，即可以被预测，如果随机数的种子相同，生成的随机数就是一样的。&lt;/p&gt;

&lt;p&gt;对于&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Random&lt;/code&gt;类，默认使用时间作为种子，所以比较容易被预测。&lt;/p&gt;

&lt;p&gt;而&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SecureRandom&lt;/code&gt;类无法指定种子，而是使用RNG算法来实现的，在底层实现中，有的底层实现使用的是真正的随机数（即根据电脑CPU本身的噪音等生成，基本可以认为是真随机数），所以不容易甚至无法预测。&lt;/p&gt;

&lt;p&gt;其实这里使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Random&lt;/code&gt;类也是可以的，因为默认生成的密码只要长度够长，又使用时间作为种子，基本上也是无法预测的。&lt;/p&gt;</content><author><name>Xingkun Zhang</name></author><category term="java" /><category term="java" /><category term="password" /><category term="regex" /><summary type="html">在开发过程中，我们常常需要设置一些初始化账户来供用户操作使用。这时候就需要为账户设置密码，为了让密码尽量随机，可以采用程序随机生成的方式，生成满足一定要求的密码。</summary></entry><entry><title type="html">设计模式与设计原则概述</title><link href="/design/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B8%8E%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99%E6%A6%82%E8%BF%B0" rel="alternate" type="text/html" title="设计模式与设计原则概述" /><published>2022-06-06T00:00:00+00:00</published><updated>2022-06-06T00:00:00+00:00</updated><id>/design/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B8%8E%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99%E6%A6%82%E8%BF%B0</id><content type="html" xml:base="/design/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%B8%8E%E8%AE%BE%E8%AE%A1%E5%8E%9F%E5%88%99%E6%A6%82%E8%BF%B0">&lt;p&gt;因为我们的代码并不是一成不变的，总会随着需求而不断发生变化，如果我们没有遵循一定的设计模式，那么代码迁移的成本可能就会非常高，所以我们需要设计模式来指导我们编写代码，进而增加代码的扩展性。设计原则则是23种设计模式的抽象概述，设计模式是设计原则的具体实现。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;1-设计原则&quot;&gt;1. 设计原则&lt;/h2&gt;

&lt;h3 id=&quot;分类&quot;&gt;分类&lt;/h3&gt;

&lt;p&gt;设计原则一共有六种，分别为&lt;/p&gt;

&lt;h4 id=&quot;单一职责原则s&quot;&gt;单一职责原则（S）&lt;/h4&gt;

&lt;p&gt;单一职责原则，即SRP（Single Responsibility Principle）。&lt;/p&gt;

&lt;p&gt;定义为：应该有且仅有一个原因引起类的变更（There should never be more than one reason for a class to change.）。&lt;/p&gt;

&lt;h4 id=&quot;开闭原则o&quot;&gt;开闭原则（O）&lt;/h4&gt;

&lt;p&gt;开闭原则，即OCP（Open Closed Principle）。&lt;/p&gt;

&lt;p&gt;定义为：一个软件实体，如类、模块和函数应该对扩展开发，对修改关闭（Softwate entities like classes,modules and functions should be open for extension but closed for modifications.）。&lt;/p&gt;

&lt;h4 id=&quot;里氏替换原则l&quot;&gt;里氏替换原则（L）&lt;/h4&gt;

&lt;p&gt;里氏替换原则，即LSP（Liskov Substitution Principle）。&lt;/p&gt;

&lt;p&gt;定义为：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;如果对每一个类型为S的对象o1，都有类型为T的对象o2，使得以T定义的所有程序P在所有的对象o1都代换成o2时，程序P的行为没有发生变化，那么类型S是类型T的子类型（If  for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T,the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.）。&lt;/li&gt;
  &lt;li&gt;所有引用基类的地方必须能透明地使用其子类的对象（Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.）。&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;迪米特法则l&quot;&gt;迪米特法则（L）&lt;/h4&gt;

&lt;p&gt;迪米特法则，即LoD（Law of Demeter）&lt;/p&gt;

&lt;p&gt;又叫最少知识原则，即LKP（Least Knowledge Principle）。&lt;/p&gt;

&lt;p&gt;定义为：一个对象应该对其他对象有最少的了解&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;只和朋友交流，不和陌生类交流&lt;/li&gt;
  &lt;li&gt;朋友之间也是有距离的，尽量减少public方法&lt;/li&gt;
  &lt;li&gt;是自己的就是自己的，如果一个方法放在本类中，既不增加类间关系，也对本类不产生负面影响，那就放在本类中&lt;/li&gt;
  &lt;li&gt;谨慎使用Serializable&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;接口隔离原则i&quot;&gt;接口隔离原则（I）&lt;/h4&gt;

&lt;p&gt;接口隔离原则，即ISP（Interface Segregation Principle）&lt;/p&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;细节应该依赖抽象。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;High level modules should not depend upon low level modules. Both should depend upon abstractions. Abstractions should not depend upon details. Details should depend upon abstractions.&lt;/p&gt;

&lt;h4 id=&quot;依赖倒置原则d&quot;&gt;依赖倒置原则（D）&lt;/h4&gt;

&lt;p&gt;依赖倒置原则，即DIP（Dependence Inversion Principle）&lt;/p&gt;

&lt;p&gt;定义为&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;客户端不应该依赖它不需要的接口（Clients should not be forced to depend upon interfaces that they don’t use.）。&lt;/li&gt;
  &lt;li&gt;类间的依赖关系应该建立在最小的接口上（The dependency of one class to another one should depend on the smallest possible interface.）。&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;总结&quot;&gt;总结&lt;/h3&gt;

&lt;p&gt;以上六大设计原则，取其缩写的首字母（重复的去掉），联合起来就是SOLID，含义就是建立稳定、灵活，健壮的设计，其中开闭原则是以上六种设计原则中最重要的一个原则，也是最基础的原则，其他几种原则或多或少都有开闭原则的影子。&lt;/p&gt;

&lt;h2 id=&quot;2-设计模式&quot;&gt;2. 设计模式&lt;/h2&gt;

&lt;p&gt;设计模式共有23中，总共可以分为三大类，此外还有其他两种模式&lt;/p&gt;

&lt;h3 id=&quot;分类-1&quot;&gt;分类&lt;/h3&gt;

&lt;h4 id=&quot;创建型模式&quot;&gt;创建型模式&lt;/h4&gt;

&lt;p&gt;共5种：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;单例模式&lt;/p&gt;

    &lt;p&gt;确保某一个类只有一个实例，而且自行实例化并向整个系统提供这个实例。(Ensure a class only one instance, and provide a global point of access to it.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;工厂方法模式&lt;/p&gt;

    &lt;p&gt;定义一个用于创建对象的接口，让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到子类。（Define an interface for creating an object, but let subclasses decide which class instantiate Factory Method lets a class defer instantiation to subclasses.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;抽象工厂模式&lt;/p&gt;

    &lt;p&gt;为创建一组相关或相互依赖的对象提供一个接口，而且无需指定它们的具体类。（Provide an interface for creating families of related or dependent objects without specifying their concrete classes.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;建造者模式&lt;/p&gt;

    &lt;p&gt;将一个复杂对象的构建与它的表示分离，使得同样的构建过程可以创建不同的表示。（Separate the construction of a complex object from its representation so that the same construction process can create different representations.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;原型模式&lt;/p&gt;

    &lt;p&gt;用原型实例指定创建对象的种类，并且通过拷贝这些原型对象创建新的对象。（Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.）&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;结构型模式&quot;&gt;结构型模式&lt;/h4&gt;

&lt;p&gt;共7种：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;适配器模式&lt;/p&gt;

    &lt;p&gt;将一个类的接口变换成客户端所期待的另一种接口，从而使原本因接口不匹配而无法在一起工作的两个类能够在一起工作。（Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn’t otherwise because of incompatible interfaces.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;装饰器模式&lt;/p&gt;

    &lt;p&gt;动态地给一个对象添加一些额外的职责。就增加功能来说，装饰模式相比生成子类更加灵活。（Attach additional responsibilities to an object dynamically keeping the same interface. Decorators provide a flexible alternative to subclassing for extending functionality.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;代理模式&lt;/p&gt;

    &lt;p&gt;为其他对象提供一种代理以控制对这个对象的访问。（Provide a surrogate or placeholder for another object to control access to it.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;外观模式&lt;/p&gt;

    &lt;p&gt;要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。门面模式提供一个高层次的接口，使得子系统更易于使用。（Provide a unified interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;桥接模式&lt;/p&gt;

    &lt;p&gt;将抽象和实现解耦，使得两者可以独立地变化。（Decouple an abstraction from its implementation so that the two can vary independently.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;组合模式&lt;/p&gt;

    &lt;p&gt;将对象组合成树形结构以表示“部分-整体”的层次结构，使得用户对单个对象和组合对象的使用具有一致性。（Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compositions of objects uniformly.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;享元模式&lt;/p&gt;

    &lt;p&gt;使用共享对象可有效地支持大量的细粒度的对象。（Use sharing to support large numbers of fine-grained objects efficiently.）&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;行为型模式&quot;&gt;行为型模式&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;策略模式&lt;/p&gt;

    &lt;p&gt;定义一组算法，将每个算法都封装起来，并且使它们之间可以互换。（Define a family of algorithms, encapsulate each one, and make them interchangeable.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;模板方法模式&lt;/p&gt;

    &lt;p&gt;定义一个操作中的算法的框架，而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。（Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm’s structure.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;观察者模式&lt;/p&gt;

    &lt;p&gt;定义对象间一种一对多的依赖关系，使得每当一个对象改变状态，则所有依赖于它的对象都会得到通知并被自动更新。（Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and updated automatically.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;迭代器模式&lt;/p&gt;

    &lt;p&gt;它提供一种方法访问一个容器对象中的各个元素，而又不需暴露该对象的内部细节。（Provide a way to access the elements of an aggregate object sequentially without exposing its underlying representation.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;责任链模式&lt;/p&gt;

    &lt;p&gt;使多个对象都有机会处理请求，从而避免了请求的发送者和接受者之间的耦合关系。将这些对象连成一条链，并沿着这条链传递该请求，直到有对象处理它为止。（Avoid coupling the sender of a request to its receiver by giving more than one object a chance to handle the request. Chain the receiving objects and pass the request along the chain until an object handles it.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;命令模式&lt;/p&gt;

    &lt;p&gt;将一个请求封装成一个对象，从而让你使用不同的请求把客户端参数化，对请求排队或者记录请求日志，可以提供命令的撤销和恢复功能。（Encapsulate a request as an object, thereby letting you parameterize clients with different requests, queue or log requests, and support undoable operations.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;备忘录模式&lt;/p&gt;

    &lt;p&gt;在不破坏封装性的前提下，捕获一个对象的内部状态，并在该对象之外保存这个状态。这样以后就可以将该对象恢复到原先保存的状态。（Without violating encapsulation, capture and externalize an object’s internal state so that the object can be restored to this state later.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;状态模式&lt;/p&gt;

    &lt;p&gt;当一个对象内在状态改变时允许其改变行为，这个对象看起来像改变了其类。（Allow an object to alter its behavior when its internal state changes. The object will appear to change its class.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;访问者模式&lt;/p&gt;

    &lt;p&gt;封装一些作用于某种数据结构中的各元素的操作，它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。（Represent an operation to be performed on the elements of an object structure. Visitor lets you define a new operation without changing the classes of the elements on which it operates.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;中介者模式&lt;/p&gt;

    &lt;p&gt;用一个中介对象封装一系列的对象交互，中介者使各对象不需要显示地相互作用，从而使其耦合松散，而且可以独立地改变它们之间的交互。（Define an object that encapsulates how a set of objects interact. Mediator promotes loose coupling by keeping objects from referring to each other explicitly, and it lets you vary their interaction independently.）&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;解释器模式&lt;/p&gt;

    &lt;p&gt;给定一门语言，定义它的文法的一种表示，并定义一个解释器，该解释器使用该表示来解释语言中的句子。（Given a language, define a representation for its grammar along with an interpreter that uses the representation to interpret sentences in the language.）&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;补充：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;并发型模式&lt;/p&gt;

    &lt;p&gt;处理多线程范式&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;线程池模式&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;</content><author><name>Xingkun Zhang</name></author><category term="design" /><category term="design" /><category term="pattern" /><category term="principle" /><summary type="html">因为我们的代码并不是一成不变的，总会随着需求而不断发生变化，如果我们没有遵循一定的设计模式，那么代码迁移的成本可能就会非常高，所以我们需要设计模式来指导我们编写代码，进而增加代码的扩展性。设计原则则是23种设计模式的抽象概述，设计模式是设计原则的具体实现。</summary></entry><entry><title type="html">rebase在git中的使用</title><link href="/git/rebase%E5%9C%A8git%E4%B8%AD%E7%9A%84%E4%BD%BF%E7%94%A8" rel="alternate" type="text/html" title="rebase在git中的使用" /><published>2022-05-29T00:00:00+00:00</published><updated>2022-05-29T00:00:00+00:00</updated><id>/git/rebase%E5%9C%A8git%E4%B8%AD%E7%9A%84%E4%BD%BF%E7%94%A8</id><content type="html" xml:base="/git/rebase%E5%9C%A8git%E4%B8%AD%E7%9A%84%E4%BD%BF%E7%94%A8">&lt;p&gt;rebase命令是git中非常常见的一个命令，只要我们需要多人或者多设备协作，如果我们想让我们的分支看起来更加更见干净，那么就离不开rebase这个命令，下面介绍了如何在命令行和IDEA中使用rebase命令&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;1为什么需要rebase&quot;&gt;1.为什么需要rebase&lt;/h2&gt;

&lt;p&gt;在进行多人协作开发时，虽然通常情况下，都是每个人负责一个功能。这样每个人都负责自己的代码块，不会去修改其他人的代码，那么代码就不会冲突。&lt;/p&gt;

&lt;p&gt;但是实际上，总会出现多个人编写或修改同一行代码的情形。&lt;/p&gt;

&lt;p&gt;对于文件A，两个员工同时从远端拉取代码，这样两个人的代码都是最新的，这时员工一在文件A第三行添加了一行代码，然后&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commit&lt;/code&gt;并&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;push&lt;/code&gt;到了远程代码仓库；员工二也在文件A第三行添加了一行代码，并&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commit&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;这时如果员工二执行推送也就是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;push&lt;/code&gt;命令，是会被远程仓库拒绝的，因为它不知道应该采用哪个人的版本，这时候就需要执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pull&lt;/code&gt;命令，先更新代码库，这时就会在本地新建一个临时分支，同时冲突的代码块也会用类似于下面的格式标明&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD
I think 1 better. //自己在本地编写commit但是没有push的代码
=======
I think code is better. // 其他人已经commit并且push的代码
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; 2449b6fb8fba4c703514b3da0174aca8c53e4177
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这时候我们就需要修改这个部分，将其改写成我们需要的东西，比如改写成下面的形式&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;I think code space is better.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;然后执行&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git add &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git commit &lt;span class=&quot;nt&quot;&gt;-m&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;feat: changed&quot;&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git merge main &lt;span class=&quot;c&quot;&gt;# 将修改后的代码合并回主分支&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git push
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这样我们就把最终的结果推送到了远程代码仓库。&lt;/p&gt;

&lt;p&gt;但是这样我们的提交历史记录就会非常ugly，比如像下面这个样子&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../assets/images/resource/2022-05-29-rebase在git中的使用.assets/image-20220529172222018.png&quot; alt=&quot;image-20220529172222018&quot; /&gt;&lt;/p&gt;

&lt;p&gt;对于这种情况，我们其实没有必要新建临时分支。遇到这种情况时，如果我们想要一个比较干净的提交历史，比如下面这样子&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;../assets/images/resource/2022-05-29-rebase在git中的使用.assets/image-20220529172502516.png&quot; alt=&quot;image-20220529172502516&quot; /&gt;&lt;/p&gt;

&lt;p&gt;就可以使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rebase&lt;/code&gt;命令。&lt;/p&gt;

&lt;h2 id=&quot;2-使用rebase&quot;&gt;2. 使用rebase&lt;/h2&gt;

&lt;h3 id=&quot;a-命令行用法&quot;&gt;a 命令行用法&lt;/h3&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;在执行&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;push&lt;/code&gt;命令之前，首先执行&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git pull &lt;span class=&quot;nt&quot;&gt;--rebase&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;这时本地就会显示冲突代码&lt;/p&gt;

    &lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD
I think 1 better. //自己在本地编写commit但是没有push的代码
=======
I think code is better. // 其他人已经commit并且push的代码
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; 2449b6fb8fba4c703514b3da0174aca8c53e4177
&lt;/code&gt;&lt;/pre&gt;

    &lt;p&gt;修改成自己需要的样子，如&lt;/p&gt;

    &lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;I think code space is better.
&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;然后执行&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git add &lt;span class=&quot;nb&quot;&gt;.&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git rebase &lt;span class=&quot;nt&quot;&gt;--continue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;这时会进入一个vim操作界面，提醒你修改commit的相关信息，按&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;i&lt;/code&gt;进入编辑模式，修改完毕后按&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Esc&lt;/code&gt;退出，然后输入&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;:wq&lt;/code&gt;保存并退出编辑。(如果你只是保留了其中一个版本，而不是对两者进行整合，那么不会弹出vim操作界面)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;这时就已经修改完冲突的代码了，然后执行&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git push
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p&gt;将本地代码提交到远程仓库&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;如果想要放弃这次的rebase，那么只需要在第三步之前执行&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git rebase &lt;span class=&quot;nt&quot;&gt;--abort&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;命令即可放弃本次rebase。&lt;/p&gt;

&lt;h3 id=&quot;b-在idea中使用&quot;&gt;b 在IDEA中使用&lt;/h3&gt;

&lt;p&gt;原理是一样的，只是IDEA的图形化界面可以让我们的操作更直观&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;点击update project&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;../assets/images/resource/2022-05-29-rebase在git中的使用.assets/image-20220529175153138.png&quot; alt=&quot;image-20220529175153138&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;在弹出的窗口中选择rebase&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;../assets/images/resource/2022-05-29-rebase在git中的使用.assets/image-20220529175235189.png&quot; alt=&quot;image-20220529175235189&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;点击OK后，在弹出的窗口中选择Merge&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;../assets/images/resource/2022-05-29-rebase在git中的使用.assets/image-20220529175358324.png&quot; alt=&quot;image-20220529175358324&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;注意这里有三个选项，其实很容易理解，Accept Yours就是保留自己的，Accept Theirs就是保留对方的，Merge就是我们需要自己决定冲突的部分最后是什么样子&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;之后会弹出窗口提示修改&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;../assets/images/resource/2022-05-29-rebase在git中的使用.assets/image-20220529175637533.png&quot; alt=&quot;image-20220529175637533&quot; /&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;修改后的样子，点击Apply即可保存修改&lt;/p&gt;

    &lt;p&gt;&lt;img src=&quot;../assets/images/resource/2022-05-29-rebase在git中的使用.assets/image-20220529175730053.png&quot; alt=&quot;image-20220529175730053&quot; /&gt;&lt;/p&gt;

    &lt;p&gt;注意不能有标红的部分，因为标红的部分代表冲突，而我们之所以这样做就是为了解决冲突&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;然后推送&lt;/p&gt;

    &lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;git push
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;这样一个简单的使用IDEA进行rebase的过程就完成了&lt;/p&gt;

&lt;h2 id=&quot;3-总结&quot;&gt;3. 总结&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;rebase可以帮助我们整洁我们的提交历史，防止添加无意义的临时分支。&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;merge&lt;/code&gt;命令更适用于开发新功能，比如给计算器添加求和功能，这时候我们就可以新建一个分支，开发完后再合并到主分支。或者新建dev等分支，等dev分支一个阶段完毕后，合并到主分支&lt;/li&gt;
&lt;/ol&gt;</content><author><name>Xingkun Zhang</name></author><category term="git" /><category term="git" /><category term="rebase" /><category term="idea" /><summary type="html">rebase命令是git中非常常见的一个命令，只要我们需要多人或者多设备协作，如果我们想让我们的分支看起来更加更见干净，那么就离不开rebase这个命令，下面介绍了如何在命令行和IDEA中使用rebase命令</summary></entry><entry><title type="html">JS实现图片懒加载</title><link href="/js/JS%E5%AE%9E%E7%8E%B0%E5%9B%BE%E7%89%87%E6%87%92%E5%8A%A0%E8%BD%BD" rel="alternate" type="text/html" title="JS实现图片懒加载" /><published>2022-05-15T00:00:00+00:00</published><updated>2022-05-15T00:00:00+00:00</updated><id>/js/JS%E5%AE%9E%E7%8E%B0%E5%9B%BE%E7%89%87%E6%87%92%E5%8A%A0%E8%BD%BD</id><content type="html" xml:base="/js/JS%E5%AE%9E%E7%8E%B0%E5%9B%BE%E7%89%87%E6%87%92%E5%8A%A0%E8%BD%BD">&lt;p&gt;图片懒加载是前端开发过程中非常常见的一个功能。图片懒加载本质上是通过检测可见区域来判断是否发送网络请求，从而优化网页加载速度，本文将实现图片懒加载功能。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;1-效果预览&quot;&gt;1. 效果预览&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;../assets/images/resource/2022-05-15-JS实现图片懒加载.assets/20220515_005437.gif&quot; alt=&quot;20220515_005437&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;2-实现思路&quot;&gt;2. 实现思路&lt;/h2&gt;

&lt;p&gt;对于图片懒加载，实际的实现思路实际上就是当图片处于或即将处于可视窗口中时，网页发送网络请求，从而加载图片。&lt;/p&gt;

&lt;p&gt;之所以不一开始就加载图片，是因为大量图片同一时间加载，会造成浏览器页面的卡顿，所以才有了懒加载的需求。&lt;/p&gt;

&lt;p&gt;所以懒加载的核心就是&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;windowHeight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;innerHeight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scrollTop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;documentElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scrollTop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scrollTop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;offsetTop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;offsetTop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;windowHeight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scrollTop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;offsetTop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;即窗口高度&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt;滚动高度&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;gt;&lt;/code&gt;图片距离顶部的高度&lt;/p&gt;

&lt;p&gt;但实际使用过程中，为了让用户有更好的体验，上面的逻辑通常是下面这个样子&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;windowHeight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scrollTop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;offsetTop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这里可以是256，也可以是更大或更小的数值，同样也是实现懒加载，但是由于多加了一点距离，这样就保证了大多数时候，用户总能及时看到图片，而不是看到占位的背景切换成图片。&lt;/p&gt;

&lt;h2 id=&quot;3-实现代码&quot;&gt;3. 实现代码&lt;/h2&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lang=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;en&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;charset=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;UTF-8&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Title&lt;span class=&quot;nt&quot;&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;style&amp;gt;&lt;/span&gt;

        &lt;span class=&quot;nc&quot;&gt;.container&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;max-content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;400px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;c&quot;&gt;/*=========要加载的图片添加lazy class===========*/&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;/*根据自己需要，修改图片加载前的颜色，或者用展位图代替*/&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;.lazy&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;py&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;antiquewhite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;overflow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;hidden&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;c&quot;&gt;/*设置lazy内部图片的style，根据自己需要调整，这里是填充显示中间部分*/&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;/*悬浮时将会缩放图片*/&lt;/span&gt;
        &lt;span class=&quot;nc&quot;&gt;.lazy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;100%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;object-fit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cover&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;c&quot;&gt;/*property duration timing-function delay*/&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;transition&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;all&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0.2s&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ease-in&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

        &lt;span class=&quot;nc&quot;&gt;.lazy&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;:hover&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nl&quot;&gt;transform&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;scale&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;1.2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;c&quot;&gt;/*=============================*/&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;H1&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&amp;gt;&lt;/span&gt;H1&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&amp;gt;&lt;/span&gt;H1&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;lazy&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://www.flywinter.com/assets/images/cover/2022-05-10-Veiled.png&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;lazy&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://www.flywinter.com/assets/images/cover/2022-05-10-Veiled.png&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;lazy&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://www.flywinter.com/assets/images/cover/2022-05-10-Veiled.png&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;lazy&quot;&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;data-src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://www.flywinter.com/assets/images/cover/2022-05-10-%E9%9B%AA%E8%A7%A3%E3%81%91.png&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;lazy&quot;&lt;/span&gt;
         &lt;span class=&quot;na&quot;&gt;data-src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://www.flywinter.com/assets/images/cover/2022-05-10-%E9%9B%AA%E8%A7%A3%E3%81%91.png&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;lazy&quot;&lt;/span&gt; 
         &lt;span class=&quot;na&quot;&gt;data-src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://www.flywinter.com/assets/images/cover/2022-05-10-%E9%9B%AA%E8%A7%A3%E3%81%91.png&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;

&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;lazy&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://www.flywinter.com/assets/images/cover/2022-05-09-mikasa-sakura.png&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;lazy&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://www.flywinter.com/assets/images/cover/2022-05-09-mikasa-sakura.png&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;container&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;div&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;class=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;lazy&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;data-src=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;https://www.flywinter.com/assets/images/cover/2022-05-09-mikasa-sakura.png&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;H2&lt;span class=&quot;nt&quot;&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span class=&quot;na&quot;&gt;type=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;text/javascript&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;cm&quot;&gt;/**
     * 另一种实现思路，使用时，先新建被div包裹的img标签，
     * 这样就不需要重新创建元素，直接给lazy里面的img标签赋值即可
     * 但是缺点就是一定几率用户会看到加载失败的图片样式，影响体验
     * 可以通过背景图片，增大判断距离来解决
     *
     * 下面的实现思路是为每个添加了lazy的元素添加标签，
     * 只要处于可视范围，就新建img元素，并且为lazy元素设置属性，
     * 只要设置了属性为true，代表已经创建了元素，即已经加载，
     * 就不需要重新加载了
     */&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lazyLoad&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;imgContainers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//窗口高度&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;windowHeight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;innerHeight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//滚动条滚动距离&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scrollTop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;documentElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scrollTop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;scrollTop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgContainers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgContainer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgContainers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;offsetTop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;offsetTop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;loaded&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;data-loaded&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;//滚动+窗口的高度&amp;gt;图片元素到顶部的距离&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;//多加256的高度，让图片接近的时候就开始加载&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;//这时图片在窗口&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;----&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;windowHeight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scrollTop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;----&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;// &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;-----------&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;offsetTop&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;------------&amp;gt;&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;imageContainer&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;//如果图片显示了，并且没有加载过，就加载图片，防止重复创建img&lt;/span&gt;
            &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;isShow&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;windowHeight&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;scrollTop&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;offsetTop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;isShow&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;loaded&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;img&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createElement&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgSrc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;data-src&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;nx&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;src&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgSrc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;nx&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;alt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgSrc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
                &lt;span class=&quot;nx&quot;&gt;imgContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;img&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;nx&quot;&gt;imgContainer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;data-loaded&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;//HTML元素都加载完毕了再添加事件&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgContainers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelectorAll&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;.lazy&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgContainers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;imgContainers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setAttribute&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;data-loaded&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//有时即使元素都加载完毕了，网页还是空白，所以延迟&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//但是这里延迟可以去掉，只保留lazyLoad()，&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// 因为实际的要求往往是只要请求网页就马上加载可视的图片，加了延迟反而显得有些卡&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;setTimeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;lazyLoad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;imgContainers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;//只要滚动，就检测是不是需要请求图片&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;scroll&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;nx&quot;&gt;lazyLoad&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;imgContainers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;4-使用方法&quot;&gt;4. 使用方法&lt;/h2&gt;

&lt;p&gt;将js代码以及&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.lazy&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.lazy &amp;gt; img&lt;/code&gt;这两个class拷贝到项目中，原来需要用到img标签的地方，替换为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;div class=&quot;lazy&quot; data-src=&quot;imagePath&quot;&amp;gt;&lt;/code&gt;，这样就可以实现图片懒加载&lt;/p&gt;</content><author><name>Xingkun Zhang</name></author><category term="js" /><category term="js" /><category term="img" /><category term="lazy" /><summary type="html">图片懒加载是前端开发过程中非常常见的一个功能。图片懒加载本质上是通过检测可见区域来判断是否发送网络请求，从而优化网页加载速度，本文将实现图片懒加载功能。</summary></entry><entry><title type="html">JS中将二进制流转换为Base64</title><link href="/js/JS%E4%B8%AD%E5%B0%86%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%B5%81%E8%BD%AC%E6%8D%A2%E4%B8%BABase64" rel="alternate" type="text/html" title="JS中将二进制流转换为Base64" /><published>2022-05-10T00:00:00+00:00</published><updated>2022-05-10T00:00:00+00:00</updated><id>/js/JS%E4%B8%AD%E5%B0%86%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%B5%81%E8%BD%AC%E6%8D%A2%E4%B8%BABase64</id><content type="html" xml:base="/js/JS%E4%B8%AD%E5%B0%86%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%B5%81%E8%BD%AC%E6%8D%A2%E4%B8%BABase64">&lt;p&gt;在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Web&lt;/code&gt;开发过程中，有时候我们需要将一些用二进制流表示的图片，转化为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Base64&lt;/code&gt;格式，让图片可以在&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;img&lt;/code&gt;标签中显示，下面将展示如何使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;js&lt;/code&gt;编码将图片转换为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Base64&lt;/code&gt;格式。&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;1-binary-to-base64&quot;&gt;1. Binary To Base64&lt;/h2&gt;

&lt;p&gt;其实只需要一行代码就可以实现&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// arrayBuffer为接收到的二进制数据&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgBase64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;data:image/png;base64,&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;btoa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fromCharCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(...&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Uint8Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arrayBuffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;但是，如果图片比较大(图片大于一百多k的时候)，使用这种方法进行转换时，会抛出错误&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Uncaught RangeError: Maximum call stack size exceeded&lt;/code&gt;，这是因为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;String.fromCharCode&lt;/code&gt;方法无法一次处理这么大的数据，可以替换为下面的代码&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// blob为接收到的二进制数据&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgBase64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;btoa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Uint8Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arrayBuffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fromCharCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;使用reduce来依次进行拼接&lt;/p&gt;

&lt;h2 id=&quot;2-data-urls&quot;&gt;2. Data URLs&lt;/h2&gt;

&lt;p&gt;在上面中解决方法中，类似&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data:image/png;base64,&lt;/code&gt;这样的前缀，作为开发人员，我们经常会看到，但是我们可能从来都没有考虑过它的含义。&lt;/p&gt;

&lt;p&gt;实际上，&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data URLs&lt;/strong&gt;，即前缀为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data:&lt;/code&gt; 协议的URL，其允许内容创建者向文档中嵌入小文件。&lt;/p&gt;

&lt;p&gt;这里的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data:&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt;、&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;https:&lt;/code&gt;等类似，格式如下&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;data:[&amp;lt;mediatype&amp;gt;][;base64],&amp;lt;data&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;其中&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mediatype&lt;/code&gt;与&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;;base64&lt;/code&gt;都是可选的，这里不要忘记&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;,&lt;/code&gt;，否则无法解析。&lt;/p&gt;

&lt;p&gt;常见的示例如下所示&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;data:,文本数据
data:text/plain,文本数据
data:text/css,CSS代码
data:text/css;base64,base64编码的CSS代码
data:text/javascript,Javascript代码
data:text/javascript;base64,base64编码的Javascript代码
data:image/gif;base64,base64编码的gif图片数据
data:image/png;base64,base64编码的png图片数据
data:image/jpeg;base64,base64编码的jpeg图片数据
data:image/x-icon;base64,base64编码的icon图片数据
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;上面的示例，在编码正确的情况下，都可以输入浏览器地址栏获取结果，注意中文会出现乱码&lt;/p&gt;

&lt;h2 id=&quot;3-btoa--atob&quot;&gt;3. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;btoa&lt;/code&gt; &amp;amp; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;atob&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IE10+&lt;/code&gt;的浏览器开始，所有浏览器都原生提供了&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base64&lt;/code&gt;的解码和编码方法，即&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;window.atob()&lt;/code&gt;和&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;window.btoa()&lt;/code&gt;。&lt;/p&gt;

&lt;p&gt;与&lt;a href=&quot;https://www.npmjs.com/package/js-base64&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Base64&lt;/code&gt;&lt;/a&gt;库的功能类似，但是原生的&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base64&lt;/code&gt;解码和编码方法在旧版本的浏览器中存在兼容性问题，所以为了解决兼容性问题，在旧版本的浏览器中，依旧需要使用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Base64&lt;/code&gt;库，或者自己实现。&lt;/p&gt;

&lt;h2 id=&quot;4-arraybuffer&quot;&gt;4. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArrayBuffer&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;首先看一个使用场景&lt;/p&gt;

&lt;div class=&quot;language-js highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;//sourceUrl 可以是本地服务器文件，也可以是远程服务器文件&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//eg &lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//服务器根目录有mm.jpg文件，那么sourceUrl=mm.jpg，实际请求时请求的路径为http://localhost:port/mm.jpg&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//fetch&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;sourceUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;GET&lt;/span&gt;&lt;span class=&quot;dl&quot;&gt;'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;responseData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;arrayBuffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;imgBase64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;btoa&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Uint8Array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;responseData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reduce&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fromCharCode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;dl&quot;&gt;''&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArrayBuffer&lt;/code&gt;是无法直接被使用的，需要通过&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypedArray&lt;/code&gt;或&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DataView&lt;/code&gt;对象进行操作，它们会将缓冲区中的数据表示为特定的格式，进而通过这些特定的格式来读写缓冲区的内容。&lt;/p&gt;

&lt;p&gt;这里之所以要用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Uint8Array&lt;/code&gt;作为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypedArray&lt;/code&gt;而不是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Uint16&lt;/code&gt;等，是因为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;window.btoa&lt;/code&gt;创建的是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ASCII&lt;/code&gt;字符串，而&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ASCII&lt;/code&gt;的范围就是&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0~255&lt;/code&gt;，所以用&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Uint8&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;5-转换过程&quot;&gt;5. 转换过程&lt;/h2&gt;

&lt;ol&gt;
  &lt;li&gt;获取&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ArrayBuffer&lt;/code&gt;对象&lt;/li&gt;
  &lt;li&gt;转换为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Uint8Array&lt;/code&gt;对象&lt;/li&gt;
  &lt;li&gt;转换为普通字符串&lt;/li&gt;
  &lt;li&gt;转换为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;base64&lt;/code&gt;编码的字符串&lt;/li&gt;
  &lt;li&gt;拼接为&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Data URL&lt;/code&gt;格式&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;参考资料&quot;&gt;参考资料&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/49123222/converting-array-buffer-to-string-maximum-call-stack-size-exceeded&quot;&gt;Maximum call stack size exceeded&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/zh-CN/docs/web/http/basics_of_http/data_uris&quot;&gt;Data URLs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/fromCharCode&quot;&gt;fromCharCode&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/&quot;&gt;MDN&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Xingkun Zhang</name></author><category term="js" /><category term="js" /><category term="binary" /><category term="base64" /><summary type="html">在Web开发过程中，有时候我们需要将一些用二进制流表示的图片，转化为Base64格式，让图片可以在img标签中显示，下面将展示如何使用js编码将图片转换为Base64格式。</summary></entry></feed>