默认收货地址
1 默认收货地址-持久层
1.1 规划需要执行的SQL语句
1.将某用户的所有收货地址设置为非默认地址(是否默认:0-不默认,1-默认)。
update t_address set is_default=0 where uid=?
2.将某用户指定的收货地址设置为默认地址。
update t_address set is_default=1, modified_user=?, modified_time=? where aid=?
3.检查该收货地址是否存在,并检查数据归属是否正确。可根据收货地址aid值,查询收货地址详情数据。
select * from t_address where aid=?
1.2 接口与抽象方法
在AddressMapper接口中声明三个抽象方法。
/**
* 将某用户的所有收货地址设置为非默认地址
* @param uid 收货地址归属的用户id
* @return 受影响的行数
*/
Integer updateNonDefaultByUid(Integer uid);
/**
* 将指定的收货地址设置为默认地址
* @param aid 收货地址id
* @param modifiedUser 修改执行人
* @param modifiedTime 修改时间
* @return 受影响的行数
*/
Integer updateDefaultByAid(
@Param("aid") Integer aid,
@Param("modifiedUser") String modifiedUser,
@Param("modifiedTime") Date modifiedTime);
/**
* 根据收货地址aid值,查询收货地址详情
* @param aid 收货地址id
* @return 匹配的收货地址详情,如果没有匹配的数据,则返回null
*/
Address findByAid(Integer aid);
1.3 配置SQL映射
1.在AddressMapper.xml映射文件,配置以上三个抽象方法的映射。
<!-- 将某用户的所有收货地址设置为非默认地址:Integer updateNonDefaultByUid(Integer uid) -->
<update id="updateNonDefaultByUid">
UPDATE
t_address
SET
is_default=0
WHERE
uid=#{uid}
</update>
<!-- 将指定的收货地址设置为默认地址:
Integer updateDefaultByAid(
@Param("aid") Integer aid,
@Param("modifiedUser") String modifiedUser,
@Param("modifiedTime") Date modifiedTime) -->
<update id="updateDefaultByAid">
UPDATE
t_address
SET
is_default=1,
modified_user=#{modifiedUser},
modified_time=#{modifiedTime}
WHERE
aid=#{aid}
</update>
<!-- 根据收货地址aid值,查询收货地址详情:Address findByAid(Integer aid) -->
<select id="findByAid" resultMap="AddressEntityMap">
SELECT
*
FROM
t_address
WHERE
aid=#{aid}
</select>
2.在AddressMapperTests类中编写并执行以上三个抽象方法的测试。
@Test
public void updateNonDefaultByUid() {
Integer uid = 26;
Integer rows = addressMapper.updateNonDefaultByUid(uid);
System.out.println("rows=" + rows);
}
@Test
public void updateDefaultByAid() {
Integer aid = 11;
String modifiedUser = "管理员";
Date modifiedTime = new Date();
Integer rows = addressMapper.updateDefaultByAid(aid, modifiedUser, modifiedTime);
System.out.println("rows=" + rows);
}
@Test
public void findByAid() {
Integer aid = 11;
Address result = addressMapper.findByAid(aid);
System.out.println(result);
}
2 默认收货地址-业务层
2.1 规划异常
1.在执行设置默认收货地址之前,需要先检查该收货地址数据是否存在,如果不存在则抛出AddressNotFoundException异常。
2.然后还需要检查数据归属是否正确,也就是不可以操作他人的数据,如果该数据中记录的uid与当前登录的用户的uid不一致,则抛出AccessDeniedException异常。
3.检查通过后先全部设置为非默认,然后将指定的收货地址设置为默认;这两种操作都是更新数据的操作,则可能抛出UpdateException异常。
4.在com.cy.store.service.ex包下创建AddressNotFoundException和AccessDeniedException异常类。
package com.cy.store.service.ex;
/** 收货地址数据不存在的异常 */
public class AddressNotFoundException extends ServiceException {
// Override Methods...
}
package com.cy.store.service.ex;
/** 非法访问的异常 */
public class AccessDeniedException extends ServiceException {
// Override Methods...
}
2.2 接口与抽象方法
在IAddressService接口中添加setDefault(Integer aid, Integer uid, String username)抽象方法。
/**
* 设置默认收货地址
* @param aid 收货地址id
* @param uid 归属的用户id
* @param username 当前登录的用户名
*/
void setDefault(Integer aid, Integer uid, String username);
2.3 实现抽象方法
1.在AddressServiceImpl类中重写setDefault(Integer aid, Integer uid, String username)方法。该方法需要添加@Transactional注解。
事务:基于Spring JDBC的事务(Transaction)处理,使用事务可以保证一系列的增删改操作,要么全部执行成功,要么全部执行失败。@Transactional注解可以用来修饰类也可以用来修饰方法。如果添加在业务类之前,则该业务类中的方法均以事务的机制运行,但是一般并不推荐这样处理。
@Transactional
@Override
public void setDefault(Integer aid, Integer uid, String username) {
// 根据参数aid,调用addressMapper中的findByAid()查询收货地址数据
// 判断查询结果是否为null
// 是:抛出AddressNotFoundException
// 判断查询结果中的uid与参数uid是否不一致(使用equals()判断)
// 是:抛出AccessDeniedException:非法访问
// 调用addressMapepr的updateNonDefaultByUid()将该用户的所有收货地址全部设置为非默认,并获取返回的受影响的行数
// 判断受影响的行数是否小于1(不大于0)
// 是:抛出UpdateException
// 调用addressMapepr的updateDefaultByAid()将指定aid的收货地址设置为默认,并获取返回的受影响的行数
// 判断受影响的行数是否不为1
// 是:抛出UpdateException
}
2.setDefault(Integer aid, Integer uid, String username)方法的具体代码实现。
@Transactional
@Override
public void setDefault(Integer aid, Integer uid, String username) {
// 根据参数aid,调用addressMapper中的findByAid()查询收货地址数据
Address result = addressMapper.findByAid(aid);
// 判断查询结果是否为null
if (result == null) {
// 是:抛出AddressNotFoundException
throw new AddressNotFoundException("尝试访问的收货地址数据不存在");
}
// 判断查询结果中的uid与参数uid是否不一致(使用equals()判断)
if (!result.getUid().equals(uid)) {
// 是:抛出AccessDeniedException
throw new AccessDeniedException("非法访问的异常");
}
// 调用addressMapper的updateNonDefaultByUid()将该用户的所有收货地址全部设置为非默认,并获取返回受影响的行数
Integer rows = addressMapper.updateNonDefaultByUid(uid);
// 判断受影响的行数是否小于1(不大于0)
if (rows < 1) {
// 是:抛出UpdateException
throw new UpdateException("设置默认收货地址时出现未知错误[1]");
}
// 调用addressMapper的updateDefaultByAid()将指定aid的收货地址设置为默认,并获取返回的受影响的行数
rows = addressMapper.updateDefaultByAid(aid, username, new Date());
// 判断受影响的行数是否不为1
if (rows != 1) {
// 是:抛出UpdateException
throw new UpdateException("设置默认收货地址时出现未知错误[2]");
}
}
3.在AddressServiceTests测试类,编写并执行单元测试。
@Test
public void setDefault() {
try {
Integer aid = 13;
Integer uid = 27;
String username = "系统管理员";
addressService.setDefault(aid, uid, username);
System.out.println("OK.");
} catch (ServiceException e) {
System.out.println(e.getClass().getSimpleName());
System.out.println(e.getMessage());
}
}
3 默认收货地址-控制器
3.1 处理异常
在BaseController类中添加处理AddressNotFoundException和AccessDeniedException的异常。
// ...
else if (e instanceof AddressNotFoundException) {
result.setState(4004);
} else if (e instanceof AccessDeniedException) {
result.setState(4005);
}
// ...
3.2 设计请求
设计用户提交的请求,并设计响应的方式。
请求路径:/addresses/{aid}/set_default
请求参数:@PathVaraible("aid") Integer aid, HttpSession sesion
请求类型:POST
响应结果:JsonResult<Void>
REST即表述性状态传递(Representational State Transfer,简称REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。它是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可伸缩性。
3.3 处理请求
1.在AddressController类中添加处理请求的setDefault(@PathVariable(“aid”) Integer aid, HttpSession session)方法。
@RequestMapping("{aid}/set_default")
public JsonResult<Void> setDefault(@PathVariable("aid") Integer aid, HttpSession session) {
Integer uid = getUidFromSession(session);
String username = getUsernameFromSession(session);
addressService.setDefault(aid, uid, username);
return new JsonResult<Void>(OK);
}
2.完成后启动项目,打开浏览器先登录,再访问http://localhost:8080/addresses/13/set_default进行测试。
4 默认收货地址-前端页面
1.在address.html页面中body标签内部的script标签内,添加设置用户默认收货地址的代码。
function setDefault(aid) {
$.ajax({
url: "/addresses/" + aid + "/set_default",
type: "POST",
dataType: "JSON",
success: function(json) {
if (json.state == 200) {
showAddressList();
} else {
alert("设置默认收货地址失败!" + json.message);
}
},
error: function(xhr) {
alert("您的登录信息已经过期,请重新登录!HTTP响应码:" + xhr.status);
location.href = "login.html";
}
});
}
2.给showAddressList()方法中的“设为默认”超链接按钮添加设置默认收货地址的点击事件。
<td><a onclick="setDefault(#{aid})" class="btn btn-xs add-def btn-default">设为默认</a></td>
3.完成后启动项目,打开浏览器先登录,再访问http://localhost:8080/web/address.html页面,点击“设为默认”超链接按钮进行功能测试。
删除收货地址
1 删除收货地址-持久层
1.1 规划需要执行的SQL语句
1.在删除之前,需检查数据是否存在,数据归属是否正确。此功能已完成,无需再次开发。
2.删除指定的收货地址的SQL语句大致是。
delete from t_address where aid=?
3.如果删除的这条数据是默认收货地址,则应该将剩余的收货地址中的某一条设置为默认收货地址,可以设定规则“将最近修改的设置为默认收货地址”,要实现此功能就必须要知道“最近修改的收货地址的id是多少”。则通过以下查询语句完成。
select * from t_address where uid=? order by modified_time desc limit 0,1
4.在执行以上操作之前,还需检查该用户的收货地址数据的数量,如果删除的收货地址是最后一条收货地址,则删除成功后无需再执行其他操作。统计收货地址数量的功能此前已经完成,无需再次开发。
1.2 接口与抽象方法
在AddressMapper接口中添加抽象方法。
/**
* 根据收货地址id删除数据
* @param aid 收货地址id
* @return 受影响的行数
*/
Integer deleteByAid(Integer aid);
/**
* 查询某用户最后修改的收货地址
* @param uid 归属的用户id
* @return 该用户最后修改的收货地址,如果该用户没有收货地址数据则返回null
*/
Address findLastModified(Integer uid);
1.3 配置SQL映射
1.在AddressMapper.xml文件中添加以上两个抽象方法的映射。
<!-- 根据收货地址id删除数据:Integer deleteByAid(Integer aid) -->
<delete id="deleteByAid">
DELETE FROM
t_address
WHERE
aid=#{aid}
</delete>
<!-- 查询某用户最后修改的收货地址:Address findLastModified(Integer uid) -->
<select id="findLastModified" resultMap="AddressEntityMap">
SELECT
*
FROM
t_address
WHERE
uid=#{uid}
ORDER BY
modified_time DESC
LIMIT 0,1
</select>
2.在AddressMapperTests测试类中添加单元测试方法。
@Test
public void deleteByAid() {
Integer aid = 4;
Integer rows = addressMapper.deleteByAid(aid);
System.out.println("rows=" + rows);
}
@Test
public void findLastModified() {
Integer uid = 30;
Address result = addressMapper.findLastModified(uid);
System.out.println(result);
}
2 删除收货地址-业务层
2.1 规划异常
在执行删除操作时,可能会删除数据失败,此时抛出DeleteException异常。在创建com.cy.store.service.ex.DeleteException异常类,并继承自ServiceException类。
package com.cy.store.service.ex;
/** 删除数据失败的异常 */
public class DeleteException extends ServiceException {
// Override Methods...
}
2.2 接口与抽象方法
在IAddressService接口中添加删除收货地址的抽象方法。
/**
* 删除收货地址
* @param aid 收货地址id
* @param uid 归属的用户id
* @param username 当前登录的用户名
*/
void delete(Integer aid, Integer uid, String username);
2.3 实现抽象方法
1.在AddressServiceImpl实现类中实现以上两个抽象方法。
@Transactional
@Override
public void delete(Integer aid, Integer uid, String username) {
// 根据参数aid,调用findByAid()查询收货地址数据
Address result = addressMapper.findByAid(aid);
// 判断查询结果是否为null
if (result == null) {
// 是:抛出AddressNotFoundException
throw new AddressNotFoundException("尝试访问的收货地址数据不存在");
}
// 判断查询结果中的uid与参数uid是否不一致(使用equals()判断)
if (!result.getUid().equals(uid)) {
// 是:抛出AccessDeniedException:非法访问
throw new AccessDeniedException("非常访问");
}
// 根据参数aid,调用deleteByAid()执行删除
Integer rows1 = addressMapper.deleteByAid(aid);
if (rows1 != 1) {
throw new DeleteException("删除收货地址数据时出现未知错误,请联系系统管理员");
}
// 判断查询结果中的isDefault是否为0
if (result.getIsDefault() == 0) {
return;
}
// 调用持久层的countByUid()统计目前还有多少收货地址
Integer count = addressMapper.countByUid(uid);
// 判断目前的收货地址的数量是否为0
if (count == 0) {
return;
}
// 调用findLastModified()找出用户最近修改的收货地址数据
Address lastModified = addressMapper.findLastModified(uid);
// 从以上查询结果中找出aid属性值
Integer lastModifiedAid = lastModified.getAid();
// 调用持久层的updateDefaultByAid()方法执行设置默认收货地址,并获取返回的受影响的行数
Integer rows2 = addressMapper.updateDefaultByAid(lastModifiedAid, username, new Date());
// 判断受影响的行数是否不为1
if (rows2 != 1) {
// 是:抛出UpdateException
throw new UpdateException("更新收货地址数据时出现未知错误,请联系系统管理员");
}
}
2.在AddressServiceTests测试类中添加单元测试方法。
@Test
public void delete() {
try {
Integer aid = 18;
Integer uid = 30;
String username = "明明";
addressService.delete(aid, uid, username);
System.out.println("OK.");
} catch (ServiceException e) {
System.out.println(e.getClass().getSimpleName());
System.out.println(e.getMessage());
}
}
3 删除收货地址-控制器
3.1 处理异常
在BaseController类中添加DeleteException异常的处理。
// ...
else if (e instanceof DeleteException) {
result.setState(5002);
}
// ...
3.2 设计请求
设计用户提交的请求,并设计响应的方式。
请求路径:/addresses/{aid}/delete
请求参数:@PathVariable("aid") Integer aid, HttpSession session
请求类型:POST
响应结果:JsonResult<Void>
3.3 处理请求
1.在AddressController类中添加处理请求的delete()方法。
@RequestMapping("{aid}/delete")
public JsonResult<Void> delete(@PathVariable("aid") Integer aid, HttpSession session) {
Integer uid = getUidFromSession(session);
String username = getUsernameFromSession(session);
addressService.delete(aid, uid, username);
return new JsonResult<Void>(OK);
}
2.完成后启动项目,打开浏览器先登录,再访问http://localhost:8080/addresses/26/delete进行测试。
4 删除收货地址-前端页面
1.在address.html页面中body标签内部的script标签内,添加设置用户删除收货地址的代码。
function deleteByAid(aid) {
$.ajax({
url: "/addresses/" + aid + "/delete",
type: "POST",
dataType: "JSON",
success: function(json) {
if (json.state == 200) {
showAddressList();
} else {
alert("删除收货地址失败!" + json.message);
}
},
error: function(json) {
alert("您的登录信息已经过期,请重新登录!HTTP响应码:" + json.status);
location.href = "login.html";
}
});
}
2.给showAddressList()方法中的“设为默认”超链接按钮添加设置默认收货地址的点击事件。
<td>
<a onclick="deleteByAid(#{aid})" class="btn btn-xs add-del btn-info">
<span class="fa fa-trash-o"></span> 删除
</a>
</td>
3.完成后启动项目,打开浏览器先登录,再访问http://localhost:8080/web/address.html页面,点击“删除”超链接按钮进行功能测试。
本期到这就结束了,点一下关注再走吧!!关注一波不迷路!!
分享不易,耗时耗力,麻烦给个不要钱的关注和赞吧
承接毕设指导,技术答疑,学习路上缺少导师的同学可以私信我
更多学习资料,公众号:墨轩学习网,B站:墨轩大楼