-
Notifications
You must be signed in to change notification settings - Fork 1
/
feed.xml
2529 lines (2404 loc) · 260 KB
/
feed.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns="http://www.w3.org/2005/Atom"><id>https://github.com/QiYongchuan/MyGitBlog</id><title>RSS feed of QiYongchuan's MyGitBlog</title><updated>2024-12-22T15:49:28.039488+00:00</updated><link href="https://github.com/QiYongchuan/MyGitBlog"/><link href="https://raw.githubusercontent.com/QiYongchuan/MyGitBlog/master/feed.xml" rel="self"/><generator uri="https://lkiesow.github.io/python-feedgen" version="1.0.0">python-feedgen</generator><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/110</id><title>从985研究生退学重回二本读计算机的这几年--2024年终总结</title><updated>2024-12-22T15:49:28.524688+00:00</updated><content type="html"><![CDATA[<p>终于要提笔写点什么了,这是一篇酝酿好久的文字,我过去想了好久,但迟迟无法动笔。</p>
<p>一方面,完美主义是造成拖延的最大的原因,我担心自己写不好,担心自己写不出我心中所想的,过去经历的这一切;另一方面,或许是因为过去这几年经历了太多太多(就我目前的经历和心智来说),我想把所有一切都记录下来,又觉得一切似乎没那么有价值,对于我来说,我无法分清发生那么多事情的轻重缓急,无法在回顾时,想清楚如何讲给他人。</p>
<p>索性,仅仅把这篇总结回顾,视为讲给自己听的,写给自己的文字好了。</p>
<p>写到哪里就算哪里好了。</p>
<h3>01 It was pretty scary at the time</h3>
<p><em>It was pretty scary at the time, but looking back it was one of the best decisions I ever made.</em></p>
<p>今天心血来潮,想到了之前给@Hawstein发过一个邮件,是因为当时在推特上看到了一篇文章《一个独立创造者的五年》,后面有提到可以say hello,给大佬发邮件,便写了下面的邮件,非常能反应当时的心境。</p>
<p><img src="https://github.com/user-attachments/assets/4aacd0c3-1fa2-454e-9fe6-7532f1185d53" alt="image" /></p>
<p><em>我今天的心情大概这样,现在pretty scary at this time ,我担心拒掉唯一的offer后,更不确定性的未来。</em></p>
<p>当时的我已经研究生退学两年了,在机缘巧合下得知了二学位这个机会,又重新回到了一所二本的学校读计算机,已经读了近两年的计算机专业了,但秋招过后,计算机的岗位甚至都没有信心去投offer,只凭着六级跟之前的农学背景,拿到了几个教培及外贸的offer。</p>
<p>但心里又迟迟不甘心,还是想做计算机的工作。</p>
<p>当时的心境及offer情况在这篇博客中也有详细的描述:[开题答辩拿了高分,但关于未来很迷茫] (<a href="https://github.com/QiYongchuan/MyGitBlog/issues/52">https://github.com/QiYongchuan/MyGitBlog/issues/52</a>)</p>
<p><strong>就像两年前,我在对未来一无所知,毫无把握的情况下,从研究生退学那样,我又一次拒绝了到手的offer,选择了自己想做的那条路。</strong></p>
<p>不同的是,两年前我明确知道,我看到了农学研究生的未来,自己退学退的毫无留恋,义无反顾;但是两年后,我自己已经经历了退学后的种种事情,两年事情发生了太多变化:</p>
<p>21年的时候培训班转码学几个月前端就能入职,24年经济持续低落,企业开始了大裁员,黑马培训班已经停止了前端的招生。
而我心里也产生了很多的顾虑,太担心跟两年前研究生退学时一样,找不到工作了。</p>
<p>但当时,又因为上完了一个月的嵌入式开发的实训课,我自己第一次独自完成了一个项目,以及在学校的java实训课上,我自己认认真真的敲完了代码,跑通了这个项目,我又重新燃起了写代码的信心。</p>
<p>(其实这也说明了,我退学转码后这两年的学习方式是多么的错误,我一次有一次的选择了去看超级长,事无巨细的B站培训班的课,结果就是我一次又一次的放弃,太多的语法细节和报错,挫败了我的自信心,在一次又一次的打击下,我放弃了写代码,我以为自己没有天赋去写代码,十分痛苦。其实现在看来,最应该做的是从转码的第一天起,就应该动手去写代码,而不是先去看课,去记笔记,去记语法细节.....</p>
<p>而在学校最后的几个实训才让我明白,代码是动手敲的,而不是像之前考研复习一样,必须先背过知识点之后,才能动手做真题。</p>
<p>——总之,在二学位最后的时间,我遇到了两个改变了观念的老师,我代码路上的引路人,我得以明白,代码是需要动手做的,以及代码就像搭积木,一块一块的去搭就好了。</p>
<p>当时的笔记:<a href="https://github.com/QiYongchuan/MyGitBlog/issues/50">除了想象力,没有什么是限制</a></p>
<p>我重新捡起来写代码的兴趣,但还是非常焦虑将来的工作的,毕竟当时已经是11月秋招接近结束了,我的基础非常差,几乎没有看的下去的项目——源于我过去两年失败的转码学习,99%的精力放到了尝试一次又一次的超过100多个小时的B站视频上了。</p>
<p>当时想的是,哪怕最后我找不到敲代码的工作,大不了我做一些兼职的项目,哪怕是卖给本科生毕设项目呢,我也要继续下去。当时退学转码为的是什么,不能再去为了谋生就去做不喜欢的工作了。</p>
<p>很幸运的是,年后3月份,我找到了软件开发的工作,当然这是后话了,后面再详细讲吧。</p>
<h3>02 从二本考上了985的研究生,然后呢?</h3>
<p>“985研究生”,“二本逆袭”,“退学”,这些真的是很好的Tag,或者说是流量密码。</p>
<p>似乎大家都喜欢这样的戏份,我也是,我们从高中就开始灌输,“提高一分,干掉千人”,似乎考上一所好的大学的那一刻,就是人生赢家了。而对于小镇做题家的执念来说,二本似乎就成了原罪,于是在考研的时候,成功考上985,便是完成了华丽的逆袭。</p>
<p>过去很长时间,我也是这样想的,在我的第一个视频<a href="https://www.bilibili.com/video/BV14S4y1T77G/">我的考研故事:从一所二本学校到985专业第一</a> 时,我将这种心情表达的淋漓尽致。</p>
<p>当时在评论区,已经有一些不好的声音了,譬如,“天坑专业,考上了也没用”等等。</p>
<p>或许同大多人一样,在看到这种扎心的评论的第一时间,肯定会生气,继而忽略掉。坦白讲,以我当时的认知,大学过去的四年里,关于专业天坑的这种声音我听到的确实不多。</p>
<p>作为一个从小听老师话的乖学生,在以往听到这种“大逆不道”的话,我第一反应肯定是:啊,这种话怎么能说的呢?这不是吃饭砸锅吗?我们辅导员入学教育的时候可不是这样讲的; 或者是流传已久的"经典土木圣经",说这种话的人,肯定是loser.....
“没有垃圾专业,只有垃圾人”,“360行,行行出状元....."</p>
<p>另一方面,我确实听说过“生化环材”四大天坑的说法,可是我当时单纯的想法竟然是,我们是农学,又不是生物,所以生化环材四大天坑跟我们没关系啦。</p>
<p>后来才知道,生物被批判为天坑不假,但是我们农学是靠着生物吃饭的。</p>
<p>毕业投简历,能投进生物类的公司就算烧高香了。我们平时做的,都是生物上的东西,我们懂得,生物都懂,我们不懂的,人家生物还懂.....</p>
<p>但我本意不是想花太多的精力批判这个专业,我曾经无比热爱这个专业,也遇到很多受人尊重老师,他们一心钻研农业研究,勤勤恳恳做事,但对于大多数人来说,或者对于我而言,因为自身的局限性,我看不到好的就业前景。</p>
<p>去年的年终总结里可能更多的写了大学生活及退学的原因
<a href="https://github.com/QiYongchuan/MyGitBlog/issues/84">从研究生退学之后的两年</a></p>
<p>总之,在我读了一学期之后,我便陷入了对未来深深的焦虑与迷茫之中,在无比的痛苦中,我选择了退学。当时的想法很简单,哪怕我去培训班培训6个月的前端呢,我去写代码,也不想三年后研究生毕业的时候,在继续迷茫,当时想的是,哪怕什么都不敢,也比留下继续读完要强。</p>
<p>我当时的想法,三年毕业之后,要么继续参与这个游戏,读博,发文章,卷进高校;要么考公,要么去就业;但读博这条路在我进实验室看到大多数师兄师姐的状态后,我已经断了这个念头。考公我自知生性散漫喜好自由,实在不喜欢那个氛围,本科时便断了这个念头;就业,当时经济尚好,我们专业尚且困难.....</p>
<p>于是,我便退学了,仅仅想着退学后去培训班学几个月前端的想法下,就退学了,985的文凭我也不要了,总之,痛苦暂时接触了,在退学回来的火车上,我一遍又一遍的听着《没有理想的人不伤心》.....</p>
<p>那天还是一个很特殊的日子,2022年2月24日。</p>
<h3>03 退学之后,招转培陷阱以及自学岁月</h3>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/110"/><category term="notes"/><category term="Top"/><published>2024-12-22T04:26:12+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/109</id><title>生活是一场持续不断的战斗</title><updated>2024-12-22T15:49:28.738618+00:00</updated><content type="html"><![CDATA[<p>好久没有静下心来,写点什么了。</p>
<p>恰恰是发生了太多事情的时候,不知道该从哪里着手,思绪,情绪一下子太多了,于是索性放了下来,迟迟不知道该从哪里着手。</p>
<p>(一)
今天是11.17,一个11月寻常的周末。</p>
<p>下午的时候,QQ空间发了提醒,7年前的今天发的说说,也是一个周末的下午,那时我大一,还刚进入大学,和舍友在宿舍里看电影。真是怀念啊,心里一下子就想起了那句:</p>
<p>“欲买桂花同载酒,终不似,少年游。”</p>
<p><img src="https://github.com/user-attachments/assets/1ed64049-04c0-4d28-abee-dd58683a078f" alt="image" /></p>
<p>2017年,距离今天已经是7年之久了。</p>
<p>当时的我,肯定也不会想到,7年之后,我会经历3个学校,会在四年之后以第一名的成绩考到高考时不敢想的985学校,然后又在一个学期之后退学,放弃学了四年的农学,三年后又成为了一名码农。</p>
<p>.....</p>
<p>上一段写出来似乎有装逼炫耀之嫌,在这里写作应该真诚一些,不知道是不是最近写小红书写多了,总是不自觉的加一些耸人听闻的标签,也许是为了追求流量,也许是自我标榜,实在不该。</p>
<p>总之,没想到是已经7年之久了,7年前的我,年轻,单纯,期待着美好的大学四年生活,对未来一切都充满着好的幻想与期待。</p>
<p>(二)</p>
<p>其实最近值得写的东西有好多,如果时间拉回到6月份,我从计算机二学位毕业了,然后在6月份去新加坡实习,一个月的时间学到了很多,我也有信心将来能够转正,能够从事软件开发的工作了。</p>
<p>7月份,我拿到了offer,开始了三个月的试用期,我搬到了青岛开始了和女朋友的同居生活。期间,在特朗普枪击遇袭的那一天(7.14),我们有了一只可爱的小狗,可乐,然后8月份告别小狗与女朋友,我前往马来西亚短暂出差工作。</p>
<p>也是在出发的同一天,我收到了妈妈出车祸的消息。好在只是刮碰,仅仅是皮外伤。</p>
<p>在马来西亚呆满了整个8月,吉隆坡真是宜居的好地方,当地的同事每天下班前5分钟就开始收拾东西,一下班整个办公室接着关灯,主打一个“别想让我加一分钟的班”。</p>
<p>9月份我又去了新加坡,在新加坡仅仅呆了两周,在中秋节前一天的周一通勤地铁上,我接到了女朋友的视频电话,第一句就是,“你快看看小可乐吧,她快咽气了.....”</p>
<p>在新加坡早高峰的地铁上,我一下子慌了神。</p>
<p>也是在前一天晚上,我得知了,妈妈还在医院住院,我瞬间感觉不妙,追问下,爸爸也是含糊其辞,"就是一个结节,动了手术,再化疗化疗巩固一下,就出院了....."</p>
<p>到公司,我师傅问我下午的返讲准备的怎么样了,我一下子哭了出来,他带我到会议室,我还是哭个不停,断断续续的整理了好几次情绪,跟他说了这些事情,他表示理解,让我现在就放下手里的工作,不用担心工作,先回国,照顾好家人,等什么时候觉得可以工作了,再给我安排工作。</p>
<p>(三)</p>
<p>我当天晚上飞回了国,在肯德基等女朋友从老家回青岛,我看见她背着一个大大的宠物书包,空空的,里面已经没有了我们的小狗。回到出租屋里,满地都是可乐之前的玩具,我小心翼翼的收拾着。</p>
<p>第二天回老家,问起妈妈的病情,刚开始也还是含糊其辞,说好了。</p>
<p>后面才慢慢跟我说,当时被车撞了早就好了,就只是擦伤,去医院检查的时候发现了肺里有结节,医生说,要是再晚一年来医院,就是肺癌晚期了,就没救了。</p>
<p>妈妈庆幸地说,幸亏是被撞了了,要不然也不会来医院检查了,我春天的时候就觉得喘不上气来了,上药店拿了点药也不管事.....</p>
<p>我心里听了不是滋味,妈妈又跟我说,"人家说肺里结节,就是打这个疫苗打的,还打了三针,当时不打还不愿意,真是倒霉啊....."</p>
<p>从动了手术之后,妈妈每隔半个月,还得回医院化疗一星期,每次化疗回来,脸色都变得不好,最近一次,脸整个虚胖,浮肿。</p>
<p>(四)</p>
<p>我开始了半个月在老家,半个月在青岛的生活节奏,还是远程工作。</p>
<p>11月的时候,终于转正了,晚了一个月,因为中间请假的原因。</p>
<p>很珍惜也很喜欢现在的工作,远程,能够敲代码,同事很好,不懂的问师傅,每天都在学习。</p>
<p>对于毕业后第一份工作来说,已经很好了。</p>
<p>但可能是ADHD的原因,再加上是第一份工作,还是远程,很多时候,工作节奏把握不好。一段时间忙的要死,一段时间就很闲,有时又因为是远程工作的原因,自己在家就完全控制不好自己的专注力,甚至严重时,自己吃饭都成问题。</p>
<p>慢慢意识到,生活是一场持续不断的战斗,需要时刻规划好自己的注意力,做事情,一定要有结构性,有一个表去记录,开始-结束-后续,否则,就是一场漫无目的的漂流,任何方向,任何一点想法,就会让生活变得失去方向.</p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/109"/><category term="notes"/><published>2024-11-17T13:47:15+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/108</id><title>Cursor小白使用教程:从安装到开发浏览器插件</title><updated>2024-12-22T15:49:28.918724+00:00</updated><content type="html"><![CDATA[<p><em>网上的教程已经有很多了,有的也很详细,但本着”费曼学习法“的原则,我来写一下,我在使用过程中遇到的问题,我的开发体验。</em></p>
<p>首先Cursor是什么? Cursor = vscode + AI ? </p>
<p>其实Cursor从推出,到大火,已经有一段时间了,但因为最近工作太忙了,同时要上线好几个项目,实在忙不过来,心有余而力不足,前段时间才刚刚下载体验,带给我最大的感受:</p>
<p>就像第一次接触ChatGPT一样惊艳,对于一个从来没有接触开发过浏览器插件的人,我用了差不多不到10分钟,总共两次提问,就完成了一个简单的浏览器插件的开发。</p>
<p>在我没接触之前,还停留在 Cursor = vscode + AI ,仅仅以为是把各种大语言模型(ChatGPT/Claude/)集中到了vscode中,不需要再去把你的代码复制到网页端,然后让其分析生成代码,再粘贴代码回你的编译器。</p>
<p>如果是这样,那我之前也体验过一些这样的插件,感觉仅仅是省去了复制-粘贴这一步。</p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/108"/><published>2024-10-26T14:50:11+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/107</id><title>Cursor折腾记录:开发趣味英语插件</title><updated>2024-12-22T15:49:29.092443+00:00</updated><content type="html"><![CDATA[<p>好玩的功能点:</p>
<ul>
<li>拍照,识别图片中的英文,到单词</li>
<li>上传一本书,解析书中的单词</li>
<li>单词自动出现在屏幕的某处,三秒后出现单词的中文释义,之后是英文释义,然后是例句,之后消失</li>
</ul>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/107"/><published>2024-10-24T13:49:08+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/106</id><title>增量下载的时间陷阱:一次时间处理错误引发的重复下载问题</title><updated>2024-12-22T15:49:29.258965+00:00</updated><content type="html"><![CDATA[<blockquote>
<p>为什么即使代码中设置了增量下载,还是会不断重复下载一些数据? 记录一次与时间处理相关的debug过程</p>
</blockquote>
<h2>业务场景:重复下载问题的发现</h2>
<p>在开发与第三方平台 <strong>banqup</strong> 的对接过程中,我遇到了一个非常奇怪的问题:<br />
<strong>即使使用了增量下载的逻辑,某些发票数据却被重复下载了。</strong></p>
<h3>问题背景</h3>
<ul>
<li>系统从 <strong>banqup</strong> 平台获取采购发票,并采用<strong>增量下载逻辑</strong>:每次下载后记录最新的时间点,下次从这个时间点之后再获取新的数据。</li>
<li>按理说,只要记录并从上次下载的时间点之后进行增量下载,就不会出现重复数据。</li>
</ul>
<p>然而,在分析日志时,我发现系统多次下载了<strong>同一时间段</strong>的发票,这引发了我的疑问:<br />
<strong>为什么已经下载过的数据会再次出现在后续的增量下载中?</strong></p>
<hr />
<h2>排查问题的过程</h2>
<h3>1. 检查增量下载逻辑</h3>
<p>我首先检查了下载逻辑代码,确保每次下载时,都准确地使用了<strong>上次下载的时间点</strong>。<br />
关键逻辑如下:</p>
<pre><code class="language-java">String lastedCreatedTime = searchLastestCreatedTime(pk_org); // 查询上次下载的时间
String requestURI;
if (lastedCreatedTime == null) {
// 如果没有记录时间,则进行全量下载
requestURI = nc.bs.einvoice.util.BillEffectUtils.getBaseURL()
+ "purchase-invoices?page=" + page + "&size=" + size
+ "&is_invoice_lines_included=1&sort=created_at,desc";
} else {
// 使用上次下载的时间进行增量下载
requestURI = nc.bs.einvoice.util.BillEffectUtils.getBaseURL()
+ "purchase-invoices?page=" + page + "&size=" + size
+ "&created_at.gte=" + lastedCreatedTime
+ "&is_invoice_lines_included=1&sort=created_at,desc";
}
</code></pre>
<p>下载逻辑看起来没有问题——<strong>如果记录了上次的下载时间,就会从这个时间点之后获取新的发票</strong>。但既然逻辑正确,为什么还会出现重复下载呢?</p>
<hr />
<h3>2. 查看数据库中存储的时间格式</h3>
<p>为了进一步排查,我查看了数据库中的时间存储情况:</p>
<pre><code class="language-java">private String searchLastestCreatedTime(String pk_org) {
SqlBuilder sborg = new SqlBuilder();
sborg.append("select TOP 1 created_at from einvoice_purchase_h ");
sborg.append("where pk_org", pk_org);
sborg.append("order by created_at desc");
DataAccessUtils utilorg = new DataAccessUtils();
IRowSet roworg = utilorg.query(sborg.toString());
String lastest_time = null;
if (roworg != null && roworg.next()) {
lastest_time = roworg.getString(0); // 从数据库获取时间
}
return lastest_time == null ? null : convertToIsoFormat(lastest_time);
}
</code></pre>
<p>我发现数据库中存储的时间是<strong>类似本地时间格式</strong>的,而增量下载使用的时间是 <strong>ISO 8601 的 UTC 时间格式</strong>。</p>
<hr />
<h3>3. 时间转换的逻辑问题</h3>
<p>接下来,我仔细检查了时间转换的代码,发现了一个关键问题:</p>
<h4><strong>从 banqup 获取时间时:</strong></h4>
<pre><code class="language-java">SimpleDateFormat createAtFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'");
if (!jsonArray.getJSONObject(i).isNull("created_at")) {
try {
date = createAtFormatter.parse(jsonArray.getJSONObject(i).getString("created_at"));
} catch (ParseException e) {
throw new BusinessException("Invalid created_at format");
}
hvo.setCreated_at(new UFDateTime(date));
}
</code></pre>
<p><strong>错误:</strong> </p>
<ul>
<li><strong><code>SimpleDateFormat</code></strong> 默认使用<strong>本地时区</strong>(如 UTC+8)进行解析,即使时间字符串是 <strong>UTC 时间</strong>。</li>
<li>这意味着,我错误地将 <strong><code>2024-10-09T02:47:45.394780Z</code></strong> 当成<strong>本地时间</strong>存入数据库。</li>
</ul>
<h4><strong>从数据库读取时间时:</strong></h4>
<pre><code class="language-java">private String convertToIsoFormat(String dateTime) {
DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.parse(dateTime, inputFormatter);
// 使用系统默认时区创建带时区的时间对象
ZonedDateTime utcDateTime = localDateTime.atZone(ZoneOffset.systemDefault())
.withZoneSameInstant(ZoneOffset.UTC);
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'");
return utcDateTime.format(outputFormatter);
}
</code></pre>
<p><strong>错误:</strong></p>
<ul>
<li>存储时将 <strong>UTC 时间误当成本地时间</strong>存入数据库。</li>
<li>查询时再错误地将<strong>本地时间转回 UTC 时间</strong>,导致时间点偏移。</li>
</ul>
<hr />
<h2><strong>问题的根本原因</strong></h2>
<p>这两个错误导致了时间点的错位:</p>
<ol>
<li>
<strong>重复下载</strong>:<ul>
<li>由于存储的本地时间被误解为 UTC 时间,在增量查询时,从一个<strong>更早的时间点</strong>开始下载,导致重复下载。</li>
</ul>
</li>
</ol>
<hr />
<h2><strong>解决方案</strong></h2>
<h3><strong>1. 正确解析和存储时间</strong></h3>
<p>从第三方平台获取时间时,确保使用 <strong>UTC</strong> 进行解析:</p>
<pre><code class="language-java">SimpleDateFormat createAtFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'");
createAtFormatter.setTimeZone(TimeZone.getTimeZone("UTC")); // 显式设置为 UTC
if (!jsonArray.getJSONObject(i).isNull("created_at")) {
try {
date = createAtFormatter.parse(jsonArray.getJSONObject(i).getString("created_at"));
} catch (ParseException e) {
throw new BusinessException("Invalid created_at format");
}
hvo.setCreated_at(new UFDateTime(date));
}
</code></pre>
<hr />
<h3><strong>2. 查询时保持时间一致性</strong></h3>
<p>从数据库查询时间时,确保时间格式不再错误转换:</p>
<pre><code class="language-java">private String searchLastestCreatedTime(String pk_org) {
SqlBuilder sborg = new SqlBuilder();
sborg.append("select TOP 1 created_at from einvoice_purchase_h ");
sborg.append("where pk_org", pk_org);
sborg.append("order by created_at desc");
DataAccessUtils utilorg = new DataAccessUtils();
IRowSet roworg = utilorg.query(sborg.toString());
String lastest_time = null;
if (roworg != null && roworg.next()) {
lastest_time = roworg.getString(0); // 获取 UTC 时间
}
return lastest_time == null ? null : lastest_time; // 不做多余转换
}
</code></pre>
<hr />
<h2><strong>总结</strong></h2>
<p>这次问题的根源在于<strong>时间和时区的处理不当</strong>。由于我错误地将<strong>UTC 时间当成本地时间存储</strong>,并在查询时<strong>再次错误转换</strong>,导致了<strong>重复下载</strong>的问题。</p>
<h3><strong>经验总结:</strong></h3>
<ol>
<li><strong>所有时间都应以 UTC 格式存储和使用</strong>,避免因时区问题造成数据偏移。</li>
<li><strong>解析时间时明确设置时区</strong>,确保时间处理一致。</li>
<li>在增量下载逻辑中,保持时间格式的一致性,避免因时间错位造成数据重复或遗漏。</li>
</ol>
<p>通过这次问题排查,我对<strong>时间和时区处理</strong>的重要性有了更深刻的认识。希望这篇博客能帮助大家在开发过程中避免类似的问题!</p>
<p><em>后记:本篇博客上述内容是由chatgpt-4o基于我们的历史对话记录生成,全文未改一字。 犯这个错误本质还是对java中时间格式处理不熟,(可以说是业务上第一次遇到),才犯下的低级错误。</em></p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/106"/><category term="Kill-bugs"/><category term="notes"/><published>2024-10-22T08:27:26+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/105</id><title>转码后第一份工作:那些内耗焦虑的时刻</title><updated>2024-12-22T15:49:29.451196+00:00</updated><content type="html"><![CDATA[<p><img src="https://github.com/user-attachments/assets/94144269-9930-44a2-8545-e9d88d394f93" alt="image" /></p>
<p><img src="https://github.com/user-attachments/assets/7232dd2c-aad7-43d3-8871-2cacebcc270a" alt="image" /></p>
<p>前段时间实习的时候发的,当时心态极度焦虑,内耗,毕竟是转码后第一份工作,第一次真正接触到实际的工作中。</p>
<p>遇到了很多的问题,发现自己技术很菜,很担心被人说,你怎么这么菜,怎么连这也不会?怎么连这也没听说过?</p>
<p>当时患得患失,一度到了有问题都不敢讲的地步。</p>
<p>后来大概是,所谓的“触底反弹”吧?</p>
<p>我想通了,大不了最差的结果就是,不过呗。这样你大不了开了我,我还不干了,我也不整天焦虑做不出来了。</p>
<p>想明白了这一点后,我整个人轻松了下来,没什么大不了嘛,顶多就是拜拜了。</p>
<p>我至少有了工作经验,至少比我刚进公司时的水平提高了,那我遇到问题就问,自己解决不了,就直接抛出给我师傅,反而工作起来顺利多了,心态也慢慢变好了。</p>
<p>至于后面,总还是会遇到“你怎么技术这么菜?”的时刻,慢慢想明白了,人最重要的是勇敢,勇敢接收和面对真实的自己,菜就多练好了。这次你指出我技术菜,至少我知道了这么写不对,又有了提到的地方了,下一次我就会了。</p>
<p>其时在ld或者其他同事眼里,你的技术水平大家肯定是清楚的(就是你真的很菜),但他们是接纳了一定程度上你技术的菜的。</p>
<p>最后的最后,我又有了新的认识,今天听了另一个新同事的转正返讲,她ld点评时说,“只要态度认真,会debug,问题总会一点一点解决的,无非是熟悉了解决的快一点,刚开始慢一点,只要认真学,总会学会的,解决掉的。”</p>
<p>工作无非就是工作,最坏不过是搞砸好了,人生还很漫长呢!</p>
<p>人生的难题大概也是如此吧,慢慢debug,总会解决掉的。</p>
<p><img src="https://github.com/user-attachments/assets/d9c5373a-d8a4-458c-abd7-649cb8af1567" alt="image" /></p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/105"/><category term="daily"/><published>2024-10-20T14:08:38+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/104</id><title>跑车级大脑,但刹车失灵是一种什么体验:ADHD的困扰与天赋</title><updated>2024-12-22T15:49:29.636255+00:00</updated><content type="html"><![CDATA[<h1>ADHDer的人,拥有跑车级的大脑,但是刹车坏掉了</h1>
<p>在新加坡地铁上,每天早上上班的路上,差不多 10 天时间,10 个小时左右听完了这本书。</p>
<p>最开始发现这本书是看到推特上有人分享,ADHD(注意力缺陷)会有一种模式,<strong>hyperfocus</strong>,即注意力高度集中模式,表现在当投入感兴趣的事情的时候,往往几个小时出不来,会一直沉浸在其中。所以 ADHDer 要尽量避免晚上的时候,写作、编程等投入的工作。</p>
<p>在我某一次写完代码,又到了凌晨两点的时候,看到了这个帖子,愈发感觉自己是这样的。于是在推荐下看了这本关于 ADHD 的书,一位美国心理学家(同时也是 ADHDer)写的书。在书里看到了太多类似的经历了:</p>
<ul>
<li>小学的冬天,手套丢了太多副,经常是忘记放到哪里了,有时候丢一只,有时候两只一起丢,就这样光手套差不多买了近十来个了。</li>
<li>高中的时候,语文考试写作文,最头疼的是纠结开头和题目,要想半天,如果想不到一个足够刺激(或者说精彩)的题目,往往怎么也写不下去。</li>
<li>大学的时候,经常忘记 ddl,会想不起交实验报告,会拖延。</li>
<li>一开始学写代码的时候,经常拼错一个单词,搞错单词字母的顺序,看半天也看不出什么来。(ADHDer 往往也有阅读障碍)</li>
</ul>
<p>以及回想过去的经历,经常会被指责太粗心了。这些都是 ADHD 的一大特征,<strong>分心</strong>。</p>
<h3>ADHD 的好处:创造力与高度集中模式 (hyperfocus)</h3>
<p>分心是因为大脑总是在寻找足够刺激的想法,这带来了很多神奇的点子。无论是白日梦,还是各种奇怪的想法,总是会时不时涌现。</p>
<p>在我接触 ChatGPT 和各种眼花缭乱好玩的 AI 应用时,我差不多每天都涌现出各种衍生的、类似的、升级的想法,各种让我自己眼前一亮、一想到就兴奋得睡不着觉的好玩的点子。(我甚至专门开了一个博客记录这些想法)</p>
<p>但正如开头提到的,ADHDer 的大脑,拥有跑车级性能的大脑,但<strong>刹车不好使</strong>。往往想到这个,搞一搞,突然又有了新的想法,又跳出去搞别的了。容易被别的东西吸引,容易被自己新的想法吸引。</p>
<h2>关于 hyperfocus 模式</h2>
<p>我最开始了解 ADHD 其实是从了解这个模式开始的。我一直以为注意力缺陷就是多动症,就是集中不了注意力。后来关注的一个博主在法国读博,讲了一系列 hyperfocus 下的行为特点:熬夜、高强度投入等等,我才开始进一步了解。(这段写得不好,毕竟我可能是 ADHD,我的注意力又跑了:)</p>
<p>书中提到 hyperfocus 的描述:当遇到感兴趣的事,投入进去时,大脑神经就像排列整齐的猎犬一样,高度集中。而平时,ADHDer 的神经,就像打碎了玻璃温度计里的水银一样,四散。</p>
<p>就先写这些吧,毕竟我的注意力又跑丢了。而且现在已经是凌晨 1 点了,进入危险时间了,不能深夜写作……</p>
<p><em>2024.9.12 凌晨12:57 于新加坡</em></p>
<p><img src="https://github.com/user-attachments/assets/77f6d37f-776b-4ec6-8f33-d799de1cdc36" alt="e845ae307c6c18b74c1d0627ca8feaa" /></p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/104"/><category term="daily"/><published>2024-10-11T14:02:45+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/103</id><title>Java学习笔记16:Java中发送网络请求的各种方式</title><updated>2024-12-22T15:49:29.824974+00:00</updated><content type="html"><![CDATA[<p><strong>1.使用 Java 原生的 HttpURLConnection</strong> </p>
<pre><code class="language-java">private JSONObject sendHttpRequest(String requestURI, JSONObject jsonBody) throws IOException, BusinessException, JSONException {
String access_token = nc.bs.einvoice.util.BillEffectUtils.ensureToken();
HttpURLConnection debtorsRequest = (HttpURLConnection) new URL(requestURI).openConnection();
debtorsRequest.setRequestMethod("POST");
debtorsRequest.setRequestProperty("Authorization", "Bearer " + access_token);
debtorsRequest.setRequestProperty("Content-Type", "application/json");
debtorsRequest.setRequestProperty("Accept", "*/*");
debtorsRequest.setDoOutput(true);
try (OutputStream os = debtorsRequest.getOutputStream()) {
byte[] input = jsonBody.toString().getBytes("utf-8");
os.write(input, 0, input.length);
}
int responseCode = debtorsRequest.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED) {
BufferedReader reader = new BufferedReader(new InputStreamReader(debtorsRequest.getInputStream()));
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
return new JSONObject(response.toString());
} else {
handleError(debtorsRequest);
return null;
}
}
private void handleError(HttpURLConnection debtorsRequest) throws IOException, JSONException, BusinessException {
BufferedReader errorResponseReader = new BufferedReader(new InputStreamReader(debtorsRequest.getErrorStream()));
StringBuilder errorResponseText = new StringBuilder();
String errorLine;
while ((errorLine = errorResponseReader.readLine()) != null) {
errorResponseText.append(errorLine);
}
JSONObject errorResponse = new JSONObject(errorResponseText.toString());
String errorMessage = errorResponse.optString("message", "Unknown error");
JSONObject errors = errorResponse.optJSONObject("errors");
throw new BusinessException("Error from API: " + errorMessage + " \\nDetails: " + errors);
}
</code></pre>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/103"/><category term="notes"/><published>2024-08-15T06:41:51+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/102</id><title>增援未来:健身与学习</title><updated>2024-12-22T15:49:30.002637+00:00</updated><content type="html"><![CDATA[<p>突然想到一个点:健身是一种“增援未来”的行为。</p>
<p>刚开始健身的时候,每次运动完,浑身疼,且精疲力尽,累的要死。</p>
<p>但时间久了才慢慢感受到,自己的精力在慢慢变好,一个很明显的体现是,以前下班回家之后,做什么都提不起精神来。以往很多时候,会有“脑雾”现象:就是感觉大脑混浊一片,浑浑噩噩的什么都不想干的时刻,现在也越来越少了。</p>
<p>想起教练说的一句话,健身是以年为单位的。</p>
<p>今天才意识到,很多事情是需要痛苦、时间,然后等待的过程。</p>
<p>我想起了我的代码学习,之前不知道要学习什么,就挑着自己感兴趣的,“瞎学了”一大些:cs50,嵌入式了,vue了,react了,很多很多,有些纯纯是因为当时觉得很酷就学了。</p>
<p>在后面进公司实习的时候,要用之前不熟的java,因为之前自己乱七八糟的学了不少语言,心里还好不是很怵,慢慢的上手,才发现好多东西都是相同的,比如某个java上的概念我不理解写不出来时,我就先用Python或者js描述给chatgpt,然后让它给我讲java中如何实现。</p>
<p>有一种在黑漆漆的山洞里,逐渐点亮火把的感觉。 </p>
<p>今天在小红书刷到了有人发cs50、cs61a/b的学习记录,又燃起了我的学习热情,当时cs50学起来还好,cs61a/b学起来是真的痛苦,且没有学完就放弃了。
现在有了chatgpt4,我想带着我的小伙伴,再来挑战一下。</p>
<p>同样,我现在学这些,跟我目前的工作不是很强的相关性的,我目前不需要再很细的去研究算法,去研究怎样用java实现一个git控制系统,但光是听名字,就很酷的东西,怎么能不去玩一玩呢?</p>
<p>不知道这个种子种下之后,将来会结出什么果,但是who care呢? 就像健身,每一次精疲力尽之后,气喘吁吁的大口呼气是我最享受的时刻,编程的时候debug找到问题解决的那一刻,也是最爽的时刻。</p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/102"/><category term="daily"/><published>2024-08-15T06:04:43+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/101</id><title>从农业研究生退学到一名程序员:我的转码之路</title><updated>2024-12-22T15:49:30.173965+00:00</updated><content type="html"><![CDATA[<blockquote>
<p>坦白讲,我认为自己还不够格写一篇这样的文章,深知自己目前实力很差,勉勉强强称的上菜鸟程序员。从研究生退学到现在,差不多已经过去两年之久了,从4.1号拿到offer入职,到现在实实在在的工作经验也不过4个月之久,远远还没有达到,跳出来写一篇所谓的经验之贴,给同样希望转码的人传授什么的资格。</p>
<p>此篇,仅作为自己过去经历的总结,如有读者看到,供娱乐文章一读即可。</p>
</blockquote>
<p>从之前的抓虫子,到现在的debug,想来这段经历也挺有趣。只不过这是如今事后看罢了,这其中的辛酸过程,自是只有自己才体会的到。</p>
<p>不过今天不忆苦思甜,不扯东扯西,只讲点实际的东西。</p>
<p>在我研究生退学之前,也曾无数次搜过相关的文章,如何转码成为一名程序员。</p>
<p>答案五花八门,有各种课程要学,各种技术栈等等,看得人心里直痒痒,既激动又焦虑。激动是觉得自己按照这个路线学下去,一定也能成功,焦虑则是,太多课程了,学不会咋办? 学完了,还是找不到工作咋办?</p>
<p>以及,考虑要不要报一个培训班? (尤其是培训班往往还在鼓吹保就业)</p>
<p><strong>00 B站自学</strong></p>
<p>我当时也面临这种情况,尤其是刚刚研究生退学,去青岛跟对象合租,在家自学时。着急想要证明自己,退学了也一定能混出名堂。于是在这种心态下,自学了差不多两个月的前端课程,这个阶段主要是看B站的pink老师的课。</p>
<p>但无奈的是,心态上焦虑,课程又漫长,看了两个月,JavaScript才刚开始看。再加上课又长,每天看一点点,视频都看不完,更别说自己动手敲代码了,就这样每天焦虑的看课赶进度,有时候截图记记笔记,课是怎么也看不完,代码呢,则是一看就懂,一敲全部报错。</p>
<p>于是这时候就去搜各种的经验贴,还加了几个前端交流群。</p>
<p>经验贴让你手敲代码,亲自去写一下。</p>
<p>但当时的我,一心只想着赶紧看完课,要去找工作了。手敲代码,一敲全是报错,半天找不出哪里错了来,越看代码越头疼,越错越不想写,再加上急切的想证明自己,结果就是越想证明自己,越担心写的代码报错,更担心报错了,半天解决不了。 于是积极性备受打击,常常陷入习得性无助里。(如果当时有chatgpt的话,或许学习之路会少很多的痛苦了)</p>
<p><strong>01 “招转培”</strong></p>
<p>当时看前端群里吹水,“谁谁谁包装经验又拿到了xx的薪资了,面试就背背就能上岸了.....”
于是,我心里也活泛了起来,又看到了希望。当然当时还没有勇气包装简历,毕竟前端三件套,才刚学到js。是当时才22年3月份,我是21年应届考上的研究生,22年2月就退学了,心想,应届生身份不是说两年嘛? 那我投一投春招吧,说不定有企业愿意培养应届生呢。</p>
<p>于是打开boss直聘开始投简历,投了几份几乎没结果。就在本着随便投投的心态试试水来着,某天中午,正在午休的时候,一个电话打了过来。一家我从没有投过简历,甚至在boss直聘上搜不到名字的公司约了面试,从此我迎来了噩梦的一个月,招转培的生活。</p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/101"/><category term="daily"/><category term="Top"/><published>2024-08-12T15:09:39+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/100</id><title>火神的禁区与n<=4的联排插排</title><updated>2024-12-22T15:49:30.363148+00:00</updated><content type="html"><![CDATA[<p>火神的禁区与n<=4的联排插排
01
连续的隧道弯道,视野却逐渐飞升,就像灵魂飘出了车里,飘到了空中,我成了第三方视角一样还在开大巴车,但视线被隧道挡住,只能凭感觉驾驶。</p>
<p>弯弯曲曲的路,马上进隧道。轰隆一声爆炸,我回到现实,大巴车终于还是撞了,车头撞烂挤在了一块。</p>
<p>一个认识的叔叔挤在了上面,还在喊我的名字,“永传,没事,我没事……”</p>
<p>幸运的是,车上50个人,除了一个受轻伤,均没有大碍,我们下了车。我们一家三口下了车,爸妈也带着劫后逃生,死里逃生的轻松感。</p>
<p>我跟他们还有一同赶来救援的人讲了,出事时我的状态和感觉。</p>
<p>一个老者说,前面是火神的禁区,又来了,今天已经过来了20多辆车,还没有一辆顺利开过去,
不是着火就是爆炸……</p>
<p>听到这我心里突然又轻松了许多,看来我出车灵魂飞出,车爆炸也不能是我自己的问题了,又是因为死里逃生,一家人还在一起。</p>
<p>于是一家人在熊熊燃烧的大火与大山前,拍了好多的合照。有意思的是,这里拍出的照片,生成的全是像原始人壁画上那种,红色线条的简体画。</p>
<p><img src="https://github.com/user-attachments/assets/dc0d4afe-facb-4b60-931c-b863d2073fbf" alt="image" />
<img src="https://github.com/user-attachments/assets/ab20848d-b1e5-43d2-820f-3d6f657b9e77" alt="image" /></p>
<p>02
既然过不去这片山,火神的禁区,索性便就住了下来。</p>
<p>跟朋友住在另一处地方,整个小镇大停电,但唯独我们家还有电。我赶紧告诉朋友,快拿出你们所有的充电宝,手机,电脑,我们赶紧冲满电,然后把我们的插口往外租给别人卖。</p>
<p>于是,我们家唯一有点的插口,被我连了一个插排出来之后,我的设备几乎占满了插排上的口,又被朋友的插排接上,形成了“插排树”,就这样最后竟然形成了7层的插排树结构。</p>
<p>密密麻麻的,上面连了我们的各种设备,很是壮观。</p>
<p>就这样我们一边在房间里玩着牌,一边等着顾客上面,毕竟我们现在是小镇上唯一有电的地方了。</p>
<p>后来没多久,以我房间为中心,竟然发展成了一个商业街,灯光以此为中心逐渐减弱,也别有一番风景。</p>
<p>某天,消防来检查消防隐患,将我们的插排树给拔了下来,他们告诉我,插排最多可以外接3个,一共必须小于4层结构,不然容易引起火灾。</p>
<p>于是我们把原来的单层7排结构,改成了左右结构的插排树。</p>
<p><img src="https://github.com/user-attachments/assets/e82a7ef1-7072-409f-a9ae-3ee71c2553c4" alt="d982e7264d04d26f42ab8abd6501fae" /></p>
<blockquote>
<p>后补:
1.图片来源于chatgpt4.0 DALL-E 模型
<img src="https://github.com/user-attachments/assets/0ded361b-6ccd-4e56-bd4d-6ef4a13b122b" alt="279e09ca50e66a58a2e9f5b46bd91ac" />
2.源于午后的真实梦境,在早上的时候参观了吉隆坡的印度教宗教景点,黑风洞,梦醒后写完本篇文字查阅资料后,才发现印度教中火,亦扮演重要的角色,实在有趣。
<img src="https://github.com/user-attachments/assets/61e5af3d-9221-4dcf-8276-b4df729530a1" alt="f05c78bbcd2c56516308caf5c115f8d" />
<img src="https://github.com/user-attachments/assets/485bd1cd-82c5-45ce-b6b2-af82086957aa" alt="7f8b83b7851dee9aeadab81d3910313" /></p>
</blockquote>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/100"/><category term="daily"/><published>2024-08-11T15:51:41+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/99</id><title>OpenApiUtil :封装调用接口的方法</title><updated>2024-12-22T15:49:30.569607+00:00</updated><content type="html"><![CDATA[<pre><code>package nc.bs.einvoice.util;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import nc.vo.pub.BusinessException;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
import java.util.Map;
public class OpenApiUtil {
private static CloseableHttpClient httpClient = HttpClients.createDefault();
/**
* 执行GET请求并返回指定类型的响应。
* @throws BusinessException
*/
public static <T> T doGet(String url, Map<String, String> headers, Class<T> responseType) throws BusinessException {
HttpGet httpGet = new HttpGet(url);
if (headers != null) {
headers.forEach(httpGet::addHeader);
}
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
JSONObject jsonObject = handleResponse(response);
return JSON.parseObject(jsonObject.toJSONString(), responseType);
} catch (IOException | BusinessException e) {
throw new BusinessException("执行GET请求失败", e);
}
}
/**
* 执行POST请求,发送JSON数据,并返回指定类型的响应。
*/
public static <T> T doPost(String url, Object payload, Map<String, String> headers, Class<T> responseType) {
HttpPost httpPost = new HttpPost(url);
StringEntity entity = new StringEntity(JSON.toJSONString(payload), "UTF-8");
httpPost.setEntity(entity);
httpPost.setHeader("Content-Type", "application/json");
if (headers != null) {
headers.forEach(httpPost::addHeader);
}
try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
JSONObject jsonObject = handleResponse(response);
return JSON.parseObject(jsonObject.toJSONString(), responseType);
} catch (IOException | BusinessException e) {
throw new RuntimeException("执行POST请求失败", e);
}
}
/**
* 处理HTTP响应的通用逻辑。
* @throws BusinessException
*/
private static JSONObject handleResponse(CloseableHttpResponse response) throws BusinessException {
int statusCode;
String jsonResponse;
try {
statusCode = response.getStatusLine().getStatusCode();
jsonResponse = EntityUtils.toString(response.getEntity());
} catch (IOException e) {
// 捕获 IOException 并重新抛出为 BusinessException
throw new BusinessException("网络请求失败: " + e.getMessage(), e);
}
if (statusCode >= 200 && statusCode <= 300) {
if (statusCode == HttpStatus.SC_NO_CONTENT) {
return new JSONObject(); // 或者返回null,具体取决于业务逻辑
}
return JSON.parseObject(jsonResponse);
} else if (statusCode == 400) {
JSONObject errorResponse = JSON.parseObject(jsonResponse.toString());
String errorMessage = errorResponse.getString("message");
if (errorMessage == null) {
errorMessage = "Unknown error";
}
String status = errorResponse.getString("status");
if (status == null) {
status = "Unknown status";
}
JSONObject errors = errorResponse.getJSONObject("errors");
throw new BusinessException("Status: " + status + "\nError from API: " + errorMessage + " \nDetails: " + errors);
} else {
// 对其他错误状态码的处理可以类似地扩展
throw new BusinessException("HTTP请求失败: 状态码 " + statusCode);
}
}
}
</code></pre>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/99"/><category term="notes"/><published>2024-07-22T14:45:23+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/98</id><title>Java学习笔记15:数据结构</title><updated>2024-12-22T15:49:30.733122+00:00</updated><content type="html"><![CDATA[<p><img src="https://github.com/user-attachments/assets/99672c6f-0b55-4b79-858d-c64bdf25f939" alt="image" /></p>
<pre><code>// 创建一个 HashMap 实例来存储请求头信息
Map<String, String> headers = new HashMap<>();
// 添加授权信息到请求头中
headers.put("Authorization", "Bearer " + accessToken);
// 设置接受的响应类型为 JSON
headers.put("Accept", "application/json"); // 改为接受 JSON 格式的响应
</code></pre>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/98"/><category term="notes"/><published>2024-07-19T07:24:29+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/97</id><title>海的那边是什么? </title><updated>2024-12-22T15:49:30.920893+00:00</updated><content type="html"><![CDATA[<p>现在是午夜1:20,我在候机厅里,再过二十几分钟,我将登上飞回中国的飞机,同时也将结束我在新加坡xx公司一个月的实习了。</p>
<p>几十分钟前,我坐在机场的大厅的地上,改完了bug,明天系统要进行演示。</p>
<p>一个月前,我肯定不会想到,我会在熬夜加班了一个星期后,还有耐心的掏出电脑,看代码。
我肯定也不会想到,这一个月我写了看了这么多的java,差不多两个月前,我刚因为毕设改用了java死活写不出来,甚至四个月前,我才开始重新系统学java.</p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/97"/><published>2024-06-03T17:25:36+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/96</id><title>基于自然语言和图像生成技术的英语词汇学习系统:项目总结</title><updated>2024-12-22T15:49:31.083795+00:00</updated><content type="html"><![CDATA[<blockquote>
<p>第一版开发已经完成,实现了前后端的联通,核心功能已经实现,单词=>llm的解释、例句,单词=>图片的生成,写此总结一下项目过程中遇到的问题,目前计划要写:</p>
</blockquote>
<ul>
<li><input disabled="" type="checkbox"> Prompt编写,如何控制llm输出json格式的结果</li>
<li><input disabled="" type="checkbox"> 数据库存储json格式的结果遇到的问题</li>
<li><input disabled="" type="checkbox"> 如何存储图片</li>
</ul>
<blockquote>
<p>又想到中期答辩给打了最低分,越想越生气,迟迟不想动笔了,暂时先放下一段时间再写好了。</p>
</blockquote>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/96"/><category term="notes"/><category term="项目记录"/><published>2024-03-26T12:24:03+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/95</id><title>Vue笔记</title><updated>2024-12-22T15:49:31.240752+00:00</updated><content type="html"><![CDATA[<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/d5d7e80f-2bb1-44be-b361-0b6889c0a585" alt="image" /></p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/95"/><published>2024-03-19T17:51:09+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/94</id><title>SpringBoot学习笔记:MyBatis以及MyBatisPlus</title><updated>2024-12-22T15:49:31.451953+00:00</updated><content type="html"><![CDATA[<h4>ORM介绍</h4>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/b3d69d94-7e1a-48d6-b38d-8d15ea56c4b0" alt="image" /></p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/76885f31-7e45-4228-ba4e-d7a8e269e916" alt="image" /></p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/5e198fd2-eeb6-4be2-8e52-ac0aafe39b21" alt="image" /></p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/94"/><published>2024-03-19T12:19:37+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/93</id><title>SpringBoot学习笔记:Swagger</title><updated>2024-12-22T15:49:31.625671+00:00</updated><content type="html"><![CDATA[<p>API表达工具
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/bb53a22e-79ee-4373-a57c-73d6afef8a6d" alt="image" /></p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/93"/><published>2024-03-19T07:44:50+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/92</id><title>SpringBoot学习笔记:RESTful应用接口</title><updated>2024-12-22T15:49:31.787808+00:00</updated><content type="html"><![CDATA[<h4>什么是RESTful?</h4>
<p>REST(Representational State Transfer)是一组设计原则,用于构建网络服务。RESTful服务意味着遵循这些设计原则的服务。</p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/88852ba7-bf4a-474e-b180-48886926593e" alt="image" />
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/ef022762-b68e-4b72-bd5c-0b9891372730" alt="image" /></p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/46fcc40a-5a3c-4dd7-8c96-1360f393784d" alt="image" />
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/edf1a8b4-712f-4355-b314-db34cbc6ece9" alt="image" />
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/b03f92a3-70f7-4ebc-9c94-8332207d584e" alt="image" /></p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/92"/><category term="notes"/><published>2024-03-19T06:19:46+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/91</id><title>SpringBoot学习笔记:拦截器</title><updated>2024-12-22T15:49:31.969990+00:00</updated><content type="html"><![CDATA[<p><strong>拦截器(Interceptor)是用来拦截进入Controller方法之前或之后的请求的。
它们常用于日志记录、身份验证、权限检查、或者添加通用的请求或响应的头信息等场景。</strong></p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/1bdc09ec-ce55-4cf0-9c4e-684795045958" alt="image" /></p>
<p>用的最多的是preHandle</p>
<p>简单使用:</p>
<p>1.创建拦截器</p>
<pre><code>public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("登录拦截器");
return true;
// 其中request对应的就是前端的请求
// if (request.getSession().getAttribute("user") == null)
// return false;
// else if (request.getSession().getAttribute("user") != null) {
// return true;
// } 可根据条件来判断
}
}
</code></pre>
<p>2.注册拦截器</p>
<pre><code>@Configuration //注明是配置类
public class WebConfig implements WebMvcConfigurer {
@Override // 添加拦截器,将我们之前写的拦截器注册,添加拦截的路径,使其生效
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/user/**");
registry.addInterceptor(new LoginInterceptor()); //也可以不添加拦截的路径,这样默认所有的都拦截
// 拦截之后就是调用LoginInterceptor的preHandle方法
}
}
</code></pre>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/91"/><category term="notes"/><published>2024-03-19T05:35:30+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/90</id><title>Java学习笔记14:String类 ,StringBuffer以及StringBuilder</title><updated>2024-12-22T15:49:32.144797+00:00</updated><content type="html"><![CDATA[<h4>继承关系</h4>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/e055865d-2ff8-41c3-913d-94e306bccefc" alt="image" /></p>
<p>说明,可以串行化,数据可以网络传输,String对象可以比较相互比较大小</p>
<p>本质是一个final 类型的char 数组[ ]</p>
<h4>两种创建方式的不同</h4>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/a3c9bad4-cc97-467c-857c-71503730df20" alt="image" />
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/e83681d6-5375-464f-b0b3-e209d74b4e6c" alt="image" /></p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/3eb29267-14f1-48bf-8164-a21075de270c" alt="image" /></p>
<p>equal:比较值是否相等
== 比较地址是否相等</p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/5ddfe772-2ddb-43c8-a547-e255d137d145" alt="image" /></p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/af2873b3-9dfb-4866-87ab-6aa4fcf2c7c0" alt="image" /></p>
<p>注意这里的方法 String.inner 返回的是常量池的地址。</p>
<p>字符串的特性:
其实是创建了两个常量池对象
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/6054a501-9ab8-48c9-97f4-cd859ede7f2c" alt="image" />
<strong>这里进行了优化,直接创建了一个</strong>
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/d4028aae-1885-404e-b5e7-12aaf6a6c2ac" alt="image" /></p>
<p><strong>常量相加,直接在池中;变量相加,在堆中</strong>
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/c1d47706-1087-450b-b000-9e3f6b3d40ab" alt="image" /></p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/b4170a28-8027-4108-a04a-91c0e23da88c" alt="image" /></p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/f89beb90-7214-4501-8393-776355aae8c9" alt="image" /></p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/90"/><category term="notes"/><published>2024-03-18T15:42:26+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/89</id><title>Java学习笔记13:包装类</title><updated>2024-12-22T15:49:32.315343+00:00</updated><content type="html"><![CDATA[<h4>什么是包装类</h4>
<p>即八大基本类型的封装类,为了用类的方法</p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/1a1ac88b-c24b-450a-99bd-afb34352e6dc" alt="image" /></p>
<h4>自动装箱和自动拆箱:</h4>
<p>本质上就是实现了自动的将包装类型与基本类型的转换,底层调用的还是之前的方法,只是自动调用了,省去了手动调。</p>
<p>自动装箱:将基本类转化成包装类</p>
<pre><code>//自动装箱 int->Integer
int n2 = 200;
Integer integer2 = n2 // 完成了将n2变成了包装类,底层本质调用的还是 Integer.valueof(n2)
</code></pre>
<p>自动拆箱:将包装类转换成基本数据类型</p>
<pre><code>//自动拆箱 Integer->int
int n3 = integer2 //底层仍然使用的是 intValue()方法
</code></pre>
<p><strong>三元运算符与等价的if else的区别:</strong></p>
<p>三元运算符是作为整体来看的,suo所以第一种情况下,精度提升为Double,1==> 1.0</p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/870fe21b-4fdc-4552-841c-408bae34938e" alt="image" /></p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/89"/><category term="notes"/><published>2024-03-18T11:44:17+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/88</id><title>Springboot学习笔记:@RequestMapping</title><updated>2024-12-22T15:49:32.498530+00:00</updated><content type="html"><![CDATA[<p>一句话介绍:@RequestMapping就是用来做路由映射的,即在Controller中,处理url地址以及前端发送的方法,进一步转到不同的方法中进行下一步的处理。</p>
<p>(补充:当然不仅限于URL路径,还可以设置(可选地)请求方法(如GET、POST等)、请求参数、请求头等条件)</p>
<pre><code>@RequestMapping(value = "/users", method = RequestMethod.GET)
public List<User> getUsers() {
// 方法体,返回用户列表
}
@RequestMapping(value = "/users", method = RequestMethod.POST, consumes = "application/json")
public User addUser(@RequestBody User user) {
// 方法体,添加一个新用户
}
</code></pre>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/7eb5d7e0-83fe-4354-9206-1618ee109fc8" alt="image" />
1.@RequestMapping 默认post、get请求均可以,可以在后面写上具体的方法,也可以直接用另一种等价的写法:
@PostMapping 和@GetMapping</p>
<ol start="2">
<li>用实体来接受形参时:注意请求发送的形式不同:请求体(body)和URL查询参数传递数据
具体可参考 #87 </li>
</ol>
<pre><code> @RequestMapping("/Entiy")
public String entity( User user){
System.out.println(user);
return "实体类接收参数";
}
@RequestMapping("/Entiy2")
// 如果前端传递的参数是json格式的,
// 那么可以使用@RequestBody
public String entity2(@RequestBody User user){
System.out.println(user);
return "实体类接收参数Json";
}
</code></pre>
<p>3.关于传参接收以及实体</p>
<h4>多个参数自动装箱(boxing)成一个JavaBean</h4>
<ul>
<li>
<p>什么是javaBean:一种特殊的Java类。</p>
<ul>
<li>所有的成员变量都是私有的private的</li>
<li>有一个不带参数的构造函数</li>
<li>通过一组get、set函数来读取或者修改属性的值</li>
<li>以上可以通过右键-生成-来对应生成</li>
</ul>
</li>
<li>
<p>实体Bean:EntityBean</p>
<ul>
<li>跟数据库的表可以实现一一对应</li>
<li>Bean的名字,与表的名字完成相同(Emp)</li>
<li>Bean中的属性名,与表的字段名相同(empno、ename、hiredate、sal)</li>
<li>属性的类型,与表中字段的类型兼容</li>
<li>实体Bean的一个实例(instance)对应数据库数据表中的一条记录</li>
</ul>
</li>
<li>
<p>JDO:Java Data Obiect : java与关系数据库的关系</p>
<ul>
<li>Data:数据库中的内容,永久存在数据库中的。</li>
<li>Object:JAvaBean的实例,存放在内存中。</li>
<li>持久化操作,将内存上的东西存入到数据库中</li>
</ul>
</li>
<li>
<p>装箱过程</p>
<ul>
<li>Step1:读取URL请求参数列表</li>
</ul>
</li>
</ul>
<pre><code class="language-http">h5?empno=11&sal=1000&hiredate=2022-2-22
</code></pre>
<ul>
<li>setp2:如果函数形参是一个JavaBean,系统会自动调用该Javabean的一组set函数,来实现属性的赋值。这个过程称为自动装箱</li>
</ul>
<pre><code class="language-java"> @ResponseBody
@RequestMapping("h5")
public String h5(Emp emp)
{
return "<h1>"+ emp + "</h1>";
}
</code></pre>
<p>前提是该javaBean中有相应的属性</p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/88"/><category term="notes"/><published>2024-03-18T05:55:53+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/87</id><title>Springboot学习笔记:@Controller、@RestController以及@RequestBody</title><updated>2024-12-22T15:49:32.667843+00:00</updated><content type="html"><![CDATA[<h3>1.@Controller与@RestController</h3>
<p>涉及MVC模型:</p>
<h5>MVC模型</h5>
<ul>
<li>M:model,模型层,和数据库打交道。《==MyBatis</li>
<li>V:view,视图层。用户看到的页面结果。 《== Thymeleafs模板语言/前后端分离项目中返回的数据(多是JSON)</li>
<li>C:controller,控制层。实现业务逻辑:数据的处理和页面的跳转。《==Spring MVC</li>
</ul>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/bda0a2d2-fe25-4057-b9f9-57b754b968ed" alt="image" /></p>
<p>控制器中两种注解:</p>
<h5>@Controller与@RestController</h5>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/478d0d60-2b56-4076-abf4-1a756425f494" alt="image" /></p>
<blockquote>
<p>在前后端分离的项目中,后端主要往前端返回的是数据,所以用RestController,
而在前后端不分离的项目时,多用Controller返回的是页面,结合Thymeleaf使用的,此时是返回页面,寻找的是页面。</p>
</blockquote>
<p>@Controller 是返回页面和数据的,当我们只用Controller的时候,默认是找的页面,比如下面是找hello页面了(前后端 不分离的项目)
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/087ac14c-138d-4a4f-8d55-123043e33a88" alt="image" /></p>
<p>如果想返回数据,而不是页面呢?
需要加上@RequestBody</p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/eb42e352-fcc6-4699-82fc-0e3ab8fdd84f" alt="image" /></p>
<h5>@RestController=@Controller和@ResponseBody的结合</h5>
<p>当你使用@RestController注解时,Spring会自动处理你的类中的所有方法,使其返回的数据直接作为HTTP响应的正文返回给客户端,而不需要你在每个方法上单独标注@ResponseBody。</p>
<p>@RestController注解是@Controller和@ResponseBody的结合,这意味着它既将类标记为控制器,又表明类中的所有方法都会自动以@ResponseBody的方式处理。这使得@RestController非常适合用于构建RESTful API,其中所有的响应都是数据(如JSON或XML),而不是视图或模板页面。</p>
<p>这种方式简化了开发过程,因为你不需要在每个方法上重复使用@ResponseBody注解,从而让代码更加简洁和直观。总的来说,如果你的应用主要是服务于HTTP API的,使用@RestController会更方便。</p>
<p>前后端分离项目中,主要使用的就是:<strong>@RestController</strong></p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/87"/><category term="notes"/><published>2024-03-18T04:49:55+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/86</id><title>SpringBoot学习笔记:与数据库打交道的方式(MyBatis和JPA)</title><updated>2024-12-22T15:49:32.857185+00:00</updated><content type="html"><![CDATA[<blockquote>
<p>之前的项目是用的Mybatis,新的项目是用到了JPA(Java Persistence API),两者均是跟数据库相关的,比较好奇两者的区别,整理部分资料。</p>
</blockquote>
<h3>为什么要用Mybatis或者JPA?</h3>
<p>涉及到几个概念:</p>
<p>数据持久化和ORM
1.数据持久化:是指将内存中的数据保存到持久化存储(如数据库)中,以便数据在程序结束后仍然存在并可以再次被访问。</p>
<p>2.对象关系映射(ORM):是一种在关系数据库和对象之间进行映射的技术,允许开发者使用面向对象的方式来操作数据库。ORM技术抽象了数据库操作的复杂性,开发者无需直接编写繁琐的SQL语句,即可进行数据操作。</p>
<p>**关系型数据库:**以ER(实体-关系)模型为基础,如MySQL、SQLServer、Oracle等。它们通过表结构(实体)、字段(属性)和表间关系(一对一、一对多、多对多)来组织数据,以及通过SQL语言进行数据的查询和操作。</p>
<ul>
<li>实体:对应数据库中的表。</li>
<li>关系:表与表之间的连接,如一对一、一对多、多对多。</li>
<li>关系运算:如选择(查询特定条件的记录)和投影(选择特定列)。</li>
</ul>
<p><strong>面向对象编程</strong>:如Java、C++、Python等语言,它们通过类、对象、继承和多态等概念来组织和操作数据。</p>
<ul>
<li>类:定义了对象的结构和行为。</li>
<li>继承与引用:允许类之间的关系和数据的重用。</li>
</ul>
<p>使用ORM框架如MyBatis或JPA,可以高效地管理数据持久化过程和对象关系映射,同时降低数据库操作的复杂性。MyBatis提供了更细粒度的控制,通过手写SQL配合对象映射,适合对SQL性能和灵活性有高要求的场景。而JPA提供了一套更高层次的抽象,通过注解和JPQL(Java Persistence Query Language)来实现自动的SQL生成和查询,适合希望快速开发且不需要深入优化SQL的应用。</p>
<p>通过这种方式,开发者可以专注于业务逻辑的实现,而不是数据库操作的细节,提高开发效率和系统的可维护性。</p>
<h3>Mybatis和JPA之间的区别:</h3>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/4e3c861f-2418-4ae3-b229-253c8a44accb" alt="image" /></p>
<p>这里我的理解是:
1.MyBatis更多的控制,尤其是可以直接写sql语句,而JPA则是封装成标准的控制方法了。
”MyBatis提供了对SQL的精细控制,而JPA则通过标准化的ORM模型来简化数据访问。“</p>
<p>2.分层设计:</p>
<ul>
<li>JPA多一层service,实现数据库访问逻辑和业务逻辑的分开,代码结构更清楚</li>
<li>Mybatis则是访问逻辑和业务逻辑均放在Mapper层(DAO层)</li>
</ul>
<h3>在MVC中的体现</h3>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/f724ece8-e56a-4fd8-8c20-8e6b5756b8e5" alt="image" /></p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/6cb6191b-544a-4602-8e68-8ccbc4610a7e" alt="image" /></p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/86"/><category term="notes"/><published>2024-03-16T05:48:39+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/85</id><title>第一次技术面试复盘</title><updated>2024-12-22T15:49:33.033916+00:00</updated><content type="html"><![CDATA[<p>下午刚刚结束了学计算机以来的第一次技术面试,给自己打个6/10分吧。</p>
<p>结果大概一周左右出来,第一次正式的技术面试,算是两年的转码学习以来迈出的第一步了。</p>
<p>趁着结果还没出来,趁着现在还不至于被不好的结果吓到:),记忆还算鲜活,写下一些面试复盘,也算是对近期学习复习的一个总结。</p>
<p>先说这次面试好的方面:
<strong>1.主动出击,扬长避短</strong>
讲了不少自己的做过的优势项目,或者说自己算熟悉的领域;不至于冷场,没有多少话讲。
这里主要讲了自己做的毕设项目,以及之前做过的动态页面展示网站,Vue的小项目。
这里的启发大概是:苍蝇腿也是腿,自己其实在学习过程中,做了不少的项目了,有些不善于总结和归纳,有些半途而废(比如之前用ts做的在线聊天的系统;未完成的扇贝单词项目等等)</p>
<p>但好在也还算积累了一点项目(虽说在写简历时自己也觉得没眼看,太简陋了点),总比什么也没有强。</p>
<p>这对于完美主义者来说,我想起了那句至理名言:<strong>先完成,再完美。我们现在先去试着做一百个失败的项目吧:)总比迟迟不动手要好。</strong>
第二点启发是,编程需要沉淀,平时付出的努力总会在将来某一天有用的。</p>
<p>2.对自己做过的项目还算熟。
这大概得一分为二来看了,对前端自己付出很多时间得项目,自然是熟一点,以及涉及到LLM模型,自己花时间整理,思考得东西,肯定是熟,能思考,能引申。但是对于后端得项目,说不上很熟,甚至一些基础的地方也卡住了。</p>
<p>不好的地方:
1.面试前太焦虑
2.基础知识点不牢固
3.明知道是重点需要复习的地方,依然没有好好复习。</p>
<p>大概是因为要第一次技术面试的原因,深感自己不足,觉得自己面试肯定会被各种无情的拷打,所有就各种的焦虑,但又格外的珍惜这次面试的机会,结果就是搞到自己焦虑不断,内耗严重。</p>
<p>想抓紧时间弥补自己的不足,又一边学一边焦虑自己怎么还这么多没有弄明白。结果就是面试紧迫感激发出来的高斗志只维持了不到几天,剩下的时间一边焦虑一边学,甚至只焦虑不学。</p>
<p>本可以按计划的话多学一点,那至少做的再好一点的。</p>
<p>同样,很多焦虑担忧的事情也没有发生:面试官超级耐心,听完了我介绍的项目,即使是很简单的项目也耐心听完了。同时,根据我的项目,针对性的提问了我许多的东西。并不是像一个考官,一定要判出个对错,很多时候像是耐心的导师,像是一个朋友,在一块探讨方案。</p>
<p>(第一次技术面试,但根据我之前看到的帖子,大概很少有这样耐心的面试官吧)</p>
<p>不知道自己能不能足够幸运面试通过了,但足够幸运获得了这次面试的机会,一是,虽然让我 在焦虑不安中度过了差不多一星期,但也是在这一星期复习了差不多以往要一个月才复习完的东西;二是,这次面试机会收获了陌生人的善意,遇到了很好的面试官,同时也对我的自身技术有了进一步的认识,该弥补的地方抓紧弥补,该加强的地方赶紧加强。</p>
<p>最重要的启发是:担心焦虑的大部分事,不会发生的,行动起来,付出总会有痕迹的。</p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/85"/><category term="daily"/><published>2024-03-07T10:57:52+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/84</id><title>从研究生退学之后的两年</title><updated>2024-12-22T15:49:33.223412+00:00</updated><content type="html"><![CDATA[<blockquote>
<p>本文原本是某天心血来潮搜自己的名字,无意间发现了某项专利竟然挂着自己的名字,遂点进去看了下,竟是自己在本科实验时做的工作,当时提出的理论设想被导师和师妹实现了,发了专利,竟然还把我的名字也挂上了。 感慨良多,又想到自己已经是研究生退学转行计算机快两年了,没想到两年的时间竟然能发生这么多的事情,有时也不禁会想,如果当初留在原来的学校继续读研而不是非得去一个985,恐怕命运又将把我带向另一条路了,于是写下了这篇半叙半议的文字,现在看来,也可以当成对过去两年的一点总结吧。</p>
</blockquote>
<p>当你高强度的搜索自己的名字时:浏览器里藏着你过去的历史</p>
<p>本来是打算github换一个名字的,因为用的是全名,且google一搜第一个就是我的主页,总觉得这样不太安全,万一哪天也被开盒罚个50w怎么办(背景承德程序员因远程工作被罚50w)。</p>
<p>但突发奇想试了一下,如果浏览器搜的是中文会怎么样?</p>
<p>结果过去的种种皆在,曾经中二写的《简书》,现在再看根本读不下去了;还有毕业后投了两年经历了修改无数次后投的期刊,前段时间见刊,也成了记录的一部分。但后面我的经历,又觉得意义也不大了。
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/8da432a0-ccb2-4320-b50a-c1de9142b81f" alt="image" /></p>
<p>还有大学期间参加的种种活动,前两年是在新闻部写新闻,后面两年慢慢出现在新闻里(参加了各种项目玩),疫情期间在家没事干拍照参加摄影作品评选,后面大四考研录取之后参加乒乓球比赛.....
现在想想,真是一段轻松惬意的好时光啊。</p>
<p>另一个主题则是研究生与退学了。
浏览器里也在忠实的记录着我发生的一切,从最初的拟录取名单公布,到在自己学院的分享考研经验,到后面的退学,完整的记录着过去发生的一切。我想倘若有人想了解我的过往,上网一搜也大概能画一个流程图了。
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/7631b38a-d703-44cc-875f-0753df059828" alt="image" /></p>
<p>当然,甚至还有不期而遇的小惊喜,搜到了一个有我参与的专利,有点疑惑,没记得参与过什么项目的啊,点进去一看:熟悉的老师们,还有师妹。原来导师悄悄把我的名字也放上去了,曾经努力的项目被人记得的感觉真好。</p>
<p>仔细看了一下,真挺不错的,在我毕业离开实验室后,师妹还有老师们把我们当初设想要做的想法,吹下的牛,都实现了,我当时在文献中看到的美国产品,他们现在已经做成了足够和它媲美的产品了。</p>
<p>【看到这还是很感慨,当时我临近毕业,成型的项目试验了多次怎么也达不到完美的效果,觉得要想做出来恐怕遥遥无期了,周老师当时还邀请我留下来读研继续做下去,我心想万一我两三年搞不出来呢。】今天得知大家做出来了,还是很兴奋的,我毕业的时候师妹才大二吧,也是差不多两年左右的时间,就做出了了不起的成果,向老师和师妹致敬。</p>
<p>两年的时间说长不长,说短也不短的。差不多两年前的这个时候,我刚迎来我研究生的第一个学期,但差不多也是这个时候左右,退学的想法最强烈了。读了研之后,我发现自己迷失了。我找不到了自己本科时候要追求的东西了,那种一想到要去做我的项目就会兴奋的点了。</p>
<p>当时本科二年级和三年级的时候,读英文的文献就像看小说一样,看了一篇又一篇,基本上把这个领域国外的论文看了个遍;但读研之后,或许是当时太着急了,或许是自己给自己太多压力了,总是进入不了状态,又天天被师兄安排的各种琐事所困,当时最大的怨恨大概是想:为什么我付出了那么多的努力,考了那么高的分,来了这就只能天天种小麦? 那这样还不如回我原来的学校继续搞我的项目?</p>
<p>大约是在我退学几个月后,因为需要调档案的原因,不得不跟之前一个关系很好的老师打电话,老师很是惋惜,对我说,你啊你,就是太认真了,太认死理了,你为什么不退学之前找我们聊聊呢......</p>
<p>大概是太年少轻狂、太心高气傲了?可我从考研到后来一直被灌输的就是那个理念,一直在不断地被追问:你的创新点是什么?你的研究意义是什么?你为什么要做这个?</p>
<p>于是回到现实中,我发现我找不到了我读研的研究意义了,更找不到生活的意义了,就像是某种价值观的格格不入,命运齿轮的严重错位。</p>
<p>在趁着我这台机器彻底失控之前,我退学了。
想起之前看到的一句话,读研只有录取和毕业的那一瞬间是快乐的。
但我体验到了不同的快乐,出成绩时看到自己380多分排第一,就兴奋到上了天,复试结束拿到录取通知书的时候又感受到了一次快乐,当时心想,期待的研究生生活就要来了。
剩下的一次轻松,就是退学时回家的路上了。但当时看着两个好朋友送我离开车站,心想着也许以后很难再见到了,心里还是很难过。这次短暂的读研之旅,遇到了两个非常好的朋友算是最大的收获了。</p>
<p>退学后的日子并不像想象中的顺利,少了许多内心的挣扎的同时,又增添了一些“非得要证明自己当初退学的选择没有错”的压力。</p>
<p>从一个二本,考上了985研究生,又退学,重新回到了一个二本学校,不知道该怎么论了,也许从外人的眼里,这怎么也有点脑袋抽了,想不明白为什么要这么做。过去某段时间,我也在跟内心作斗争,一定要怎样怎样,向所有人证明自己的选择没有错。</p>
<p>这很挣扎,感觉就像每天背着枷锁在生活。后来我慢慢想明白了,我想起大二上《武侠风景》课上老师讲金庸小说里的一句话:那都是很好很好的,可是我偏不喜歡。</p>
<p>我用不着向别人证明自己了,别人也没那么在意你的选择,没有后悔离开那里,应该就是对自己当初内心选择最好的证明了。</p>
<p>另一个原因可能在于,太容易得到的,反而不容易珍惜了?
虽然我备考的过程是很艰辛的,但是在我上岸之后,截至到今年24这一届,我又连续辅导了三届的考生。差不多每一年,我出的模拟题,都能猜到西农的原题至少60%左右了(22年甚至差不多到了80%),剩下的知识点猜不到原题也基本看一眼就知道是考的什么了。</p>
<p>大概是这种心理也起到了一点作用吧。</p>
<p>今年秋招一开始找工作的时候特别焦虑,一度不知道自己要干什么了。有一个Hr问我,你应该问问自己到底擅长什么,然后去做。</p>
<p>我当时想的是,我擅长考试啊,又擅长辅导别人,我自己考第一也辅导过别人考第一,我知道从学不会到学会的过程是什么样的,我知道他们在考什么。</p>
<p>Hr说,那你就去做这个啊,你应该开辅导机构的,就做你擅长的就好了。</p>
<p>可我心理总迈不过这个槛,不敢跟学生讲我退学了,不敢面对学生的疑惑。</p>
<p>但或许另一个槛在于,我总不能一直和那个学校原来的专业打交道吧,那我退学的意义和初衷又在哪里呢?</p>
<p>现在我想我又找到了自己的方向了,虽说现在已经是计算机专业就业的寒冬了,但另一方面大语言模型各种AI的涌现,又在孕育着各种的机会。</p>
<p>我想起两年前研究生复试的时候,老师问我,你这个高岭土喷到室外应用的效果如何时,我回答说目前还只是在室内的理论性验证,将来我们实验室的研究方向是室外领域。</p>
<p>现在,我们室外也可以了。</p>
<pre><code> 写于2023年12.30
</code></pre>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/84"/><category term="daily"/><category term="Top"/><published>2024-02-28T04:36:24+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/83</id><title>Java的一些基础知识点复习</title><updated>2024-12-22T15:49:33.415259+00:00</updated><content type="html"><![CDATA[<p><strong>方法的重载 overload</strong></p>
<p>定义:一个类中方法名字相同,但是参数列表不同的方法。</p>
<blockquote>
<p>注意:重载的方法,就是不同的方法,只是名称相同而已。
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/43049d4c-3ac2-4c06-9c3a-631973c2d9a4" alt="image" /></p>
</blockquote>
<ul>
<li>形参的数量不同</li>
<li>形参的类型不同
均可以构成方法的重载(也就是说是不同的方法)</li>
</ul>
<pre><code> static void add(){
}
static void add(int a,int b)
{
System.out.println(a+b);
}
static void add(double a,double b)
{
System.out.println(a+b);
}
</code></pre>
<blockquote>
<p>当返回值不同时,但形参形同时,无法构成 </p>
</blockquote>
<pre><code> static int add(int a,int b,int c){
System.out.println(a+b+c);
return a+b+c;
}
static double add(int a,int b,int c){
System.out.println(a+b+c);
return a+b+c;
}
</code></pre>
<p><strong>方法的调用机制</strong></p>
<ul>
<li>当程序执行到方法时,会在栈中单独开一个空间(栈空间)</li>
<li>执行完毕,或者执行到return语句后,就会返回到 <strong>调用方法的地方</strong></li>
<li>同理,main方法栈执行完毕之后,栈空间也会回收,整个程序退出</li>
</ul>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/f6d6fb3a-07e1-4b87-85bc-f776e64eaa93" alt="image" /></p>
<p><strong>方法的传参</strong></p>
<ul>
<li>基本数据类型传参:形参不影响实参的传递(本质上栈中main方法区与swap方法区是两个区,两者不会相互影响)</li>
<li>引用数据类型传参:传递过程传递的其实是地址,所以栈方法指向的空间和main主方法指向的空间是一致的
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/3b3a049a-b833-4856-9781-fcaf129b8274" alt="image" /></li>
</ul>
<p><strong>可变参数</strong></p>
<p>Java中允许同一个类中多个<strong>同名</strong> <strong>同功能</strong>但是<strong>参数个数不同</strong>的方法,封装成一个方法。</p>
<p>==>对方法重载的一种优化,不用因为参数个数不同而写多个方法了
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/a287a282-f311-40a2-84ca-37850136dafb" alt="image" /></p>
<p>可以把传入的参数nums 视为数组</p>
<pre><code> public int getSum(int... nums) {
System.out.println("参数的个数" + nums.length);
int tolNums = 0;
for (int i = 0; i < nums.length; i++) {
tolNums += nums[i];
}
return tolNums;
}
</code></pre>
<ul>
<li>可以直接传递一个数组</li>
<li>可变参数可以和普通类型参数放在一起传参,但是必须保证可变参数放在最后</li>
<li>一个形参列表只允许出现一个可变参数,不可以多个可变参数一块。</li>
</ul>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/83"/><category term="notes"/><published>2024-02-28T03:49:14+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/82</id><title>哈佛大学cs50x-cs50-full-stack全栈项目学习记录</title><updated>2024-12-22T15:49:33.586599+00:00</updated><content type="html"><![CDATA[<p>项目仓库地址:<a href="https://github.com/QiYongchuan/cs50-full-stack">https://github.com/QiYongchuan/cs50-full-stack</a></p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/82"/><category term="Top"/><category term="项目记录"/><published>2024-02-24T13:53:39+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/81</id><title>JavaScript Full Course - Beginner to Pro</title><updated>2024-12-22T15:49:33.768817+00:00</updated><content type="html"><![CDATA[<p>Function
why we use function?
let us reuse code</p>
<p>return与parameter的区别
<img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/0f4ec351-3a90-49d3-a059-3b29ad179989" alt="image" /></p>
<p>存储在对象中的函数,也称为方法。
比如:console是对象,console.log则是方法(function)</p>
<p>内置对象 Json与localStorage</p>
<p><img src="https://github.com/QiYongchuan/MyGitBlog/assets/105039020/0db54f33-2378-4d33-beb3-b4a20eda82ed" alt="image" /></p>
]]></content><link href="https://github.com/QiYongchuan/MyGitBlog/issues/81"/><category term="notes"/><published>2024-02-22T06:10:35+00:00</published></entry><entry><id>https://github.com/QiYongchuan/MyGitBlog/issues/80</id><title>Django学习记录:如何创建一个项目</title><updated>2024-12-22T15:49:34.208866+00:00</updated><content type="html"><![CDATA[<h1>Django</h1>
<h3>一、创建项目的流程</h3>
<p>1.创建整体项目-项目名称</p>
<pre><code>django-admin startproject airline
</code></pre>
<p>2.进入项目文件夹,创建相应的应用</p>
<pre><code>cd airline
python manage.py startapp flights
</code></pre>
<p>3.创建完成后,在项目文件夹的setting中增加新建好的应用</p>
<pre><code>--airline
--settings.py
# Application definition
INSTALLED_APPS = [
"flights",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
</code></pre>
<p>4.在项目文件夹的urls.py中设置页面的跳转逻辑</p>
<pre><code>--airline
--urls.py
from django.contrib import admin
from django.urls import include,path
urlpatterns = [
path("admin/", admin.site.urls),
path("flights/",include("flights.urls"))
]
</code></pre>
<p>5.在创建的应用文件夹(flights)中,创建urls.py</p>
<pre><code>from django.urls import path
from . import views
urlpatterns = []
</code></pre>
<ol start="6">
<li>models.py </li>
</ol>
<p>用来控制SQL,在django中</p>
<pre><code># Create your models here.
class Flight(models.Model):
origin = models.CharField(max_length=64)
destination = models.CharField(max_length=64)
duration = models.IntegerField()
</code></pre>
<p>在命令行中:</p>
<pre><code>python manage.py makemigrations
显示:
Migrations for 'flights':
flights\migrations\0001_initial.py
- Create model Flight
其中生成的文件中0001——initial.py描述的就是Django如何操控数据库的
operations = [
migrations.CreateModel(
name="Flight",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("origin", models.CharField(max_length=64)),
("destination", models.CharField(max_length=64)),
("duration", models.IntegerField()),
],
),
]
</code></pre>
<p>继续敲命令</p>
<pre><code>python manage.py migrate
当查看文件夹时,db.sqlite3创建成功
</code></pre>
<p>继续输命令:</p>
<pre><code>python manage.py shell
可以用python的语法直接操控数据库
from flights.models import Flight
f = Flight(origin = "New York",destination="London",duration=415)
f.save()
上述命令相当于插入
Flight.objects.all()
<QuerySet [<Flight: Flight object (1)>]>
// 查询命令
可以在python的命令行中,就相当于可以在python的代码中执行。
</code></pre>