首頁 > 軟體

springboot使用者資料修改的詳細實現

2022-04-06 19:00:38

修改密碼

1 使用者-修改密碼-持久層

1.1 規劃需要執行的SQL語句

使用者修改密碼時需要執行的SQL語句大致是:

UPDATE t_user SET password=?, modified_user=?, modified_time=? WHERE uid=?

在執行修改密碼之前,還應檢查使用者資料是否存在、並檢查使用者資料是否被標記為“已刪除”、並檢查原密碼是否正確,這些檢查都可以通過查詢使用者資料來輔助完成:

SELECT * FROM t_user WHERE uid=?

1.2 介面與抽象方法

在UserMapper介面新增updatePasswordByUid(Integer uid,String password,String modifiedUser,Date modifiedTime)抽象方法。

用註解來簡化xml設定時,@Param註解的作用是給引數命名,引數命名後就能根據名字得到引數值,正確的將引數傳入sql語句中。@Param("引數名")註解中的引數名需要和sql語句中的#{引數名}的引數名保持一致。

/**
 * 根據uid更新使用者的密碼
 * @param uid 使用者的id
 * @param password 新密碼
 * @param modifiedUser 最後修改執行人
 * @param modifiedTime 最後修改時間
 * @return 受影響的行數
 */
Integer updatePasswordByUid(
		@Param("uid") Integer uid, 
		@Param("password") String password, 
		@Param("modifiedUser") String modifiedUser, 
		@Param("modifiedTime") Date modifiedTime);

/**
 * 根據使用者id查詢使用者資料
 * @param uid 使用者id
 * @return 匹配的使用者資料,如果沒有匹配的使用者資料,則返回null
 */
User findByUid(Integer uid);

1.3 設定SQL對映

1.在UserMapper.xml中設定updatePasswordByUid()、findByUid()抽象方法的對映。

<!-- 根據uid更新使用者的密碼:
	 Integer updatePasswordByUid(
		@Param("uid") Integer uid, 
		@Param("password") String password, 
		@Param("modifiedUser") String modifiedUser, 
		@Param("modifiedTime") Date modifiedTime) -->
<update id="updatePasswordByUid">
	UPDATE
		t_user 
	SET
		password = #{password},
		modified_user = #{modifiedUser},
		modified_time = #{modifiedTime} 
	WHERE
		uid = #{uid}
</update>

<!-- 根據使用者id查詢使用者資料:User findByUid(Integer uid) -->
<select id="findByUid" resultMap="UserEntityMap">
	SELECT
		*
	FROM
		t_user
	WHERE
		uid = #{uid}
</select>

2.在UserMapperTests中編寫並執行單元測試。

@Test
public void updatePasswordByUid() {
	Integer uid = 7;
	String password = "123456";
	String modifiedUser = "超級管理員";
	Date modifiedTime = new Date();
	Integer rows = userMapper.updatePasswordByUid(uid, password, modifiedUser, modifiedTime);
	System.out.println("rows=" + rows);
}

@Test
public void findByUid() {
	Integer uid = 7;
	User result = userMapper.findByUid(uid);
	System.out.println(result);
}

2 使用者-修改密碼-業務層

2.1 規劃異常

1.使用者在修改密碼前,需要檢查使用者資料是否存在及是否被標記為“已刪除”。如果檢查不通過則應丟擲UserNotFoundException異常。

2.使用者修改密碼時,可能會因為輸入的原密碼錯誤導致修改失敗,則應丟擲PasswordNotMatchException異常。

3.在執行修改密碼時,如果返回的受影響行數與預期值不同,則應丟擲UpdateException異常。

4.建立com.cy.store.service.ex.UpdateException異常類,繼承自ServiceException類。

/** 更新資料的異常 */
public class UpdateException extends ServiceException {
	// Override Methods...
}

2.2 介面與抽象方法

在IUserService中新增changePassword(Integer uid, String username, String oldPassword, String newPassword)抽象方法。

/**
 * 修改密碼
 * @param uid 當前登入的使用者id
 * @param username 使用者名稱
 * @param oldPassword 原密碼
 * @param newPassword 新密碼
 */
public void changePassword(Integer uid, String username, String oldPassword, String newPassword);

2.3 實現抽象方法

1.在UserServiceImpl類中實現changePassword()抽象方法。

public void changePassword(Integer uid, String username, String oldPassword, String newPassword) {
	// 呼叫userMapper的findByUid()方法,根據引數uid查詢使用者資料
	// 檢查查詢結果是否為null
	// 是:丟擲UserNotFoundException異常

	// 檢查查詢結果中的isDelete是否為1
	// 是:丟擲UserNotFoundException異常

	// 從查詢結果中取出鹽值
	// 將引數oldPassword結合鹽值加密,得到oldMd5Password
	// 判斷查詢結果中的password與oldMd5Password是否不一致
	// 是:丟擲PasswordNotMatchException異常

	// 將引數newPassword結合鹽值加密,得到newMd5Password
	// 建立當前時間物件
	// 呼叫userMapper的updatePasswordByUid()更新密碼,並獲取返回值
	// 判斷以上返回的受影響行數是否不為1
	// 是:拋了UpdateException異常
}

2.changePassword()方法的具體程式碼。

String中的equals與contentEquals方法,都可以用來比較String物件內容是否相同。

@Override
public void changePassword(Integer uid, String username, String oldPassword, String newPassword) {
	// 呼叫userMapper的findByUid()方法,根據引數uid查詢使用者資料
	User result = userMapper.findByUid(uid);
	// 檢查查詢結果是否為null
	if (result == null) {
		// 是:丟擲UserNotFoundException異常
		throw new UserNotFoundException("使用者資料不存在");
	}
	
	// 檢查查詢結果中的isDelete是否為1
	if (result.getIsDelete().equals(1)) {
		// 是:丟擲UserNotFoundException異常
		throw new UserNotFoundException("使用者資料不存在");
	}
	
	// 從查詢結果中取出鹽值
	String salt = result.getSalt();
	// 將引數oldPassword結合鹽值加密,得到oldMd5Password
	String oldMd5Password = getMd5Password(oldPassword, salt);
	// 判斷查詢結果中的password與oldMd5Password是否不一致
	if (!result.getPassword().contentEquals(oldMd5Password)) {
		// 是:丟擲PasswordNotMatchException異常
		throw new PasswordNotMatchException("原密碼錯誤");
	}
	
	// 將引數newPassword結合鹽值加密,得到newMd5Password
	String newMd5Password = getMd5Password(newPassword, salt);
	// 建立當前時間物件
	Date now = new Date();
	// 呼叫userMapper的updatePasswordByUid()更新密碼,並獲取返回值
	Integer rows = userMapper.updatePasswordByUid(uid, newMd5Password, username, now);
	// 判斷以上返回的受影響行數是否不為1
	if (rows != 1) {
		// 是:丟擲UpdateException異常
		throw new UpdateException("更新使用者資料時出現未知錯誤,請聯絡系統管理員");
	}
}

3.在UserServiceTests中編寫並執行單元測試。

@Test
public void changePassword() {
    try {
        Integer uid = 5;
        String username = "lower";
        String oldPassword = "123456";
        String newPassword = "888888";
        userService.changePassword(uid, username, oldPassword, newPassword);
        System.out.println("密碼修改成功!");
    } catch (ServiceException e) {
        System.out.println("密碼修改失敗!" + e.getClass().getSimpleName());
        System.out.println(e.getMessage());
    }
}

3 使用者-修改密碼-控制器

3.1 處理異常

在使用者修改密碼的業務中丟擲了新的UpdateException異常,需要在BaseController類中進行處理。

@ExceptionHandler(ServiceException.class)
public JsonResult<Void> handleException(Throwable e) {
	JsonResult<Void> result = new JsonResult<Void>(e);
	if (e instanceof UsernameDuplicateException) {
		result.setState(4000);
	} else if (e instanceof UserNotFoundException) {
		result.setState(4001);
	} else if (e instanceof PasswordNotMatchException) {
		result.setState(4002);
	} else if (e instanceof InsertException) {
		result.setState(5000);
	} else if (e instanceof UpdateException) {
		result.setState(5001);
	}
	return result;
}

3.2 設計請求

設計使用者提交的請求,並設計響應的方式。

請求路徑:/users/change_password
請求引數:String oldPassword, String newPassword, HttpSession session
請求型別:POST
響應結果:JsonResult<Void>

3.3 處理請求

1.在UserController類中新增處理請求的changePassword(String oldPassword, String newPassword, HttpSession session)方法。

@RequestMapping("change_password")
public JsonResult<Void> changePassword(String oldPassword, String newPassword, HttpSession session) {
	// 呼叫session.getAttribute("")獲取uid和username
	// 呼叫業務物件執行修改密碼
	// 返回成功
	
	return null;
}

2.實現UserController控制器中的修改密碼方法的程式碼。

@RequestMapping("change_password")
public JsonResult<Void> changePassword(String oldPassword, String newPassword, HttpSession session) {
	// 呼叫session.getAttribute("")獲取uid和username
	Integer uid = getUidFromSession(session);
	String username = getUsernameFromSession(session);
	// 呼叫業務物件執行修改密碼
	iUserService.changePassword(uid, username, oldPassword, newPassword);
	// 返回成功
	return new JsonResult<Void>(OK);
}

3.啟動專案先登入,再存取http://localhost:8080/users/change_password?oldPassword=xx&newPassword=xx進行測試。

4 使用者-修改密碼-前端頁面

1.在password.html頁面中body標籤內部的最後,新增script標籤用於編寫JavaScript程式。

<script type="text/javascript">
    $("#btn-change-password").click(function() {
        $.ajax({
            url: "/users/change_password",
            type: "POST",
            data: $("#form-change-password").serialize(),
            dataType: "json",
            success: function(json) {
                if (json.state == 200) {
                    alert("修改成功!");
                } else {
                    alert("修改失敗!" + json.message);
                }
            }
        });
	});
</script>

2.啟動專案先登入,再存取http://localhost:8080/web/password.html頁面並進行修改密碼。

問題:如果無法正常將資料傳遞給後臺,重啟動系統和IDEA開發工具,登陸後便可修改密碼。

3.問題:在操作前端頁面時使用者進入修改密碼頁面,長時間停留在當前頁面未進行任何操作,將導致登入資訊過期。此時點選修改按鈕時,仍會向/users/change_password傳送請求,會被攔截器重定向到登入頁面。由於整個過程是由$.ajax()函數採用非同步的方式處理的,所以重定向也是由非同步任務完成的,在頁面中沒有任何表現就會出現“使用者登入資訊超時後點選按鈕沒有任何反應”的問題。

解決方案:可以在password.html頁面的$.ajax()中補充error屬性的設定,該屬性的值是一個回撥函數。當伺服器未正常響應狀態碼時,例如出現302、400、404、405、500等狀態碼時,將會呼叫該函數。

error: function (xhr) {
    alert("您的登入資訊已經過期,請重新登入!HTTP響應碼:" + xhr.status);
    location.href = "login.html";
}

個人資料

1 使用者-個人資料-持久層

1.1 規劃需要執行的SQL語句

1.執行修改使用者個人資料的SQL語句大致是:

UPDATE t_user SET phone=?, email=?, gender=?, modified_user=?, modified_time=? WHERE uid=?

2.在執行修改使用者資料之前,當用戶剛開啟修改資料的頁面時,就應把當前登入的使用者資訊顯示到頁面中。顯示使用者資料可以通過:

SELECT * FROM t_user WHERE uid=?

說明:

1.該查詢功能已經實現,無需再次開發;

2.在執行修改使用者資料之前,還應檢查使用者資料是否存在、是否標記為“已刪除”,也可以通過以上查詢來實現。

1.2 介面與抽象方法

在UserMapper介面中新增updateInfoByUid(User user)方法。

/**
 * 根據uid更新使用者資料
 * @param user 封裝了使用者id和新個人資料的物件
 * @return 受影響的行數
 */
Integer updateInfoByUid(User user);

1.3 設定SQL對映

1.在UserMapper.xml中設定Integer updateInfoByUid(User user)抽象方法的對映。

<!-- 根據uid更新使用者個人資料:Integer updateInfoByUid(User user) -->
<update id="updateInfoByUid">
	UPDATE
		t_user 
	SET
		<if test="phone != null">phone = #{phone},</if>
		<if test="email != null">email = #{email},</if>
		<if test="gender != null">gender = #{gender},</if>
		modified_user = #{modifiedUser},
		modified_time = #{modifiedTime}
	WHERE
		uid = #{uid}
</update>

2.在UserMapperTests中編寫並執行單元測試。

@Test
public void updateInfoByUid() {
    User user = new User();
    user.setUid(20);
    user.setPhone("17858802222");
    user.setEmail("admin@cy.com");
    user.setGender(1);
    user.setModifiedUser("系統管理員");
    user.setModifiedTime(new Date());
    Integer rows = userMapper.updateInfoByUid(user);
    System.out.println("rows=" + rows);
}

2 使用者-個人資料-業務層

2.1 規劃異常

1.關於使用者修改個人資料是由兩個功能組成的。

  • 開啟頁面時顯示當前登入的使用者的資訊;

  • 點選修改按鈕時更新使用者的資訊。

2.關於開啟頁面時顯示當前登入的使用者的資訊,可能會因為使用者資料不存在、使用者被標記為“已刪除”而無法正確的顯示頁面,則丟擲UserNotFoundException異常。

3.關於點選修改按鈕時更新使用者的資訊,在執行修改資料之前仍需再次檢查使用者資料是否存在、使用者是否被標記為“已刪除”,則可能丟擲UserNotFoundException異常。並且在執行修改資料過程中,還可能丟擲UpdateException異常。

2.2 介面與抽象方法

在IUserService介面中新增兩個抽象方法,分別對應以上兩個功能。

/**
 * 獲取當前登入的使用者的資訊
 * @param uid 當前登入的使用者的id
 * @return 當前登入的使用者的資訊
 */
User getByUid(Integer uid);

/**
 * 修改使用者資料
 * @param uid 當前登入的使用者的id
 * @param username 當前登入的使用者名稱
 * @param user 使用者的新的資料
 */
void changeInfo(Integer uid, String username, User user);

2.3 實現抽象方法

1.在UserServiceImpl實現類中實現getByUid(Integer uid)和changeInfo(Integer uid, String username, User user)以上兩個抽象方法。

@Override
public User getByUid(Integer uid) {
	// 呼叫userMapper的findByUid()方法,根據引數uid查詢使用者資料
	// 判斷查詢結果是否為null
	// 是:丟擲UserNotFoundException異常

	// 判斷查詢結果中的isDelete是否為1
	// 是:丟擲UserNotFoundException異常

	// 建立新的User物件
	// 將以上查詢結果中的username/phone/email/gender封裝到新User物件中

	// 返回新的User物件
	return null;
}

@Override
public void changeInfo(Integer uid, String username, User user) {
	// 呼叫userMapper的findByUid()方法,根據引數uid查詢使用者資料
	// 判斷查詢結果是否為null
	// 是:丟擲UserNotFoundException異常

	// 判斷查詢結果中的isDelete是否為1
	// 是:丟擲UserNotFoundException異常

	// 向引數user中補全資料:uid
	// 向引數user中補全資料:modifiedUser(username)
	// 向引數user中補全資料:modifiedTime(new Date())
	// 呼叫userMapper的updateInfoByUid(User user)方法執行修改,並獲取返回值
	// 判斷以上返回的受影響行數是否不為1
	// 是:丟擲UpdateException異常
	
}

2.getByUid(Integer uid)和changeInfo(Integer uid, String username, User user)方法的具體程式碼實現。

@Override
public User getByUid(Integer uid) {
	// 呼叫userMapper的findByUid()方法,根據引數uid查詢使用者資料
	User result = userMapper.findByUid(uid);
	// 判斷查詢結果是否為null
	if (result == null) {
		// 是:丟擲UserNotFoundException異常
		throw new UserNotFoundException("使用者資料不存在");
	}
 
	// 判斷查詢結果中的isDelete是否為1
	if (result.getIsDelete().equals(1)) {
		// 是:丟擲UserNotFoundException異常
		throw new UserNotFoundException("使用者資料不存在");
	}

	// 建立新的User物件
	User user = new User();
	// 將以上查詢結果中的username/phone/email/gender封裝到新User物件中
	user.setUsername(result.getUsername());
	user.setPhone(result.getPhone());
	user.setEmail(result.getEmail());
	user.setGender(result.getGender());
	
	// 返回新的User物件
	return user;
}

@Override
public void changeInfo(Integer uid, String username, User user) {
	// 呼叫userMapper的findByUid()方法,根據引數uid查詢使用者資料
	User result = userMapper.findByUid(uid);
	// 判斷查詢結果是否為null
	if (result == null) {
		// 是:丟擲UserNotFoundException異常
		throw new UserNotFoundException("使用者資料不存在");
	}

	// 判斷查詢結果中的isDelete是否為1
	if (result.getIsDelete().equals(1)) {
		// 是:丟擲UserNotFoundException異常
		throw new UserNotFoundException("使用者資料不存在");
	}

	// 向引數user中補全資料:uid
	user.setUid(uid);
	// 向引數user中補全資料:modifiedUser(username)
	user.setModifiedUser(username);
	// 向引數user中補全資料:modifiedTime(new Date())
	user.setModifiedTime(new Date());
	// 呼叫userMapper的updateInfoByUid(User user)方法執行修改,並獲取返回值
	Integer rows = userMapper.updateInfoByUid(user);
	// 判斷以上返回的受影響行數是否不為1
	if (rows != 1) {
		// 是:丟擲UpdateException異常
		throw new UpdateException("更新使用者資料時出現未知錯誤,請聯絡系統管理員");
	}
}

3.在UserServiceTests類中進行單元測試。

@Test
public void getByUid() {
    try {
        Integer uid = 20;
        User user = iUserService.getByUid(uid);
        System.out.println(user);
    } catch (ServiceException e) {
        System.out.println(e.getClass().getSimpleName());
        System.out.println(e.getMessage());
    }
}

@Test
public void changeInfo() {
    try {
        Integer uid = 20;
        String username = "資料管理員";
        User user = new User();
        user.setPhone("15512328888");
        user.setEmail("admin03@cy.cn");
        user.setGender(2);
        iUserService.changeInfo(uid, username, user);
        System.out.println("OK.");
    } catch (ServiceException e) {
        System.out.println(e.getClass().getSimpleName());
        System.out.println(e.getMessage());
    }
}

3 使用者-個人資料-控制器

3.1 處理異常

說明:無需再次開發。

3.2 設計請求

1.設計使用者提交顯示當前登入的使用者資訊的請求,並設計響應的方式。

請求路徑:/users/get_by_uid
請求引數:HttpSession session
請求型別:GET
響應結果:JsonResult<User>

2.設計使用者提交執行修改使用者資訊的請求,並設計響應的方式。

請求路徑:/users/change_info
請求引數:User user, HttpSession session
請求型別:POST
響應結果:JsonResult<Void>

3.3 處理請求

1.處理獲取使用者資訊請求

1.在UserController類中新增處理請求的getByUid()方法,並匯入org.springframework.web.bind.annotation.GetMapping包。

@GetMapping("get_by_uid")
public JsonResult<User> getByUid(HttpSession session) {
	// 從HttpSession物件中獲取uid
	// 呼叫業務物件執行獲取資料
	// 響應成功和資料
	return null;
}

2.getByUid(HttpSession session)方法中具體程式碼實現為。

@GetMapping("get_by_uid")
public JsonResult<User> getByUid(HttpSession session) {
    // 從HttpSession物件中獲取uid
    Integer uid = getUidFromSession(session);
    // 呼叫業務物件執行獲取資料
    User data = userService.getByUid(uid);
    // 響應成功和資料
    return new JsonResult<User>(OK, data);
}

3.完成後啟動專案,開啟瀏覽器先登入,再存取http://localhost:8080/users/get_by_uid請求進行測試。

2.處理修改使用者個人資訊請求

1.在UserController類中新增處理請求的changeInfo(User user, HttpSession session)方法。

@RequestMapping("change_info")
public JsonResult<Void> changeInfo(User user, HttpSession session) {
	// 從HttpSession物件中獲取uid和username
	// 呼叫業務物件執行修改使用者資料
	// 響應成功
	return null;
}

2.changeInfo(User user, HttpSession session)方法中具體程式碼實現為。

@RequestMapping("change_info")
public JsonResult<Void> changeInfo(User user, HttpSession session) {
	// 從HttpSession物件中獲取uid和username
	Integer uid = getUidFromSession(session);
	String username = getUsernameFromSession(session);
	// 呼叫業務物件執行修改使用者資料
	userService.changeInfo(uid, username, user);
	// 響應成功
	return new JsonResult<Void>(OK);
}

3.完成後啟動專案,開啟瀏覽器先登入,再存取http://localhost:8080/users/change_info?phone=17858800000&email=admin07@cy.com&gender=1進行測試。

4 使用者-個人資料-前端頁面

1.在userdata.html頁面中body標籤內部的最後,新增script標籤用於編寫JavaScript程式。

<script type="text/javascript">
    $(document).ready(function() {
        $.ajax({
            url: "/users/get_by_uid",
            type: "GET",
            dataType: "json",
            success: function(json) {
                if (json.state == 200) {
                    console.log("username=" + json.data.username);
                    console.log("phone=" + json.data.phone);
                    console.log("email=" + json.data.email);
                    console.log("gender=" + json.data.gender);

                    $("#username").val(json.data.username);
                    $("#phone").val(json.data.phone);
                    $("#email").val(json.data.email);

                    let radio = json.data.gender == 0 ? $("#gender-female") : $("#gender-male");
                    radio.prop("checked", "checked");
                } else {
                    alert("獲取使用者資訊失敗!" + json.message);
                }
            }
        });
	});

    $("#btn-change-info").click(function() {
        $.ajax({
            url: "/users/change_info",
            type: "POST",
            data: $("#form-change-info").serialize(),
            dataType: "json",
            success: function(json) {
                if (json.state == 200) {
                    alert("修改成功!");
                    location.href = "login.html";
                } else {
                    alert("修改失敗!" + json.message);
                }
            },
            error: function(xhr) {
                alert("您的登入資訊已經過期,請重新登入!HTTP響應碼:" + xhr.status);
                location.href = "login.html";
            }
        });
    });
</script>

2.完成後啟動專案,開啟瀏覽器先登入,再存取http://localhost:8080/web/userdata.html頁面並進行使用者個人資料的修改測試。

總結

到此這篇關於springboot使用者資料修改的文章就介紹到這了,更多相關springboot使用者資料修改內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com