springboot項目整合-註冊功能模塊開發
工程簡介
準備工作:項目所用到的html界面以及sql文件鏈接如下:鏈接: //pan.baidu.com/s/18loHJiKRC6FI6XkoANMSJg?pwd=nkz2 提取碼: nkz2 複製這段內容後打開百度網盤手機App,操作更方便哦
第一步:註冊功能的實現
1.1持久層的設計
1.1.1規範需要執行的SQL語句
1.用戶的註冊工作,相當於在做數據的插入操作
insert into t_user (username,password) values (?,?)
2.在用戶的註冊是首先需要查詢當前的用戶名是否存在,如果存在則不能進行註冊,相當於一個查詢語句
select * from t_user where username = ?
1.1.2設計接口和抽象方法
定義mapper接口,在項目的目錄結構下首先創建一個mapper包,在這個包下根據不同的功能模塊來創建mapper接口
1.創建一個userMapper 需要考慮上述的兩個注意點
package com.cy.store.mapper;
import com.cy.store.pojo.User;
/**
* 用戶模塊的持久化層接口
*/
public interface UserMapper {
/**
* 插入用戶的數據->用來實現註冊功能
* @param user
* @return 受到影響的行數(增刪改查 )
*/
Integer insert(User user);
/**
* 根據用戶名查詢用戶的數據
* @param username
* @return 如果找到了則返回相對應的用戶信息,找不到返回null
*/
User findByUsername(String username);
}
1.1.3 編寫映射
1.定義xml映射文件,與對應的接口進行關聯.所有餓映射文件需要放置在resource目錄下,一般為了方便管理,一般在這個目錄下創建一個mapper文件夾,然後在找這個文件夾存放相應的mapper 文件
2.創建接口的對應的映射文件,規則:和接口的名稱保持一致即可,創建一個UserMapper.xml
1.1.4 單元測試
1.每個獨立的層編寫完畢需要編寫單元測試方法,來測試當前的功能, 在test包下創建一個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方法上加上這個註解: @Repository
*/
@Autowired
private UserMapper userMapper;
/**
* @Dat 2022年11月2日17:25:41
* 測試成功
*/
@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 查詢的結果為:User(uid=1, username=tom, password=123456, salt=null, phone=null, email=null, gender=null, avatar=null, isDelete=null)
* 測試成功
*/
@Test
public void testFindByUsername(){
User tom = userMapper.findByUsername("tom");
log.info("查詢的結果為:{}",tom);
}
}
1.2註冊功能-業務層
1.2.1 規劃異常
1.runtimeException異常,作為這個異常的子類,然後在定義具體的異常類型來繼承這個異常,業務層異常的基類
serviceException異常,這個異常繼承RuntimeException異常,以此建立異常的機制。
2.用戶在進行註冊時候可能會產生用戶名被佔用的錯誤,拋出一個異常 UsernameDuplicatedException
3.正在執行數據插入操作的時候,服務器、數據庫宕機。處於正在執行插入的過程中,所產生的異常InsertException
1.2.2 設計接口和抽象方法
1.在service包下創建一個IUserService
2.設計一個實現類的包
3.實現類中重寫 註冊方法實現完全的用戶註冊邏輯
@Override
public void reg(User user) {
//調用findByUsernam 方法 判斷用戶名是否被註冊過
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("在用戶註冊中產生了位置的異常");
}
}
1.2.3 在單元測試中創建UserServiceTest類 進行相應的註冊邏輯進行測試
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 測試用戶註冊的功能 成功返回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());
//打印錯誤信息
System.out.println(e.getMessage());
}
}
}
1.3控制層
1.3.1 創建響應
1.狀態碼、狀態描述信息、數據,這部分功能封裝在一個類中,將這類方法作為方法返回值,返回給前端瀏覽器 com.cy.store.StoreApplication
1.3.2. 設計請求
依據當前的業務功能模塊進行請求的設計
請求的路徑: /user/reg
請求參數: User user
請求類型: Post
響應結果:JsonResult<void>
1.3.3 處理請求
1.創建一個控制層的對應的類 UserController com.cy.store.controller.UserController
try {
userService.reg(user);
voidJsonResult.setState(200);
voidJsonResult.setMessage("用戶註冊成功");
} catch (UsernameDuplicatedException e) {
voidJsonResult.setState(4000);
voidJsonResult.setMessage("用戶名被佔用");
}
catch (InsertException e) {
voidJsonResult.setState(5000);
voidJsonResult.setMessage("註冊時發生未知的異常");
}
業務邏輯過於複雜 進行簡化
1.3.4 控制層優化設計
在控制層抽離一個父類,在這個父類中統一的處理關於異常的相關操作,編寫一個BaseController類,在這個類中,統一的處理異常
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
*
* 用來表示控制層類的基類
*
*/
public class BaseController {
public static final int OK = 200; //表示操作成功的狀態碼
//請求處理方法,這個方法的返回值就是需要傳遞給前端的數據
//當項目中產生異常時,會被攔截到此方法 這個方法此時充當的就是請求處理方法 方法的返回值直接給到前端
@ExceptionHandler(ServiceException.class) // 主要用於統一處理拋出的異常
public JsonResult<Void> handleException(Throwable e){
JsonResult<Void> result = new JsonResult<>(e);
if (e instanceof UsernameDuplicatedException){
result.setState(4000);
result.setMessage("用戶名已經被佔用");
}else if (e instanceof InsertException){
result.setState(5000);
result.setMessage("註冊時發生未知的異常");
}
return result;
}
}
修改後的controller – userController 的代碼如下;
@RestController
@RequestMapping("users")
public class UserController extends BaseController{
@Autowired
private IUserService userService;
/**
* 原先的代碼
*
* @RequestMapping("reg")
public JsonResult<Void> reg(User user){
//創建結果響應對象
JsonResult<Void> voidJsonResult = new JsonResult<>();
try {
userService.reg(user);
voidJsonResult.setState(200);
voidJsonResult.setMessage("用戶註冊成功");
} catch (UsernameDuplicatedException e) {
voidJsonResult.setState(4000);
voidJsonResult.setMessage("用戶名被佔用");
}
catch (InsertException e) {
voidJsonResult.setState(5000);
voidJsonResult.setMessage("註冊時發生未知的異常");
}
return voidJsonResult;
}**/
/**
* 優化以後的代碼
* @param user
* @return
*/
@RequestMapping("reg")
public JsonResult<Void> reg(User user) {
userService.reg(user);
return new JsonResult<>(OK);
}
}
妙不可言!!!!!!!!!!
1.4前端頁面的設計
1.在register頁面中編寫發送請求的方法,後端接收方法為reg,當檢測中點擊事件後觸發請求–》 點擊事件
選擇對應的按鍵(%(「選擇器」)),再去添加點擊的事件,$.ajax()函數發送異步請求額
2.JQuery封裝了一個函數,稱為$.ajax()函數,通過對象調用ajax函數,可以異步的加載一個請求,依靠的是JAVAScript提供的一個xhr(xmlHttpResponse),封裝了這個對象
3.ajax()使用方法: 需要傳遞一個方法體作為一個方法的參數使用:一對大括號被稱為方法體.ajax接收多個參數,參數之間要求使用”,”進行分割,每一組參數之間使用”:”進行分割
。參數的組成部分一個是參數的名稱(不能隨意更改),參數的值要求是用字符串來標識。參數的聲明順序沒有要求 。語法結構如下:
$.ajax({
url: "",
type: "",
dataType: "",
success: function() {
},
error:function() {
}
});
4.ajax函數參數的含義
url : 標識請求的地址(url地址)。不能包括列表部分的內容 例如: url:”localhost:8080/users/reg”
type: 請求類型(GET 和 POST 請求類型) 例如: type:”POST”
data: 向指定的請求url地址提交的數據: 例如: data:”username=”tom”&password=”123456″”
dataType:提交的數據的類型 例如:”json”
success:當服務器正常響應客戶端時,將會自動調用success方法,並且將服務器返回的數據以參數的形式傳遞給這個方法的參數上
error:當服務器異常響應客戶端時,將會自動調用error方法,並且將服務器返回的數據以參數的形式傳遞給這個方法的參數上
5.js代碼可以獨立聲明在一個js的文件里或者聲明在一個script標籤中