黑馬點評1——短信篇(基于session)

?🌈hello,你好鴨,我是Ethan,一名不斷學習的碼農,很高興你能來閱讀。

??目前博客主要更新Java系列、項目案例、計算機必學四件套等。
🏃人生之義,在于追求,不在成敗,勤通大道。加油呀!

🔥個人主頁:Ethan Yankang
🔥專欄:黑馬點評||Java項目

🔥本篇概覽:講解基于session的短信登錄。Threadlocal的使用。雙攔截器的使用。數據脫敏的技巧等。

目錄

????????????1、短信登錄——基于session

1.1、導入黑馬點評項目

1.1.1 、導入SQL

1.1.2、有關當前模型

nginx總結:

1.1.3、導入后端項目

1.1.4、導入前端工程

1.1.5 運行前端項目

1.2 、基于Session實現登錄流程

知識補充:session

1.3 、實現發送短信驗證碼功能

? 代碼——發送驗證碼

? 代碼——登錄

1.4、實現登錄攔截功能

溫馨小貼士:tomcat的運行原理

溫馨小貼士:關于threadlocal

? 代碼——攔截器

? 代碼——讓攔截器生效

1.5、用戶信息脫敏

?代碼——將user對象換成UserDTO

1.6、session共享問題——用redis的原因


1、短信登錄——基于session

1.1、導入黑馬點評項目

1.1.1 、導入SQL

1.1.2、有關當前模型

手機或者app端發起請求,請求我們的nginx服務器,nginx基于七層模型走的是HTTP協議,可以實現基于Lua直接繞開tomcat訪問redis,也可以作為靜態資源服務器,輕松扛下上萬并發, 負載均衡到下游tomcat服務器,打散流量,我們都知道一臺4核8G的tomcat,在優化和處理簡單業務的加持下,大不了就處理1000左右的并發, 經過nginx的負載均衡分流后,利用集群支撐起整個項目,同時nginx在部署了前端項目后,更是可以做到動靜分離,進一步降低tomcat服務的壓力,這些功能都得靠nginx起作用,所以nginx(面試準備)是整個項目中重要的一環。

nginx總結:

動靜分離

靜態部署

負載均衡

在tomcat支撐起并發流量后,我們如果讓tomcat直接去訪問Mysql,根據經驗Mysql企業級服務器只要上點并發,一般是16或32 核心cpu,32 或64G內存,像企業級mysql加上固態硬盤能夠支撐的并發,大概就是4000起~7000左右,上萬并發, 瞬間就會讓Mysql服務器的cpu,硬盤全部打滿,容易崩潰,所以我們在高并發場景下,會選擇使用mysql集群(面試準備),同時為了進一步降低Mysql的壓力,同時增加訪問的性能,我們也會加入Redis,同時使用Redis集群(面試準備)使得Redis對外提供更好的服務。

1.1.3、導入后端項目

在資料中提供了一個項目源碼:

1.1.4、導入前端工程

1.1.5 運行前端項目

1.2 、基于Session實現登錄流程

知識補充:session

在 Web 開發中,Session 指的是服務器為了保存用戶在多次請求之間的狀態信息而創建的一種機制。當用戶訪問網站時,服務器會為該用戶創建一個唯一的 Session 對象,用于存儲用戶相關的特定數據,如登錄狀態、用戶偏好等。在同一次會話(會話通常指從用戶打開瀏覽器開始訪問某個網站到關閉瀏覽器的整個過程。)期間,用戶與服務器之間的交互可以通過這個 Session 來維護相關狀態和數據,使得服務器能夠識別是同一個用戶在進行操作,從而實現個性化的服務和交互。它通常基于 Cookie 或其他機制在客戶端和服務器之間進行關聯和傳遞。

發送驗證碼:

用戶在提交手機號后,會校驗手機號是否合法,如果不合法,則要求用戶重新輸入手機號

如果手機號合法,后臺此時生成對應的驗證碼,同時將驗證碼進行保存,然后再通過短信的方式將驗證碼發送給用戶(實際上必要的知識驗證碼,而非短信)。

短信驗證碼登錄、注冊:

用戶將驗證碼和手機號進行輸入,后臺從session中拿到當前驗證碼,然后和用戶輸入的驗證碼進行校驗。

如果不一致,則無法通過校驗。

如果一致,則后臺根據手機號查詢用戶,如果用戶不存在,則為用戶創建賬號信息,保存到數據庫,無論是否存在,都會將用戶信息保存到session中,方便后續獲得當前登錄信息

校驗登錄狀態:

用戶在請求時候,會從cookie中攜帶著JsessionId到后臺,后臺通過JsessionId從session中拿到用戶信息,如果沒有session信息,則進行攔截如果有session信息,則將用戶信息保存到threadLocal中,并且放行

1.3 、實現發送短信驗證碼功能

頁面流程

具體代碼如下

貼心小提示:

具體邏輯上文已經分析,我們僅僅只需要按照提示的邏輯寫出代碼即可。

  • ? 代碼——發送驗證碼

?@Overridepublic Result sendCode(String phone, HttpSession session) {// 1.校驗手機號if (RegexUtils.isPhoneInvalid(phone)) {// 2.如果不符合,返回錯誤信息return Result.fail("手機號格式錯誤!");}// 3.符合,生成驗證碼String code = RandomUtil.randomNumbers(6);
?// 4.保存驗證碼到 sessionsession.setAttribute("code",code);// 5.發送驗證碼log.debug("發送短信驗證碼成功,驗證碼:{}", code);// 返回okreturn Result.ok();}
  • ? 代碼——登錄

 ?@Overridepublic Result login(LoginFormDTO loginForm, HttpSession session) {// 1.校驗手機號String phone = loginForm.getPhone();if (RegexUtils.isPhoneInvalid(phone)) {// 2.如果不符合,返回錯誤信息return Result.fail("手機號格式錯誤!");}// 3.校驗驗證碼Object cacheCode = session.getAttribute("code");String code = loginForm.getCode();if(cacheCode == null || !cacheCode.toString().equals(code)){//3.不一致,報錯return Result.fail("驗證碼錯誤");}//一致,根據手機號查詢用戶User user = query().eq("phone", phone).one();
?//5.判斷用戶是否存在if(user == null){//不存在,則創建user = ?createUserWithPhone(phone);}//7.保存用戶信息到session中session.setAttribute("user",user);
?return Result.ok();}

1.4、實現登錄攔截功能

溫馨小貼士:tomcat的運行原理

當用戶發起請求時,會訪問我們向tomcat注冊的端口,任何程序想要運行,都需要有一個線程對當前端口號進行監聽,tomcat也不例外,當監聽線程知道用戶想要和tomcat連接連接時,那會由監聽線程創建socket連接,socket都是成對出現的,用戶通過socket像互相傳遞數據,當tomcat端的socket接受到數據后,此時監聽線程會從tomcat的線程池中取出一個線程執行用戶請求,在我們的服務部署到tomcat后,線程會找到用戶想要訪問的工程,然后用這個線程轉發到工程中的controller,service,dao中,并且訪問對應的DB,在用戶執行完請求后,再統一返回,再找到tomcat端的socket,再將數據寫回到用戶端的socket,完成請求和響應

通過以上講解,我們可以得知 每個用戶其實對應都是去找tomcat線程池中的一個線程來完成工作的, 使用完成后再進行回收,既然每個請求都是獨立的,所以在每個用戶去訪問我們的工程時,我們可以使用threadlocal來做到線程隔離,每個線程操作自己的一份數據

溫馨小貼士:關于threadlocal

如果小伙伴們看過threadLocal的源碼,你會發現在threadLocal中,無論是他的put方法和他的get方法, 都是先從獲得當前用戶的線程,然后從線程中取出線程的成員變量map,只要線程不一樣,map就不一樣,所以可以通過這種方式來做到線程隔離

有關Threadlocal詳情帖子請點擊這里

? 代碼——攔截器

public class LoginInterceptor implements HandlerInterceptor {
?@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {//1.獲取sessionHttpSession session = request.getSession();//2.獲取session中的用戶Object user = session.getAttribute("user");//3.判斷用戶是否存在if(user == null){//4.不存在,攔截,返回401狀態碼response.setStatus(401);return false;}//5.存在,保存用戶信息到ThreadlocalUserHolder.saveUser((User)user);//6.放行return true;}
}

? 代碼——讓攔截器生效

@Configuration
public class MvcConfig implements WebMvcConfigurer {
?@Resourceprivate StringRedisTemplate stringRedisTemplate;
?@Overridepublic void addInterceptors(InterceptorRegistry registry) {// 登錄攔截器registry.addInterceptor(new LoginInterceptor()).excludePathPatterns("/shop/**","/voucher/**","/shop-type/**","/upload/**","/blog/hot","/user/code","/user/login").order(1);// token刷新的攔截器registry.addInterceptor(new RefreshTokenInterceptor(stringRedisTemplate)).addPathPatterns("/**").order(0);}
}

1.5、用戶信息脫敏

我們通過瀏覽器觀察到此時用戶的全部信息都在,這樣極為不靠譜,所以我們應當在返回用戶信息之前,將用戶的敏感信息進行隱藏,采用的核心思路就是書寫一個UserDto對象,這個UserDto對象就沒有敏感信息了,我們在返回前,將有用戶敏感信息的User對象轉化成沒有敏感信息的UserDto對象,那么就能夠避免這個尷尬的問題了

在登錄方法處修改

//7.保存用戶信息到session中
session.setAttribute("user", BeanUtils.copyProperties(user,UserDTO.class));

在攔截器處:

//5.存在,保存用戶信息到Threadlocal
UserHolder.saveUser((UserDTO) user);

在UserHolder處:

?代碼——將user對象換成UserDTO

public class UserHolder {private static final ThreadLocal<UserDTO> tl = new ThreadLocal<>();
?public static void saveUser(UserDTO user){tl.set(user);}
?public static UserDTO getUser(){return tl.get();}
?public static void removeUser(){tl.remove();}
}

1.6、session共享問題——引出用redis的原因

核心思路分析:

每個tomcat中都有一份屬于自己的session,假設用戶第一次訪問第一臺tomcat,并且把自己的信息存放到第一臺服務器的session中,但是第二次這個用戶訪問到了第二臺tomcat,那么在第二臺服務器上,肯定沒有第一臺服務器存放的session,所以此時整個登錄攔截功能就會出現問題,我們能如何解決這個問題呢?早期的方案是session拷貝,就是說雖然每個tomcat上都有不同的session,但是每當任意一臺服務器的session修改時,都會同步給其他的Tomcat服務器的session,這樣的話,就可以實現session的共享了

但是這種方案具有兩個大問題

1、每臺服務器中都有完整的一份session數據,服務器壓力過大。

2、session拷貝數據時,可能會出現延遲

所以咱們后來采用的方案都是基于redis來完成,我們把session換成redis,redis數據本身就是共享的,就可以避免session共享的問題了

📣非常感謝你閱讀到這里,如果這篇文章對你有幫助,希望能留下你的點贊👍 關注? 分享👥 留言💬thanks!!!
📚愿大家都能學有所得,功不唐捐!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/14343.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/14343.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/14343.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何使用多種算法解決LeetCode第135題——分發糖果問題

?????? 歡迎來到我的博客。希望您能在這里找到既有價值又有趣的內容&#xff0c;和我一起探索、學習和成長。歡迎評論區暢所欲言、享受知識的樂趣&#xff01; 推薦&#xff1a;數據分析螺絲釘的首頁 格物致知 終身學習 期待您的關注 導航&#xff1a; LeetCode解鎖100…

WPF 的 style 定義 使用 繼承 復用

style 樣式 如何定義一個 style 樣式 <Button Content"樣式" Width"100" Height"50"><Button.Style><Style></Style></Button.Style></Button>擁有的屬性 targetType “” 針對什么類型生效setter 設置屬…

Ubuntu中 petalinux 安裝 移植linux --tftp/tftp-hpa服務的方法

Xilinx 文檔 PetaLinux 指南&#xff1a;如何創建 PetaLinux 環境 &#xff08;2019.1&#xff09; PetaLinux工具參考指南 PetaLinux安裝詳解(Xilinx , linux, zynq, zynqMP) petalinux 2020.1安裝教程 一、PetaLinux工具和庫安裝 PetaLinux 工具要求主機系統 /bin/sh 為“b…

18.網絡編程

網絡編程 又稱為Socket編程。 Java中網絡編程主要是以Java語言完成信息數據在網絡上的傳輸。 網絡 計算機網絡&#xff0c;指的是將不同地理位置的多臺計算機連接起來&#xff0c;可以實現信息共享和信息傳輸。 Java是Internet上的語言&#xff0c;提供了對網絡應用程序的…

筆記 | 《css權威指南》

網絡安全色 URL text-indent line-height & vertical-align 字體 font-weight 400 normal 700 bold background-attachment

SpringBoot項目集成JetCache緩存框架步驟

JetCache是阿里開源的基于java開發的緩存框架&#xff0c;支持多種緩存類型&#xff1a;本地緩存、分布式緩存、多級緩存。能夠滿足不同業務場景的緩存需求。 1.導入依賴 <!--jetcache緩存 --> <dependency><groupId>com.alicp.jetcache</groupId>&l…

【調試筆記-20240516-Windows-使用VS2019編譯edk2(上)】

調試筆記-系列文章目錄 調試筆記-20240516-Windows-使用VS2019編譯edk2&#xff08;上&#xff09; 文章目錄 調試筆記-系列文章目錄調試筆記-20240516-Windows-使用VS2019編譯edk2&#xff08;上&#xff09; 前言一、安裝開發工具1. 安裝 VS20192. 安裝 Python 3.103. 安裝 …

pdf加水印怎么加?3種添加水印方法分享

pdf加水印怎么加&#xff1f;PDF加水印不僅是為了保護文檔內容&#xff0c;確保信息的安全性和完整性&#xff0c;更是一種有效的版權保護措施。通過添加水印&#xff0c;您可以在文檔中嵌入公司名稱、日期、編號等信息&#xff0c;以明確文檔的歸屬權和使用限制。此外&#xf…

小而美:兩步完成從源碼到應用的極簡交付

作者&#xff1a;花三&#xff08;王俊&#xff09; Serverless 應用引擎 SAE 是阿里云推出的一款零代碼改造、極簡易用、自適應彈性的容器化應用托管平臺&#xff0c;面市以來為幾萬家企業客戶提供服務&#xff0c;運行穩定&#xff0c;廣受好評。 SAE 的出現解決了眾多企業…

Python庫之lxml的簡介、安裝、使用方法詳細攻略

Python庫之lxml的簡介、安裝、使用方法詳細攻略 簡介 lxml是一個用于處理XML和HTML文檔的Python庫&#xff0c;它提供了簡單易用的API來解析和生成這些文檔。lxml以其性能和易用性而受到廣泛歡迎&#xff0c;特別適合于需要處理大量數據或需要高性能解析的場景。 安裝 安裝…

運行時異常和編譯時異常的區別

Java中的異常被分為兩大類&#xff1a;編譯時異常和運行時異常。 都是RuntimeException類及其子類異常&#xff0c;如NullPointerException、IndexOutOfBoundsException。這些異常是不檢查異常&#xff0c;運行時異常的特點是Java編譯器不會檢查它&#xff0c;程序中可以選擇捕…

純代碼如何實現WordPress搜索包含評論內容?

WordPress自帶的搜索默認情況下是不包含評論內容的&#xff0c;不過有些WordPress網站評論內容比較多&#xff0c;而且也比較有用&#xff0c;所以想要讓用戶在搜索時也能夠同時搜索到評論內容&#xff0c;那么應該怎么做呢&#xff1f; 網絡上很多教程都是推薦安裝SearchWP插…

RK3588 Android13 預安裝自己的apk應用及把這個應用設置為默認桌面

1、cp -rf device/rockchip/rk3588/rk3588m_s/preinstall device/rockchip/rk3588/rk3588_t/ 2、給device/rockchip/rk3588/rk3588_t/preinstall/的存放app的文件夾改名為app-imms2&#xff0c;在app-imms2放入app-imms2.apk,編譯安卓源碼即可&#xff0c; 3、編譯完會在out/…

android sp指針的cast

sp<Base> b; sp<Derived> d; b static_cast<Base*>(d.get()); 對于c原生的智能指針&#xff0c;有static_pointer_cast之類的操作方法。可以看cppreference。

Spring Web MVC介紹及詳細教程

目錄 1.什么是Spring Web MVC&#xff1f; 1.1 MVC定義 1.2 Spring MVC與MVC關系 2.為什么要學習Spring MVC 3.項目創建 4.Spring MVC連接 4.1 RequestMapping 4.2 PostMapping和GetMapping 5.Spring MVC參數獲取 5.1 獲取單個參數 5.2 獲取多個參數 5.3 獲取普通對…

通用代碼生成器應用場景一,項目前期

通用代碼生成器是一種自動化編程軟件&#xff0c;是一種先進的編譯系統。它具有表級抽象。把系統抽象為域對象&#xff0c;枚舉&#xff0c;彈性登錄模塊&#xff0c;復雜版面和圖形報表。使用通用代碼生成器完成項目前期&#xff0c;比直接使用對應的高級語言快的多&#xff0…

element Notification 消息過多需要折疊

Notification 消息過多太長 希望能折疊 如圖下效果 element-plus 可以將dom 插入到具體的元素 結合css :nth-child 來控制樣式達到效果 element dom 只能插入到body中 所以無法使用:nth-child 1.Notification需要消息提示時設置class let eleNum 0 // 彈窗的序號 function…

vue+canvas實現逐字手寫效果

在pc端進行逐字手寫的功能。用戶可以在一個 inputCanvas 上書寫單個字&#xff0c;然后在特定時間后將這個字添加到 outputCanvas 上&#xff0c;形成一個逐字的手寫效果。用戶還可以保存整幅圖像或者撤銷上一個添加的字。 <template><div class"container"…

小紅書-社區搜索部 (NLP、CV算法實習生) 一面面經

&#x1f604; 整個流程按如下問題展開&#xff0c;用時60min左右面試官人挺好&#xff0c;前半部分問問題&#xff0c;后半部分coding一道題。 各位有什么問題可以直接評論區留言&#xff0c;24小時內必回信息&#xff0c;放心~ 文章目錄 1、自我介紹2、介紹下項目&#xff…

金額計算導致的錯誤問題匯總解決

在日常的開發中&#xff0c;前端計算金額是非常常見&#xff0c;如果不夠仔細&#xff0c;考慮不夠周全的話&#xff0c;很容易犯錯的&#xff0c;金額這個東西一但錯了是很嚴重的&#xff0c;因此總結一些常見的錯誤&#xff1a; 1.最重要的&#xff0c;涉及到計算的參數一定要…