49. 主页-热销排行-实体类
创建cn.tedu.store.entity.Product实体类,继承自BaseEntity:
/**
* 商品数据的实体类
*/
public class Product extends BaseEntity {
private static final long serialVersionUID = -199568590252555336L;
private Integer id;
private Integer categoryId;
private String itemType;
private String title;
private String sellPoint;
private Long price;
private Integer num;
private Integer status;
private String image;
private Integer priority;
// ...
}
50. 主页-热销排行-持久层
(a) SQL
应该按照数据的priority降序排列,取出排名最靠前的4样商品,则:
select * from t_product order by priority desc limit 0, 4
(b) 接口与抽象方法
创建cn.tedu.store.mapper.ProductMapper接口,声明抽象方法:
List<Product> findHotList();
© 配置映射
复制得到ProductMapper.xml配置文件,修改根节点的namespace属性值对应以上接口,然后配置以上抽象方法的映射:
<resultMap id="ProductEntityMap"
type="cn.tedu.store.entity.Product">
<id column="id" property="id"/>
<result column="category_id" property="categoryId"/>
<result column="item_type" property="itemType"/>
<result column="title" property="title"/>
<result column="sell_point" property="sellPoint"/>
<result column="price" property="price"/>
<result column="num" property="num"/>
<result column="image" property="image"/>
<result column="status" property="status"/>
<result column="priority" property="priority"/>
<result column="created_user" property="createdUser"/>
<result column="created_time" property="createdTime"/>
<result column="modified_user" property="modifiedUser"/>
<result column="modified_time" property="modifiedTime"/>
</resultMap>
<!-- 查询热销的前4名的商品列表 -->
<!-- List<Product> findHotList() -->
<select id="findHotList"
resultMap="ProductEntityMap">
SELECT
*
FROM
t_product
ORDER BY
priority DESC
LIMIT
0,4
</select>
创建测试类,编写并执行单元测试:
@Test
public void findHotList() {
List<Product> list = mapper.findHotList();
System.err.println("count=" + list.size());
for (Product item : list) {
System.err.println(item);
}
}
51. 主页-热销排行-业务层
(a) 规划异常
无
(b) 接口与抽象方法
创建cn.tedu.store.service.IProductService接口,然后添加抽象方法:
List<Product> getHotList();
© 实现
创建cn.tedu.store.service.impl.ProductServiceImpl,实现IProductService接口,添加@Service注解,在类中声明@Autowired private ProductMapper productMapper;持久层对象。
私有化实现持久层接口中的方法:
/**
* 查询热销的前4名的商品列表
* @return 热销的前4名的商品列表
*/
private List<Product> findHotList() {
return productMapper.findHotList();
}
重写IProductService接口中的抽象方法:
@Override
public List<Product> getHotList() {
List<Product> list = findHotList();
for (Product product : list) {
product.setCategoryId(null);
product.setItemType(null);
product.setSellPoint(null);
product.setNum(null);
product.setStatus(null);
product.setPriority(null);
product.setCreatedUser(null);
product.setCreatedTime(null);
product.setModifiedUser(null);
product.setModifiedTime(null);
}
return list;
}
创建测试类,编写并执行单元测试:
@Test
public void getHotList() {
List<Product> list = service.getHotList();
System.err.println("count=" + list.size());
for (Product item : list) {
System.err.println(item);
}
}
52. 主页-热销排行-控制器层
(a) 处理异常
无
(b) 设计请求
请求路径:/products/hot
请求参数:无
请求类型:GET
响应数据:JsonResult<List<Product>>
是否拦截:否,需要在拦截器的配置中将 /products/** 设置为白名单
© 处理请求
先找到拦截器的配置,将/products/**设置为白名单。
创建cn.tedu.store.controller.ProductController控制器类,继承自BaseController,在类之前添加@RestController和@RequestMapping("products")注解,在类中声明@Autowired private IProductService productService;业务层对象。
然后,在类中添加处理请求的方法:
@GetMapping("hot")
public JsonResult<List<Product>> getHotList() {
// 查询
// 返回
}
完成后,打开浏览器,无需登录,通过http://localhost:8080/products/hot即可访问。
53. 主页-热销排行-前端界面
参考收货地址列表的处理方式。
54. 商品-查看详情-持久层
(a) 规划SQL语句
select * from t_product where id=?
(b) 接口与抽象方法
Product findById(Integer id);
© 配置映射
映射:
<!-- 根据商品id查询商品详情 -->
<!-- Product findById(Integer id) -->
<select id="findById"
resultMap="ProductEntityMap">
SELECT
*
FROM
t_product
WHERE
id=#{id}
</select>
测试:
@Test
public void findById() {
Integer id = 10000022;
Product data = mapper.findById(id);
System.err.println(data);
}
55. 商品-查看详情-业务层
(a) 规划异常
可能存在:ProductNotFoundException。
(b) 接口与抽象方法
Product getById(Integer id) throws ProductNotFoundException;
© 实现抽象方法
私有化实现持久层接口中的方法:
/**
* 根据商品id查询商品详情
* @param id 商品id
* @return 匹配的商品详情,如果没有匹配的数据,则返回null
*/
private Product findById(Integer id) {
return productMapper.findById(id);
}
实现业务层接口中的抽象方法:
public Product getById(Integer id) throws ProductNotFoundException {
// 调用私有方法执行查询
// 判断查询结果是否为null:ProductNotFoundException
// 将查询结果中的部分属性设置为null,例如隐藏属性和日志
// 返回结果
}
实现代码:
@Override
public Product getById(Integer id) {
// 调用私有方法执行查询
Product result = findById(id);
// 判断查询结果是否为null:ProductNotFoundException
if (result == null) {
throw new ProductNotFoundException(
"查询商品详情失败!尝试访问的数据不存在!");
}
// 将查询结果中的部分属性设置为null,例如隐藏属性和日志
result.setPriority(null);
result.setCreatedUser(null);
result.setCreatedTime(null);
result.setModifiedUser(null);
result.setModifiedTime(null);
// 返回结果
return result;
}
测试:
@Test
public void getById() {
Integer id = 10000022;
Product data = service.getById(id);
System.err.println(data);
}
56. 商品-查看详情-控制器层
(a) 统一处理异常
处理ProductNotFoundException。
(b) 设计请求
设计“商品-查看详情”的请求方式:
请求路径:/products/{id}/details
请求参数:@PathVariable("id") Integer id
请求方式:GET
响应数据:JsonResult<Product>
是否拦截:否,不拦截,已经将 /products/** 添加到白名单,所以无需修改配置
© 处理请求
@GetMapping("{id}/details")
public JsonResult<Product> getById(
@PathVariable("id") Integer id) {
// 调用业务层对象执行查询
Product data = productService.getById(id);
// 响应成功与数据
return new JsonResult<>(SUCCESS, data);
}
http://localhost:8080/products/10000022/details
57. 商品-查看详情-前端界面
58. 购物车-创建数据表
CREATE TABLE t_cart (
cid INT AUTO_INCREMENT COMMENT '购物车数据id',
uid INT NOT NULL COMMENT '用户id',
pid INT NOT NULL COMMENT '商品id',
num INT NOT NULL COMMENT '数量',
price BIGINT NOT NULL COMMENT '商品单价',
created_user VARCHAR(50) COMMENT '创建人',
created_time DATETIME COMMENT '创建时间',
modified_user VARCHAR(50) COMMENT '最后修改人',
modified_time DATETIME COMMENT '最后修改时间',
PRIMARY KEY (cid)
) DEFAULT CHARSET=UTF8;
59. 购物车-创建实体类
创建cn.tedu.store.entity.Cart继承自BaseEntity:
60. 购物车-加入购物车-持久层
(a) 规划SQL语句
把商品添加到购物车:
insert into t_cart (除了cid以外的所有字段) values (...);
并不是每次“加入购物车”都会产生新的购物车数据,如果该用户添加的商品在购物车已经存在,则应该只增加数量:
update t_cart set num=?(新值),modified_user=?,modified_time=? where cid=?
到底是应该插入新的数据,还是只增加数量,应该先“检查该用户是否已经将该商品添加到购物车”:
select * from t_cart where uid=? and pid=?
(b) 接口与抽象方法
创建cn.tedu.store.mapper.CartMapper接口,并添加抽象方法:
Integer insert(Cart cart);
Integer updateNum(
@Param("cid") Integer cid,
@Param("num") Integer num,
@Param("username") String username,
@Param("modifiedTime") Date modifiedTime);
Cart findByUidAndPid(
@Param("uid") Integer uid,
@Param("pid") Integer pid);
© 配置映射
映射:
<mapper namespace="cn.tedu.store.mapper.CartMapper">
<resultMap id="CartEntityMap"
type="cn.tedu.store.entity.Cart">
<id column="cid" property="cid"/>
<result column="uid" property="uid"/>
<result column="pid" property="pid"/>
<result column="num" property="num"/>
<result column="price" property="price"/>
<result column="created_user" property="createdUser"/>
<result column="created_time" property="createdTime"/>
<result column="modified_user" property="modifiedUser"/>
<result column="modified_time" property="modifiedTime"/>
</resultMap>
<!-- 插入购物车数据 -->
<!-- Integer insert(Cart cart) -->
<insert id="insert"
useGeneratedKeys="true"
keyProperty="cid">
INSERT INTO t_cart (
uid, pid,
num, price,
created_user, created_time,
modified_user, modified_time
) VALUES (
#{uid}, #{pid},
#{num}, #{price},
#{createdUser}, #{createdTime},
#{modifiedUser}, #{modifiedTime}
)
</insert>
<!-- 修改商品在购物车中的数量 -->
<!-- Integer updateNum(
@Param("cid") Integer cid,
@Param("num") Integer num,
@Param("username") String username,
@Param("modifiedTime") Date modifiedTime) -->
<update id="updateNum">
UPDATE
t_cart
SET
num=#{num},
modified_user=#{username},
modified_time=#{modifiedTime}
WHERE
cid=#{cid}
</update>
<!-- 根据用户id和商品id查询购物车数据 -->
<!-- Cart findByUidAndPid(
@Param("uid") Integer uid,
@Param("pid") Integer pid) -->
<select id="findByUidAndPid"
resultMap="CartEntityMap">
SELECT
*
FROM
t_cart
WHERE
uid=#{uid} AND pid=#{pid}
</select>
</mapper>
测试:
@RunWith(SpringRunner.class)
@SpringBootTest
public class CartMapperTests {
@Autowired
CartMapper mapper;
@Test
public void insert() {
Cart cart = new Cart();
cart.setUid(1);
cart.setPid(2);
cart.setNum(3);
cart.setPrice(4L);
Integer rows = mapper.insert(cart);
System.err.println("rows=" + rows);
}
@Test
public void updateNum() {
Integer cid = 1;
Integer num = 10;
String username = "哈喽";
Date modifiedTime = new Date();
Integer rows = mapper.updateNum(cid, num, username, modifiedTime);
System.err.println("rows=" + rows);
}
@Test
public void findByUidAndPid() {
Integer uid = 1;
Integer pid = 2;
Cart cart = mapper.findByUidAndPid(uid, pid);
System.err.println(cart);
}
}
61. 购物车-加入购物车-业务层
(a) 规划异常
此次的查询没有异常。
可能插入数据,也可能修改数据,则可能抛出对应的异常。
(b) 接口与抽象方法
创建cn.tedu.store.service.ICartService业务层接口,并添加抽象方法:
void addToCart(Integer uid, Integer pid, Integer num, String username);
© 实现抽象方法
创建cn.tedu.store.service.impl.CartServiceImpl,实现ICartService接口,添加@Service注解,在类中声明@Autowired private CartMapper cartMapper;持久层对象,另声明@Autowired private IProductService productService;商品的业务层对象。
私有化实现持久层接口中的3个方法:
/**
* 插入购物车数据
* @param cart 购物车数据
* @throws InsertException 插入数据异常
*/
private void insert(Cart cart) throws InsertException {
Integer rows = cartMapper.insert(cart);
if (rows != 1) {
throw new InsertException(
"将商品添加到购物车失败!插入数据时发生未知错误!");
}
}
/**
* 修改商品在购物车中的数量
* @param cid 购物车数据的id
* @param num 新的数量
* @param username 操作执行人
* @param modifiedTime 操作执行时间
* @throws UpdateException 更新数据异常
*/
private void updateNum(Integer cid, Integer num,
String username, Date modifiedTime) {
Integer rows = cartMapper.updateNum(cid, num, username, modifiedTime);
if (rows != 1) {
throw new UpdateException(
"调整商品数量失败!修改数据时发生未知错误!");
}
}
/**
* 根据用户id和商品id查询购物车数据
* @param uid 用户id
* @param pid 商品id
* @return 匹配的购物车数据,如果没有匹配的数据,则返回null
*/
private Cart findByUidAndPid(Integer uid, Integer pid) {
return cartMapper.findByUidAndPid(uid, pid);
}
重写ICartService接口中的抽象方法:
public void addToCart(Integer uid, Integer pid, Integer num, String username) {
// 基于参数uid和pid查询数据
// 判断查询结果是否为null
// 是:需要新增购物车数据
// 自行创建Cart对象
// 调用productService的getById()方法获取单价并封装到Cart对象
// 将uid、pid、num参数封装到Cart对象
// 创建当前时间对象,将时间和username封装到Cart对象的日志属性
// 执行插入
// 否:需要修改欲购物的商品的数量
// 从查询结果中获取当前数量num和数据的cid
// 将以上查询结果中的当前数量num和参数增量num相加,得到新的数量
// 执行更新数量
}
测试:
@Test
public void addToCart() {
try {
Integer uid = 100;
Integer pid = 10000017;
Integer num = 3;
String username = "土豪";
service.addToCart(uid, pid, num, username);
System.err.println("OK.");
} catch (ServiceException e) {
System.err.println(e.getClass().getName());
System.err.println(e.getMessage());
}
}
62. 购物车-加入购物车-控制器层
(a) 统一处理异常
(b) 设计请求
设计“购物车-加入购物车”的请求方式:
请求路径:/users/reg
请求参数:User user
请求方式:POST
响应数据:JsonResult<Void>
© 处理请求
博客详细介绍了电商系统中主页热销排行、商品查看详情、购物车等模块的开发。涵盖实体类、持久层、业务层、控制器层和前端界面的开发步骤,包括 SQL 规划、接口与抽象方法创建、配置映射、异常处理、请求设计与处理等内容。
2万+

被折叠的 条评论
为什么被折叠?



