springboot項(xiàng)目整合注冊(cè)功能模塊開(kāi)發(fā)實(shí)戰(zhàn)
工程簡(jiǎn)介
準(zhǔn)備工作:
項(xiàng)目所用到的html界面以及sql文件鏈接如下:
百度網(wǎng)盤獲取地址:
鏈接: https://pan.baidu.com/s/1CcbQWP8RNqyy3ieib1osLg?pwd=t1qu 提取碼: t1qu
第一步:注冊(cè)功能的實(shí)現(xiàn)
1.1持久層的設(shè)計(jì)
1.1.1規(guī)范需要執(zhí)行的SQL語(yǔ)句
1.用戶的注冊(cè)工作,相當(dāng)于在做數(shù)據(jù)的插入操作
insert into t_user (username,password) values (?,?)
2.在用戶的注冊(cè)是首先需要查詢當(dāng)前的用戶名是否存在,如果存在則不能進(jìn)行注冊(cè),相當(dāng)于一個(gè)查詢語(yǔ)句
select * from t_user where username = ?
1.1.2設(shè)計(jì)接口和抽象方法
定義mapper接口,在項(xiàng)目的目錄結(jié)構(gòu)下首先創(chuàng)建一個(gè)mapper包,在這個(gè)包下根據(jù)不同的功能模塊來(lái)創(chuàng)建mapper接口
1.創(chuàng)建一個(gè)userMapper 需要考慮上述的兩個(gè)注意點(diǎn)
package com.cy.store.mapper; import com.cy.store.pojo.User; /** * 用戶模塊的持久化層接口 */ public interface UserMapper { /** * 插入用戶的數(shù)據(jù)->用來(lái)實(shí)現(xiàn)注冊(cè)功能 * @param user * @return 受到影響的行數(shù)(增刪改查 ) */ Integer insert(User user); /** * 根據(jù)用戶名查詢用戶的數(shù)據(jù) * @param username * @return 如果找到了則返回相對(duì)應(yīng)的用戶信息,找不到返回null */ User findByUsername(String username); }
1.1.3 編寫映射
1.定義xml映射文件,與對(duì)應(yīng)的接口進(jìn)行關(guān)聯(lián).所有餓映射文件需要放置在resource目錄下,一般為了方便管理,一般在這個(gè)目錄下創(chuàng)建一個(gè)mapper文件夾,然后在找這個(gè)文件夾存放相應(yīng)的mapper 文件
2.創(chuàng)建接口的對(duì)應(yīng)的映射文件,規(guī)則:和接口的名稱保持一致即可,創(chuàng)建一個(gè)UserMapper.xml
1.1.4 單元測(cè)試
1.每個(gè)獨(dú)立的層編寫完畢需要編寫單元測(cè)試方法,來(lái)測(cè)試當(dāng)前的功能, 在test包下創(chuàng)建一個(gè)mapper包
包:test-com.cy.store.mapper.UserMapperTest
package com.cy.store.mapper; import com.cy.store.pojo.User; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; /** * @PROJECT_NAME: store * @DESCRIPTION: * @USER: 28416 * @DATE: 2022/11/2 16:43 */ @Slf4j @SpringBootTest public class UserMapperTest { /** * 在mapper方法上加上這個(gè)注解: @Repository */ @Autowired private UserMapper userMapper; /** * @Dat 2022年11月2日17:25:41 * 測(cè)試成功 */ @Test public void insert(){ User user = new User(); user.setUsername("tom"); user.setPassword("123456"); Integer insert = userMapper.insert(user); log.info("插入返回的值:{}",insert); } /** * @Date 2022年11月2日17:27:25 * @return 查詢的結(jié)果為:User(uid=1, username=tom, password=123456, salt=null, phone=null, email=null, gender=null, avatar=null, isDelete=null) * 測(cè)試成功 */ @Test public void testFindByUsername(){ User tom = userMapper.findByUsername("tom"); log.info("查詢的結(jié)果為:{}",tom); } }
1.2注冊(cè)功能-業(yè)務(wù)層
1.2.1 規(guī)劃異常
1.runtimeException異常,作為這個(gè)異常的子類,然后在定義具體的異常類型來(lái)繼承這個(gè)異常,業(yè)務(wù)層異常的基類
serviceException異常,這個(gè)異常繼承RuntimeException異常,以此建立異常的機(jī)制。
2.用戶在進(jìn)行注冊(cè)時(shí)候可能會(huì)產(chǎn)生用戶名被占用的錯(cuò)誤,拋出一個(gè)異常 UsernameDuplicatedException
3.正在執(zhí)行數(shù)據(jù)插入操作的時(shí)候,服務(wù)器、數(shù)據(jù)庫(kù)宕機(jī)。處于正在執(zhí)行插入的過(guò)程中,所產(chǎn)生的異常InsertException
1.2.2 設(shè)計(jì)接口和抽象方法
1.在service包下創(chuàng)建一個(gè)IUserService
2.設(shè)計(jì)一個(gè)實(shí)現(xiàn)類的包
3.實(shí)現(xiàn)類中重寫 注冊(cè)方法實(shí)現(xiàn)完全的用戶注冊(cè)邏輯
@Override public void reg(User user) { //調(diào)用findByUsernam 方法 判斷用戶名是否被注冊(cè)過(guò) String username = user.getUsername(); User byUsername = userMapper.findByUsername(username); if (byUsername != null){ throw new UsernameDuplicatedException("用戶名被占用"); } Integer insert = userMapper.insert(user); if (insert != 1){ throw new InsertException("在用戶注冊(cè)中產(chǎn)生了位置的異常"); } }
1.2.3 在單元測(cè)試中創(chuàng)建UserServiceTest類 進(jìn)行相應(yīng)的注冊(cè)邏輯進(jìn)行測(cè)試
package com.cy.store.service; import com.cy.store.pojo.User; import com.cy.store.service.ex.ServiceException; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; /** * @PROJECT_NAME: store * @DESCRIPTION: * @USER: 28416 * @DATE: 2022/11/2 18:15 */ @SpringBootTest public class UserServiceTest { @Autowired private IUserService userService; /** * @Date 2022年11月2日19:25:39 * @return UsernameDuplicatedException * @return 測(cè)試用戶注冊(cè)的功能 成功返回1 or 返回自定義的exception * / * */ @Test public void reg(){ try { User user = new User(); user.setUsername("Lux"); user.setPassword("123456"); userService.reg(user); System.out.println("ok"); } catch (ServiceException e) { //獲取異常的類名 System.out.println(e.getClass().getSimpleName()); //打印錯(cuò)誤信息 System.out.println(e.getMessage()); } } }
1.3控制層
1.3.1 創(chuàng)建響應(yīng)
1.狀態(tài)碼、狀態(tài)描述信息、數(shù)據(jù),這部分功能封裝在一個(gè)類中,將這類方法作為方法返回值,返回給前端瀏覽器 com.cy.store.StoreApplication
1.3.2. 設(shè)計(jì)請(qǐng)求
依據(jù)當(dāng)前的業(yè)務(wù)功能模塊進(jìn)行請(qǐng)求的設(shè)計(jì)
請(qǐng)求的路徑: /user/reg
請(qǐng)求參數(shù): User user
請(qǐng)求類型: Post
響應(yīng)結(jié)果:JsonResult<void>
1.3.3 處理請(qǐng)求
1.創(chuàng)建一個(gè)控制層的對(duì)應(yīng)的類 UserController com.cy.store.controller.UserController
try { userService.reg(user); voidJsonResult.setState(200); voidJsonResult.setMessage("用戶注冊(cè)成功"); } catch (UsernameDuplicatedException e) { voidJsonResult.setState(4000); voidJsonResult.setMessage("用戶名被占用"); } catch (InsertException e) { voidJsonResult.setState(5000); voidJsonResult.setMessage("注冊(cè)時(shí)發(fā)生未知的異常"); }
業(yè)務(wù)邏輯過(guò)于復(fù)雜 進(jìn)行簡(jiǎn)化
1.3.4 控制層優(yōu)化設(shè)計(jì)
在控制層抽離一個(gè)父類,在這個(gè)父類中統(tǒng)一的處理關(guān)于異常的相關(guān)操作,編寫一個(gè)BaseController類,在這個(gè)類中,統(tǒng)一的處理異常
package com.cy.store.controller; import com.cy.store.service.ex.InsertException; import com.cy.store.service.ex.ServiceException; import com.cy.store.service.ex.UsernameDuplicatedException; import com.cy.store.util.JsonResult; import org.springframework.web.bind.annotation.ExceptionHandler; /** * @PROJECT_NAME: store * @DESCRIPTION: * @USER: 28416 * @DATE: 2022/11/2 20:34 * * 用來(lái)表示控制層類的基類 * */ public class BaseController { public static final int OK = 200; //表示操作成功的狀態(tài)碼 //請(qǐng)求處理方法,這個(gè)方法的返回值就是需要傳遞給前端的數(shù)據(jù) //當(dāng)項(xiàng)目中產(chǎn)生異常時(shí),會(huì)被攔截到此方法 這個(gè)方法此時(shí)充當(dāng)?shù)木褪钦?qǐng)求處理方法 方法的返回值直接給到前端 @ExceptionHandler(ServiceException.class) // 主要用于統(tǒng)一處理拋出的異常 public JsonResult<Void> handleException(Throwable e){ JsonResult<Void> result = new JsonResult<>(e); if (e instanceof UsernameDuplicatedException){ result.setState(4000); result.setMessage("用戶名已經(jīng)被占用"); }else if (e instanceof InsertException){ result.setState(5000); result.setMessage("注冊(cè)時(shí)發(fā)生未知的異常"); } return result; } }
修改后的controller - userController 的代碼如下;
@RestController @RequestMapping("users") public class UserController extends BaseController{ @Autowired private IUserService userService; /** * 原先的代碼 * * @RequestMapping("reg") public JsonResult<Void> reg(User user){ //創(chuàng)建結(jié)果響應(yīng)對(duì)象 JsonResult<Void> voidJsonResult = new JsonResult<>(); try { userService.reg(user); voidJsonResult.setState(200); voidJsonResult.setMessage("用戶注冊(cè)成功"); } catch (UsernameDuplicatedException e) { voidJsonResult.setState(4000); voidJsonResult.setMessage("用戶名被占用"); } catch (InsertException e) { voidJsonResult.setState(5000); voidJsonResult.setMessage("注冊(cè)時(shí)發(fā)生未知的異常"); } return voidJsonResult; }**/ /** * 優(yōu)化以后的代碼 * @param user * @return */ @RequestMapping("reg") public JsonResult<Void> reg(User user) { userService.reg(user); return new JsonResult<>(OK); } }
妙不可言?。。。。。。。。?!
1.4前端頁(yè)面的設(shè)計(jì)
1.在register頁(yè)面中編寫發(fā)送請(qǐng)求的方法,后端接收方法為reg,當(dāng)檢測(cè)中點(diǎn)擊事件后觸發(fā)請(qǐng)求--》 點(diǎn)擊事件
選擇對(duì)應(yīng)的按鍵(%(“選擇器”)),再去添加點(diǎn)擊的事件,$.ajax()函數(shù)發(fā)送異步請(qǐng)求額
2.JQuery封裝了一個(gè)函數(shù),稱為$.ajax()函數(shù),通過(guò)對(duì)象調(diào)用ajax函數(shù),可以異步的加載一個(gè)請(qǐng)求,依靠的是JAVAScript提供的一個(gè)xhr(xmlHttpResponse),封裝了這個(gè)對(duì)象
3.ajax()使用方法: 需要傳遞一個(gè)方法體作為一個(gè)方法的參數(shù)使用:一對(duì)大括號(hào)被稱為方法體.ajax接收多個(gè)參數(shù),參數(shù)之間要求使用","進(jìn)行分割,每一組參數(shù)之間使用":"進(jìn)行分割
。參數(shù)的組成部分一個(gè)是參數(shù)的名稱(不能隨意更改),參數(shù)的值要求是用字符串來(lái)標(biāo)識(shí)。參數(shù)的聲明順序沒(méi)有要求 。語(yǔ)法結(jié)構(gòu)如下:
$.ajax({ url: "", type: "", dataType: "", success: function() { }, error:function() { } });
4.ajax函數(shù)參數(shù)的含義
url : 標(biāo)識(shí)請(qǐng)求的地址(url地址)。不能包括列表部分的內(nèi)容 例如: url:"localhost:8080/users/reg"
type: 請(qǐng)求類型(GET 和 POST 請(qǐng)求類型) 例如: type:"POST"
data: 向指定的請(qǐng)求url地址提交的數(shù)據(jù): 例如: data:"username="tom"&password="123456""
dataType:提交的數(shù)據(jù)的類型 例如:"json"
success:當(dāng)服務(wù)器正常響應(yīng)客戶端時(shí),將會(huì)自動(dòng)調(diào)用success方法,并且將服務(wù)器返回的數(shù)據(jù)以參數(shù)的形式傳遞給這個(gè)方法的參數(shù)上
error:當(dāng)服務(wù)器異常響應(yīng)客戶端時(shí),將會(huì)自動(dòng)調(diào)用error方法,并且將服務(wù)器返回的數(shù)據(jù)以參數(shù)的形式傳遞給這個(gè)方法的參數(shù)上
5.js代碼可以獨(dú)立聲明在一個(gè)js的文件里或者聲明在一個(gè)script標(biāo)簽中
注冊(cè)功能實(shí)現(xiàn)完成
到此這篇關(guān)于springboot項(xiàng)目整合注冊(cè)功能模塊開(kāi)發(fā)的文章就介紹到這了,更多相關(guān)springboot注冊(cè)模塊內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Spring Boot Admin(監(jiān)控工具)的使用
今天我們將會(huì)講解一個(gè)優(yōu)秀的監(jiān)控工具Spring Boot Admin。 它采用圖形化的界面,讓我們的Spring Boot管理更加簡(jiǎn)單,需要的朋友可以參考下2020-02-02Java多態(tài)用法與注意點(diǎn)實(shí)例分析
這篇文章主要介紹了Java多態(tài)用法與注意點(diǎn),結(jié)合實(shí)例形式分析了java多態(tài)相關(guān)的向上轉(zhuǎn)型、向下轉(zhuǎn)型、隱藏等相關(guān)操作技巧,需要的朋友可以參考下2019-08-08如何利用java控制鼠標(biāo)操作一些重復(fù)的事情
這篇文章主要給大家介紹了關(guān)于如何利用java控制鼠標(biāo)操作一些重復(fù)的事情,主要利用的是Robot類,Robot可以模擬鼠標(biāo)和鍵盤的輸入,相當(dāng)于Java版的按鍵精靈,需要的朋友可以參考下2021-12-12JAVA技術(shù)實(shí)現(xiàn)上傳下載文件到FTP服務(wù)器(完整)
這篇文章主要介紹了JAVA技術(shù)實(shí)現(xiàn)上傳下載文件到FTP服務(wù)器(完整),本文使用 Apache Jakarta Commons Net(commons-net-3.3.jar) 基于FileZilla Server服務(wù)器實(shí)現(xiàn)FTP服務(wù)器上文件的上傳/下載/刪除等操作,需要的朋友可以參考下2015-07-07Java中的SpringAOP、代理模式、常用AspectJ注解詳解
這篇文章主要介紹了Java中的SpringAOP、代理模式、常用AspectJ注解詳解,Spring提供了面向切面編程的豐富支持,允許通過(guò)分離應(yīng)用的業(yè)務(wù)邏輯與系統(tǒng)級(jí)服務(wù),例如審計(jì)和事務(wù)管理進(jìn)行內(nèi)聚性的開(kāi)發(fā),需要的朋友可以參考下2023-09-09教你怎么使用Java實(shí)現(xiàn)WebSocket
這篇文章主要介紹了教你怎么使用Java WebSocket,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java的小伙伴們有很好的幫助,需要的朋友可以參考下2021-05-05java不同版本在多線程中使用隨機(jī)數(shù)生成器的實(shí)現(xiàn)
本文主要介紹了java不同版本在多線程中使用隨機(jī)數(shù)生成器的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-04-04