-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
436 lines (351 loc) · 39.6 KB
/
index.html
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
<!DOCTYPE html><html lang="zh-CN" data-theme="light"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover"><title>TechNotes</title><meta name="author" content="TechNotes"><meta name="copyright" content="TechNotes"><meta name="format-detection" content="telephone=no"><meta name="theme-color" content="ffffff"><meta name="description" content="Stay hungry.Stay foolish.">
<meta property="og:type" content="website">
<meta property="og:title" content="TechNotes">
<meta property="og:url" content="http://techniquenotes.github.io/index.html">
<meta property="og:site_name" content="TechNotes">
<meta property="og:description" content="Stay hungry.Stay foolish.">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://techniquenotes.github.io/img/avatar.png">
<meta property="article:author" content="TechNotes">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://techniquenotes.github.io/img/avatar.png"><link rel="shortcut icon" href="/img/favicon.png"><link rel="canonical" href="http://techniquenotes.github.io/index.html"><link rel="preconnect" href="//cdn.jsdelivr.net"/><link rel="preconnect" href="//busuanzi.ibruce.info"/><link rel="stylesheet" href="/css/index.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css" media="print" onload="this.media='all'"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox/fancybox.min.css" media="print" onload="this.media='all'"><script>const GLOBAL_CONFIG = {
root: '/',
algolia: undefined,
localSearch: undefined,
translate: undefined,
noticeOutdate: {"limitDay":730,"position":"top","messagePrev":"It has been","messageNext":"days since the last update, the content of the article may be outdated."},
highlight: {"plugin":"highlighjs","highlightCopy":true,"highlightLang":true,"highlightHeightLimit":200},
copy: {
success: '复制成功',
error: '复制错误',
noSupport: '浏览器不支持'
},
relativeDate: {
homepage: false,
post: false
},
runtime: '天',
dateSuffix: {
just: '刚刚',
min: '分钟前',
hour: '小时前',
day: '天前',
month: '个月前'
},
copyright: {"limitCount":0,"languages":{"author":"作者: TechNotes","link":"链接: ","source":"来源: TechNotes","info":"著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。"}},
lightbox: 'fancybox',
Snackbar: undefined,
source: {
justifiedGallery: {
js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.js',
css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery/dist/fjGallery.min.css'
}
},
isPhotoFigcaption: false,
islazyload: false,
isAnchor: false,
percent: {
toc: true,
rightside: true,
}
}</script><script id="config-diff">var GLOBAL_CONFIG_SITE = {
title: 'TechNotes',
isPost: false,
isHome: true,
isHighlightShrink: false,
isToc: false,
postUpdate: '2024-03-27 15:51:32'
}</script><noscript><style type="text/css">
#nav {
opacity: 1
}
.justified-gallery img {
opacity: 1
}
#recent-posts time,
#post-meta time {
display: inline !important
}
</style></noscript><script>(win=>{
win.saveToLocal = {
set: function setWithExpiry(key, value, ttl) {
if (ttl === 0) return
const now = new Date()
const expiryDay = ttl * 86400000
const item = {
value: value,
expiry: now.getTime() + expiryDay,
}
localStorage.setItem(key, JSON.stringify(item))
},
get: function getWithExpiry(key) {
const itemStr = localStorage.getItem(key)
if (!itemStr) {
return undefined
}
const item = JSON.parse(itemStr)
const now = new Date()
if (now.getTime() > item.expiry) {
localStorage.removeItem(key)
return undefined
}
return item.value
}
}
win.getScript = url => new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = url
script.async = true
script.onerror = reject
script.onload = script.onreadystatechange = function() {
const loadState = this.readyState
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
script.onload = script.onreadystatechange = null
resolve()
}
document.head.appendChild(script)
})
win.getCSS = (url,id = false) => new Promise((resolve, reject) => {
const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = url
if (id) link.id = id
link.onerror = reject
link.onload = link.onreadystatechange = function() {
const loadState = this.readyState
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
link.onload = link.onreadystatechange = null
resolve()
}
document.head.appendChild(link)
})
win.activateDarkMode = function () {
document.documentElement.setAttribute('data-theme', 'dark')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d')
}
}
win.activateLightMode = function () {
document.documentElement.setAttribute('data-theme', 'light')
if (document.querySelector('meta[name="theme-color"]') !== null) {
document.querySelector('meta[name="theme-color"]').setAttribute('content', 'ffffff')
}
}
const t = saveToLocal.get('theme')
if (t === 'dark') activateDarkMode()
else if (t === 'light') activateLightMode()
const asideStatus = saveToLocal.get('aside-status')
if (asideStatus !== undefined) {
if (asideStatus === 'hide') {
document.documentElement.classList.add('hide-aside')
} else {
document.documentElement.classList.remove('hide-aside')
}
}
const detectApple = () => {
if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){
document.documentElement.classList.add('apple')
}
}
detectApple()
})(window)</script><link rel="stylesheet" href="/css/custom.css"><meta name="generator" content="Hexo 6.3.0"></head><body><div id="web_bg"></div><div id="sidebar"><div id="menu-mask"></div><div id="sidebar-menus"><div class="avatar-img is-center"><img src="/img/avatar.png" onerror="onerror=null;src='/img/friend_404.gif'" alt="avatar"/></div><div class="sidebar-site-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">33</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">4</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">12</div></a></div><hr/><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> Home</span></a></div><div class="menus_item"><a class="site-page" href="/tools/"><i class="fa-fw fa fa-tools"></i><span> Tools</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fa fa-archive"></i><span> Categories</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fa fa-tags"></i><span> Tags</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fa fa-folder-open"></i><span> Archives</span></a></div></div></div></div><div class="page" id="body-wrap"><header class="full_page" id="page-header" style="background-image: url('/img/favicon.png')"><nav id="nav"><span id="blog-info"><a href="/" title="TechNotes"><span class="site-name">TechNotes</span></a></span><div id="menus"><div class="menus_items"><div class="menus_item"><a class="site-page" href="/"><i class="fa-fw fas fa-home"></i><span> Home</span></a></div><div class="menus_item"><a class="site-page" href="/tools/"><i class="fa-fw fa fa-tools"></i><span> Tools</span></a></div><div class="menus_item"><a class="site-page" href="/categories/"><i class="fa-fw fa fa-archive"></i><span> Categories</span></a></div><div class="menus_item"><a class="site-page" href="/tags/"><i class="fa-fw fa fa-tags"></i><span> Tags</span></a></div><div class="menus_item"><a class="site-page" href="/archives/"><i class="fa-fw fa fa-folder-open"></i><span> Archives</span></a></div></div><div id="toggle-menu"><a class="site-page" href="javascript:void(0);"><i class="fas fa-bars fa-fw"></i></a></div></div></nav><div id="site-info"><h1 id="site-title">TechNotes</h1><div id="site-subtitle"><span id="subtitle"></span></div><div id="site_social_icons"><a class="social-icon" href="https://github.com/techniquenotes" target="_blank" title="Github"><i class="fab fa-github" style="color: #24292e;"></i></a><a class="social-icon" href="mailto:[email protected]" target="_blank" title="Email"><i class="fas fa-envelope" style="color: #4a7dbe;"></i></a></div></div><div id="scroll-down"><i class="fas fa-angle-down scroll-down-effects"></i></div></header><main class="layout" id="content-inner"><div class="recent-posts" id="recent-posts"><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2024/03/27/SpringSecurity/SpringSecurity%E5%BA%9F%E5%BC%83WebSecurityConfigurerAdapter%E5%90%8E%E9%85%8D%E7%BD%AE/" title="SpringSecurity废弃WebSecurityConfigurerAdapter后配置">SpringSecurity废弃WebSecurityConfigurerAdapter后配置</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time class="post-meta-date-created" datetime="2024-03-27T06:58:06.868Z" title="发表于 2024-03-27 14:58:06">2024-03-27</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-03-27T07:03:09.094Z" title="更新于 2024-03-27 15:03:09">2024-03-27</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/SpringSecurity/">SpringSecurity</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/Tutorial/">Tutorial</a></span></div><div class="content">ApplicationConfiguration.java12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849package com.example.springsecurity.config;import com.example.springsecurity.dao.UserMapper;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.authentication.AuthenticationProvider;import org.springframework.securi ...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2024/03/27/SpringSecurity/SpringSecurity%E6%9F%A5%E7%9C%8B%E8%BF%87%E6%BB%A4%E5%99%A8%E9%93%BE/" title="SpringSecurity查看过滤器链">SpringSecurity查看过滤器链</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time class="post-meta-date-created" datetime="2024-03-27T06:51:08.965Z" title="发表于 2024-03-27 14:51:08">2024-03-27</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-03-27T06:59:23.863Z" title="更新于 2024-03-27 14:59:23">2024-03-27</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/SpringSecurity/">SpringSecurity</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/Tutorial/">Tutorial</a></span></div><div class="content">配置 application.properties1#logging.level.org.springframework.security.web.FilterChainProxy=DEBUG
运行控制台打印出过滤器链信息
</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2024/03/27/Postgresql/%E4%BD%BF%E7%94%A8%20Mybatis%20%E5%90%91%20Postgresql%20%E6%8F%92%E5%85%A5%20UUID%20%E5%AD%97%E6%AE%B5/" title="使用 Mybatis 向 Postgresql 插入 UUID 字段">使用 Mybatis 向 Postgresql 插入 UUID 字段</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time class="post-meta-date-created" datetime="2024-03-27T05:54:02.759Z" title="发表于 2024-03-27 13:54:02">2024-03-27</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-03-27T06:03:47.869Z" title="更新于 2024-03-27 14:03:47">2024-03-27</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Postgresql/">Postgresql</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/">数据库</a></span></div><div class="content">数据库id 字段设置为 character varying
User 对象id 设置为 String 类型
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273package com.example.springsecurity.entity;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.userdetails.UserDetails;import java.util.Collection;import java.util.Date;import java.util.List;import java.util.UUID;public class User implements UserDetails { ...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2024/03/24/SpringSecurity/Spring%20boot%20+%20Postgresql%20%E5%AE%9E%E7%8E%B0%20JWT%20%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81/" title="Spring boot + Postgresql 实现 JWT 身份验证">Spring boot + Postgresql 实现 JWT 身份验证</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time class="post-meta-date-created" datetime="2024-03-24T12:44:52.227Z" title="发表于 2024-03-24 20:44:52">2024-03-24</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-03-24T14:13:12.026Z" title="更新于 2024-03-24 22:13:12">2024-03-24</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/SpringSecurity/">SpringSecurity</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/Tutorial/">Tutorial</a></span></div><div class="content">背景在不断发展的 Web 开发和应用程序安全领域,对强大身份验证机制的需求从未如此迫切。向公众公开 API 时,确保只有授权人员才能访问资源至关重要。
JSON Web Tokens (JWT) 是现代 Web 应用程序中最流行、最有效的身份验证方法之一。它提供了一种灵活、无状态的方式来验证用户身份并保护 API 端点;它也被称为基于 Token 的身份验证。
在本文中,我们将探讨在 Spring Boot 3 应用程序中实现 JWT 身份验证。
目标API 必须公开一些无需身份验证即可访问的路由,而另一些则需要身份验证。下表列举了这些路由:
AP 路由
访问状态
描述
[POST] /auth/login
未受保护
注册新用户
[POST] /auth/signup
未受保护
验证用户身份
[GET] /user
受保护
检索当前经过身份验证的用户
工具
JDK 21
Postgresql 16.2
SpringBoot 3.2.3
Mybatis
Maven
Spring Security 6.2.3
依赖 ...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2024/03/16/Angular/Angular_Chapter1/" title="Angular Chapter1">Angular Chapter1</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time class="post-meta-date-created" datetime="2024-03-16T14:36:38.096Z" title="发表于 2024-03-16 22:36:38">2024-03-16</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-03-16T14:37:32.373Z" title="更新于 2024-03-16 22:37:32">2024-03-16</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Angular/">Angular</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/Tutorial/">Tutorial</a></span></div><div class="content">1.1 设计原则和方法YAGNI
You Aren’t Gonna Need It
不写不需要的代码
DRY
Don’t Repeat Yourself
不要重复你自己的代码
OCP
OPen Close Principle
开闭原则,对扩展开放,对修改封闭
Low Coupling, High Cohesion
高聚合,低耦合
Dimeter Law
迪米特法则,“最少知识” 法则
一个对象/组件只负责必须的少量功能
</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2024/03/16/Angular/Angular_Chapter2/" title="Angular Chapter2">Angular Chapter2</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time class="post-meta-date-created" datetime="2024-03-16T14:36:38.096Z" title="发表于 2024-03-16 22:36:38">2024-03-16</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-03-16T14:37:51.472Z" title="更新于 2024-03-16 22:37:51">2024-03-16</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Angular/">Angular</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/Tutorial/">Tutorial</a></span></div><div class="content">2.1 Angular 概述AngularJS v1.x 官网:https://angularjs.org/
Angular v2.x~v8.x 官网:https://angular.io/
Angular中文镜像网站:https://angular.cn/
搭建Angular开发环境前提:Node.js V10.x 以上
12C:\Users\lenovo>node -vv18.19.0
下载并安装脚手架工具默认仓库:registry.npmjs.com
1npm i -g @angular/cli
运行脚手架工具创建空白项目1ng new myngapp01
最新版没有生成app.module.ts,修改命令
https://github.com/angular/angular/issues/52751
1D:\Angular_Learning\Project>ng new myngapp01 --no-standalone --routing --ssr=false
进入空白项目并运行开发服务器12cd myngapp01npm start
客户端访问测试 ...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2024/03/16/Angular/Angular_Chapter3/" title="Angular Chapter3">Angular Chapter3</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time class="post-meta-date-created" datetime="2024-03-16T14:36:38.096Z" title="发表于 2024-03-16 22:36:38">2024-03-16</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-03-16T14:40:34.431Z" title="更新于 2024-03-16 22:40:34">2024-03-16</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Angular/">Angular</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/Tutorial/">Tutorial</a></span></div><div class="content">3.1 模块Angular项目启动过程分析
angular.json:NG 项目的配置
index:./src/index.html <app-root></app-root>
brower:./scr/main.ts
main.ts:bootstrapModule(AppModule)
app.module.ts:bootstrap:AppComponent
app.component.ts :selector:'app-root'
templateUrl:'app.component.html
app.component.html:HTML片段
3.2 组件Angular 核心概念(一):模块
Module:不同于Node.js 或 ES6中的模块,NG 中的模块就是一个抽象的容器,用于对组件进行分组。
整个应用初始时有且只有一个主组件:AppModule
Angular 核心概念(二):组件
组件:是一段可以反复使用的页面片段,如页头 ...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2024/03/15/Java/%E7%AE%97%E6%B3%95/%E7%89%B9%E6%AE%8A%E7%AE%97%E6%B3%95/%E6%89%8B%E6%92%95%E4%BB%A3%E7%A0%81/" title="手撕代码">手撕代码</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time class="post-meta-date-created" datetime="2024-03-15T05:28:17.239Z" title="发表于 2024-03-15 13:28:17">2024-03-15</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-03-16T14:41:56.054Z" title="更新于 2024-03-16 22:41:56">2024-03-16</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/%E7%89%B9%E6%AE%8A%E7%AE%97%E6%B3%95/">特殊算法</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E7%AE%97%E6%B3%95/">算法</a></span></div><div class="content">
</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2024/02/27/Java/%E7%AE%97%E6%B3%95/Leetcode/%E9%93%BE%E8%A1%A8/" title="链表">链表</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time class="post-meta-date-created" datetime="2024-02-27T07:03:53.523Z" title="发表于 2024-02-27 15:03:53">2024-02-27</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-03-09T08:28:15.824Z" title="更新于 2024-03-09 16:28:15">2024-03-09</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Leetcode/">Leetcode</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E7%AE%97%E6%B3%95/">算法</a></span></div><div class="content">147. 对链表进行插入排序
Problem: 147. 对链表进行插入排序
思路
维护有序链表,开始时只有一个头节点。
哑节点dommuy.next = head,便于在头节点前插入节点
有序链表最后一个节点lastSorted
待插入节点cur
while循环对cur遍历
如果lastSorted <= cur,将lastSorted和cur均向后移动一个节点
否则,需要将cur插入到有序链表中。定义prev为有序链表中cur节点的邻近前节点。初始化prev为哑节点(不是头节点,要用prev.next比较)。
如果prev的后节点小于等于cur,prev向后移动一位
否则。说明找到了插入位置,改变lastSorted,cur,prev的next指针,将cur插入到有序链表中。
将cur更新为lastSorted.next
Code1234567891011121314151617181920212223242526272829303132333435/** * Definition for singly-linked list. * publi ...</div></div></div><div class="recent-post-item"><div class="recent-post-info no-cover"><a class="article-title" href="/2024/02/27/Java/%E7%AE%97%E6%B3%95/Leetcode/%E6%95%B0%E7%BB%84/" title="数组">数组</a><div class="article-meta-wrap"><span class="post-meta-date"><i class="far fa-calendar-alt"></i><span class="article-meta-label">发表于</span><time class="post-meta-date-created" datetime="2024-02-27T06:10:27.687Z" title="发表于 2024-02-27 14:10:27">2024-02-27</time><span class="article-meta-separator">|</span><i class="fas fa-history"></i><span class="article-meta-label">更新于</span><time class="post-meta-date-updated" datetime="2024-03-10T09:11:11.173Z" title="更新于 2024-03-10 17:11:11">2024-03-10</time></span><span class="article-meta"><span class="article-meta-separator">|</span><i class="fas fa-inbox"></i><a class="article-meta__categories" href="/categories/Leetcode/">Leetcode</a></span><span class="article-meta tags"><span class="article-meta-separator">|</span><i class="fas fa-tag"></i><a class="article-meta__tags" href="/tags/%E7%AE%97%E6%B3%95/">算法</a></span></div><div class="content">34. 在排序数组中查找元素的第一个和最后一个位置
Problem: 34. 在排序数组中查找元素的第一个和最后一个位置
思路两次二分查找,分别找到等于$target$ 的元素的最左位置和最右位置
初始化最左位置 $first = -1$,最右位置 $last = -1$。
找最左位置:
如果$nums[mid]$ 等于 $target$,暂时认为此时的位置是最左位置,令$first = mid$。再让 $right = mid - 1$,尝试查找更左的位置是否还有与 $target$ 相同的元素。
如果 $nums[mid]$ 小于 $target$,查找 $mid$ 右侧的元素
如果 $nums[mid]$ 大于 $target$,查找 $mid$ 左侧的元素。
找最右位置同理:
如果$nums[mid]$ 等于 $target$,暂时认为此时的位置是最右位置,令$last = mid$。再让 $left = mid + 1$,尝试查找更右的位置是否还有与 $target$ 相同的元素。
如果 $nums[mid] ...</div></div></div><nav id="pagination"><div class="pagination"><span class="page-number current">1</span><a class="page-number" href="/page/2/#content-inner">2</a><span class="space">…</span><a class="page-number" href="/page/4/#content-inner">4</a><a class="extend next" rel="next" href="/page/2/#content-inner"><i class="fas fa-chevron-right fa-fw"></i></a></div></nav></div><div class="aside-content" id="aside-content"><div class="card-widget card-info"><div class="is-center"><div class="avatar-img"><img src="/img/avatar.png" onerror="this.onerror=null;this.src='/img/friend_404.gif'" alt="avatar"/></div><div class="author-info__name">TechNotes</div><div class="author-info__description">Stay hungry.Stay foolish.</div></div><div class="card-info-data site-data is-center"><a href="/archives/"><div class="headline">文章</div><div class="length-num">33</div></a><a href="/tags/"><div class="headline">标签</div><div class="length-num">4</div></a><a href="/categories/"><div class="headline">分类</div><div class="length-num">12</div></a></div><a id="card-info-btn" target="_blank" rel="noopener" href="https://github.com/techniquenotes"><i class="fab fa-github"></i><span>Follow Me</span></a><div class="card-info-social-icons is-center"><a class="social-icon" href="https://github.com/techniquenotes" target="_blank" title="Github"><i class="fab fa-github" style="color: #24292e;"></i></a><a class="social-icon" href="mailto:[email protected]" target="_blank" title="Email"><i class="fas fa-envelope" style="color: #4a7dbe;"></i></a></div></div><div class="card-widget card-announcement"><div class="item-headline"><i class="fas fa-bullhorn fa-shake"></i><span>公告</span></div><div class="announcement_content">This is my Blog</div></div><div class="sticky_layout"><div class="card-widget card-recent-post"><div class="item-headline"><i class="fas fa-history"></i><span>最新文章</span></div><div class="aside-list"><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2024/03/27/SpringSecurity/SpringSecurity%E5%BA%9F%E5%BC%83WebSecurityConfigurerAdapter%E5%90%8E%E9%85%8D%E7%BD%AE/" title="SpringSecurity废弃WebSecurityConfigurerAdapter后配置">SpringSecurity废弃WebSecurityConfigurerAdapter后配置</a><time datetime="2024-03-27T06:58:06.868Z" title="发表于 2024-03-27 14:58:06">2024-03-27</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2024/03/27/SpringSecurity/SpringSecurity%E6%9F%A5%E7%9C%8B%E8%BF%87%E6%BB%A4%E5%99%A8%E9%93%BE/" title="SpringSecurity查看过滤器链">SpringSecurity查看过滤器链</a><time datetime="2024-03-27T06:51:08.965Z" title="发表于 2024-03-27 14:51:08">2024-03-27</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2024/03/27/Postgresql/%E4%BD%BF%E7%94%A8%20Mybatis%20%E5%90%91%20Postgresql%20%E6%8F%92%E5%85%A5%20UUID%20%E5%AD%97%E6%AE%B5/" title="使用 Mybatis 向 Postgresql 插入 UUID 字段">使用 Mybatis 向 Postgresql 插入 UUID 字段</a><time datetime="2024-03-27T05:54:02.759Z" title="发表于 2024-03-27 13:54:02">2024-03-27</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2024/03/24/SpringSecurity/Spring%20boot%20+%20Postgresql%20%E5%AE%9E%E7%8E%B0%20JWT%20%E8%BA%AB%E4%BB%BD%E9%AA%8C%E8%AF%81/" title="Spring boot + Postgresql 实现 JWT 身份验证">Spring boot + Postgresql 实现 JWT 身份验证</a><time datetime="2024-03-24T12:44:52.227Z" title="发表于 2024-03-24 20:44:52">2024-03-24</time></div></div><div class="aside-list-item no-cover"><div class="content"><a class="title" href="/2024/03/16/Angular/Angular_Chapter1/" title="Angular Chapter1">Angular Chapter1</a><time datetime="2024-03-16T14:36:38.096Z" title="发表于 2024-03-16 22:36:38">2024-03-16</time></div></div></div></div><div class="card-widget card-categories"><div class="item-headline">
<i class="fas fa-folder-open"></i>
<span>分类</span>
<a class="card-more-btn" href="/categories/" title="查看更多">
<i class="fas fa-angle-right"></i></a>
</div>
<ul class="card-category-list" id="aside-cat-list">
<li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Anaconda/"><span class="card-category-list-name">Anaconda</span><span class="card-category-list-count">2</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Angular/"><span class="card-category-list-name">Angular</span><span class="card-category-list-count">3</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Deep-Learning/"><span class="card-category-list-name">Deep Learning</span><span class="card-category-list-count">2</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Git/"><span class="card-category-list-name">Git</span><span class="card-category-list-count">2</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Hexo/"><span class="card-category-list-name">Hexo</span><span class="card-category-list-count">3</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/IDEA/"><span class="card-category-list-name">IDEA</span><span class="card-category-list-count">1</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Leetcode/"><span class="card-category-list-name">Leetcode</span><span class="card-category-list-count">3</span></a></li><li class="card-category-list-item "><a class="card-category-list-link" href="/categories/Postgresql/"><span class="card-category-list-name">Postgresql</span><span class="card-category-list-count">1</span></a></li>
</ul></div><div class="card-widget card-tags"><div class="item-headline"><i class="fas fa-tags"></i><span>标签</span></div><div class="card-tag-cloud"><a href="/tags/Tutorial/" style="font-size: 1.45em; color: rgb(153, 191, 58)">Tutorial</a><a href="/tags/Note/" style="font-size: 1.35em; color: rgb(138, 142, 61)">Note</a><a href="/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/" style="font-size: 1.15em; color: rgb(104, 23, 62)">数据库</a><a href="/tags/%E7%AE%97%E6%B3%95/" style="font-size: 1.25em; color: rgb(35, 192, 188)">算法</a></div></div><div class="card-widget card-archives"><div class="item-headline"><i class="fas fa-archive"></i><span>归档</span></div><ul class="card-archive-list"><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2024/03/"><span class="card-archive-list-date">三月 2024</span><span class="card-archive-list-count">8</span></a></li><li class="card-archive-list-item"><a class="card-archive-list-link" href="/archives/2024/02/"><span class="card-archive-list-date">二月 2024</span><span class="card-archive-list-count">25</span></a></li></ul></div><div class="card-widget card-webinfo"><div class="item-headline"><i class="fas fa-chart-line"></i><span>网站资讯</span></div><div class="webinfo"><div class="webinfo-item"><div class="item-name">文章数目 :</div><div class="item-count">33</div></div><div class="webinfo-item"><div class="item-name">已运行时间 :</div><div class="item-count" id="runtimeshow" data-publishDate="2023-04-28T16:00:00.000Z"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">本站总字数 :</div><div class="item-count">53.1k</div></div><div class="webinfo-item"><div class="item-name">本站访客数 :</div><div class="item-count" id="busuanzi_value_site_uv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">本站总访问量 :</div><div class="item-count" id="busuanzi_value_site_pv"><i class="fa-solid fa-spinner fa-spin"></i></div></div><div class="webinfo-item"><div class="item-name">最后更新时间 :</div><div class="item-count" id="last-push-date" data-lastPushDate="2024-03-27T07:51:32.056Z"><i class="fa-solid fa-spinner fa-spin"></i></div></div></div></div></div></div></main><footer id="footer"><div id="footer-wrap"><div class="copyright">©2023 - 2024 By TechNotes</div><div class="framework-info"><span>框架 </span><a target="_blank" rel="noopener" href="https://hexo.io">Hexo</a><span class="footer-separator">|</span><span>主题 </span><a target="_blank" rel="noopener" href="https://github.com/jerryc127/hexo-theme-butterfly">Butterfly</a></div><div class="footer_custom_text">Hi, welcome to my <a href="https://techniquenotes.github.io">blog</a>!</div></div></footer></div><div id="rightside"><div id="rightside-config-hide"><button id="darkmode" type="button" title="浅色和深色模式转换"><i class="fas fa-adjust"></i></button><button id="hide-aside-btn" type="button" title="单栏和双栏切换"><i class="fas fa-arrows-alt-h"></i></button></div><div id="rightside-config-show"><button id="rightside_config" type="button" title="设置"><i class="fas fa-cog fa-spin"></i></button><button id="go-up" type="button" title="回到顶部"><span class="scroll-percent"></span><i class="fas fa-arrow-up"></i></button></div></div><div><script src="/js/utils.js"></script><script src="/js/main.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox/fancybox.umd.min.js"></script><script>function panguFn () {
if (typeof pangu === 'object') pangu.autoSpacingPage()
else {
getScript('https://cdn.jsdelivr.net/npm/pangu/dist/browser/pangu.min.js')
.then(() => {
pangu.autoSpacingPage()
})
}
}
function panguInit () {
if (false){
GLOBAL_CONFIG_SITE.isPost && panguFn()
} else {
panguFn()
}
}
document.addEventListener('DOMContentLoaded', panguInit)</script><div class="js-pjax"><script>window.typedJSFn = {
init: (str) => {
window.typed = new Typed('#subtitle', Object.assign({
strings: str,
startDelay: 300,
typeSpeed: 150,
loop: true,
backSpeed: 50,
}, null))
},
run: (subtitleType) => {
if (true) {
if (typeof Typed === 'function') {
subtitleType()
} else {
getScript('https://cdn.jsdelivr.net/npm/typed.js/dist/typed.umd.min.js').then(subtitleType)
}
} else {
subtitleType()
}
}
}
</script><script>function subtitleType () {
getScript('https://yijuzhan.com/api/word.php?m=js').then(() => {
const con = str[0]
if (true) {
const from = '出自 ' + str[1]
const sub = ["Stay hungry,Stay foolish","Never put off till tomorrow what you can do today"]
sub.unshift(con, from)
typedJSFn.init(sub)
} else {
document.getElementById('subtitle').innerHTML = con
}
})
}
typedJSFn.run(subtitleType)
</script></div><script src="https://cdn.jsdelivr.net/npm/pjax/pjax.min.js"></script><script>let pjaxSelectors = ["meta[property=\"og:image\"]","meta[property=\"og:title\"]","meta[property=\"og:url\"]","head > title","#config-diff","#body-wrap","#rightside-config-hide","#rightside-config-show",".js-pjax"]
var pjax = new Pjax({
elements: 'a:not([target="_blank"])',
selectors: pjaxSelectors,
cacheBust: false,
analytics: false,
scrollRestoration: false
})
document.addEventListener('pjax:send', function () {
// removeEventListener scroll
window.tocScrollFn && window.removeEventListener('scroll', window.tocScrollFn)
window.scrollCollect && window.removeEventListener('scroll', scrollCollect)
document.getElementById('rightside').style.cssText = "opacity: ''; transform: ''"
if (window.aplayers) {
for (let i = 0; i < window.aplayers.length; i++) {
if (!window.aplayers[i].options.fixed) {
window.aplayers[i].destroy()
}
}
}
typeof typed === 'object' && typed.destroy()
//reset readmode
const $bodyClassList = document.body.classList
$bodyClassList.contains('read-mode') && $bodyClassList.remove('read-mode')
typeof disqusjs === 'object' && disqusjs.destroy()
})
document.addEventListener('pjax:complete', function () {
window.refreshFn()
document.querySelectorAll('script[data-pjax]').forEach(item => {
const newScript = document.createElement('script')
const content = item.text || item.textContent || item.innerHTML || ""
Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
newScript.appendChild(document.createTextNode(content))
item.parentNode.replaceChild(newScript, item)
})
GLOBAL_CONFIG.islazyload && window.lazyLoadInstance.update()
typeof chatBtnFn === 'function' && chatBtnFn()
typeof panguInit === 'function' && panguInit()
// google analytics
typeof gtag === 'function' && gtag('config', '', {'page_path': window.location.pathname});
// baidu analytics
typeof _hmt === 'object' && _hmt.push(['_trackPageview',window.location.pathname]);
typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting()
// prismjs
typeof Prism === 'object' && Prism.highlightAll()
})
document.addEventListener('pjax:error', (e) => {
if (e.request.status === 404) {
pjax.loadUrl('/404.html')
}
})</script><script async data-pjax src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script></div></body></html>