中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

springboot用戶數據怎么修改

發布時間:2022-04-06 17:30:44 來源:億速云 閱讀:495 作者:iii 欄目:開發技術

這篇文章主要介紹“springboot用戶數據怎么修改”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“springboot用戶數據怎么修改”文章能幫助大家解決問題。

    修改密碼

    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用戶數據怎么修改”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    石棉县| 原阳县| 裕民县| 兰坪| 济源市| 景德镇市| 奉新县| 海晏县| 双流县| 锡林浩特市| 庆安县| 百色市| 漠河县| 义马市| 腾冲县| 托里县| 卢龙县| 淳安县| 厦门市| 黑水县| 镇宁| 西吉县| 双城市| 金乡县| 吕梁市| 界首市| 连云港市| 扎兰屯市| 长岛县| 连山| 台北市| 临高县| 大英县| 苍南县| 昭通市| 临湘市| 吴川市| 石景山区| 商城县| 尼木县| 峨眉山市|