SpringBoot电脑商城项目--删除收获地址+热销排行

删除收获地址

1 删除收获地址-持久层

1.1 规划sql语句

  • 在删除操作之前判断该数据是否存在,判断该条地址的归属是否是当前的用户
  • 执行删除收货地址的操作

delete from t_address where aid=?

  • 如果用户删除的时默认地址,将剩下地址的某一条作为默认收货地址,自定义规则是:最新修改的收货地址信息是默认地址,可以通过修改时间进行降序排列

        limit 0,1 limit(n-1)*n,pageSize,第一个参数时第几页,第二个参数是当前页展示多少条

select * from t_address where uid=? order by modified_time DESC limit 0,1

  • 如果用户本身只有一条收货地址,删除后就不用进行其他操作了

1.2 编写接口层以及抽象方法

/*** 根据aid删除收货地址数据* @param* @return*/Integer deleteByAid(Integer aid);/*** 根据用户id查询用户最后一次修改的收货地址数据* @param uid 用户id* @return  返回值是用户最后一次修改的收货地址数据*/Address findLastModified(Integer uid);

1.3 xml文件中进行sql映射

<delete id="deleteByAid">DELETE FROM t_address WHERE aid=#{aid}</delete><!--    查询该用户最新修改地址的信息 第一页,一条    --><select id="findLastModified" resultMap="AddressEntityMap">select * from t_address where uid=#{uid} order by modified_time desc limit 0,1</select>

1.4 进行测试

        在AddressMapperTest类中进行测试

@Testvoid deleteByAid() {Integer integer = addressMapper.deleteByAid(7);System.out.println(integer);}@Testpublic void findLastModified() {Address address = addressMapper.findLastModified(9);System.out.println(address);}

2 删除收获地址-业务层

2.1 异常规划

        在执行删除的时候哦可能会产生未知的删除异常导致数据不能删除成功,则抛出DeleteException异常

package com.cy.store.service.ex;/**删除数据时产生的异常*/
public class DeleteException extends ServiceException{public DeleteException() {super();}public DeleteException(String message) {super(message);}public DeleteException(String message, Throwable cause) {super(message, cause);}public DeleteException(Throwable cause) {super(cause);}protected DeleteException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);}
}

2.2 service层接口和抽象方法

    /*** 删除收货地址* @param aid 收货地址id* @param uid 用户id* @param username 用户名*/void delete(Integer aid, Integer uid, String username);

2.3 实现类实现接口重写抽象方法

    /*** 删除收货地址* @param aid 收货地址id* @param uid 用户id* @param username 用户名*/@Overridepublic void delete(Integer aid, Integer uid, String username) {
//        判断收货地址是否存在Address address = addressMapper.findByAid(aid);if (address==null){throw new AddressNotFoundException("收货地址数据不存在");}
//        判断用户id与收货地址数据中的用户id是否相同if (!address.getUid().equals(uid)){throw new AccessDeniedException("非法数据访问");}
//        删除收货地址操作Integer rows = addressMapper.deleteByAid(aid);
//        如果删除失败,抛出删除异常if (rows!=1){throw new DeleteException("删除数据时产生未知的异常");}
//        统计用户的收货地址数量,如果为0,就直接终止程序Integer count = addressMapper.countByUid(uid);if (count==0){
//            直接终止程序return;}
//        如果删除的收货地址是默认收货地址,则将用户最新修改的收货地址设置为默认收货地址if (address.getIsDefault()==1){
//            查询 用户最新修改的收货地址Address lastModified = addressMapper.findLastModified(uid);
//            设置为默认值Integer integer = addressMapper.updateDefaultByAid(lastModified.getAid(), username, new Date());if (integer!=1){throw new UpdateException("更新数据时产生未知的异常");}}}

2.4 测试业务

        在assressServiceTest中进行测试

@Testvoid delete() {addressService.delete(6,9,"admin");}

3 删除收获地址-控制层

3.1 处理DeleteException异常

        在BaseController中需要处理DeleteException

/*** 控制层基类*/
public class BaseController {//操作成功的状态码public static final int OK = 200;/*** 全局异常处理器,用于捕获并处理业务层抛出的异常。** @param e 捕获的异常对象* @return 返回封装后的 JsonResult 对象,包含状态码和错误信息*/
//    该项目中产生了异常,会被统一拦截到此方法中,这个方法此时就充当了请求处理方法,方法的返回值直接给前端浏览器,返回给前端的数据中,状态码,状态码对应信息,数据@ExceptionHandler({ServiceException.class, FileUploadException.class})public JsonResult<Void> handleException(Throwable e) {// 创建一个 JsonResult 实例,并初始化异常消息JsonResult<Void> result = new JsonResult<>(e);// 判断异常类型,设置对应的状态码和提示信息if (e instanceof UsernameDuplicatedException){// 用户名被占用时返回 400 状态码和相应提示result.setState(4000);result.setMessage("用户名被占用");} else if (e instanceof InsertException){// 插入数据失败时返回 500 状态码和相应提示result.setState(4000);result.setMessage("注册时产生未知的异常");}else if (e instanceof UsernameNotFoundException){result.setState(4001);result.setMessage("用户数据不存在");}else if (e instanceof PasswordNotMatchException){result.setState(4002);result.setMessage("用户密码错误");}else if (e instanceof AddressCountLimitException){result.setState(4003);result.setMessage("收货地址超出上限");}else if (e instanceof AccessDeniedException){result.setState(4004);result.setMessage("收货地址数据非法访问");}else if (e instanceof AddressNotFoundException){result.setState(4005);result.setMessage("收货地址数据不存在");}else if (e instanceof DeleteException){result.setState(5002);result.setMessage("删除数据时产生未知的异常");}else if (e instanceof UpdateException){result.setState(5003);result.setMessage("更新数据时产生未知的异常");} else if (e instanceof FileEmptyException) {result.setState(6000);} else if (e instanceof FileSizeException) {result.setState(6001);} else if (e instanceof FileTypeException) {result.setState(6002);} else if (e instanceof FileStateException) {result.setState(6003);} else if (e instanceof FileUploadIOException) {result.setState(6004);}// 返回最终的响应结果return result;}/*** 从Session中获取当前登录用户的uid* * @param session HttpSession对象,用于获取会话中的用户ID* @return 当前登录用户的uid* * `protected` 表示该方法只能被同一个包内的类或子类访问。* `final` 表示该方法不能被子类重写。*/protected final Integer getUidFromSession(HttpSession session) {// 从Session中获取uid// 从会话中获取uid属性并转换为整数类型返回return Integer.valueOf(session.getAttribute("uid").toString());}/*** 从Session中获取当前登录用户的用户名* @param session HttpSession对象,用于获取会话中的用户名* @return 当前登录用户的用户名*/protected final String getUsernameFromSession(HttpSession session) {// 从Session中获取当前登录的用户名return session.getAttribute("username").toString();}}

3.2 设计请求

请求路径:/address/delete/{aid}

请求方式:POST

请求参数:Integer aid,HttpSession session

返回值类型:JsonResult<Void>

3.3 编写AddressController类代码,实现请求

    /*** 删除收货地址* @param aid 收货地址id* @param session 当前登录的用户的会话* @return*/@RequestMapping("/delete/{aid}")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<>(OK);}

4 Address.html前端页面

4.1 给删除按钮绑定点击事件

 4.2 编写deleteById()函数方法,发送请求

function deleteById(aid){$.ajax({url: "/addresses/delete/"+ aid,type: "POST",dataType: "json",success: function (json) {if (json.state == 200) {alert("删除收货地址成功")//	将列表的tr清空,替代成新的tr//	重新调用获取列表的方法showAddressList();}else{alert("删除地址失败")}},error: function (xhr) {alert("删除收货地址时产生未知的异常"+xhr.message)}})};

        但是!!!可能会出现这个问题

Uncaught SyntaxError: Invalid or unexpected token (at address.html:1:12)

 在检查代码和业务逻辑没有问题后,发现可能是 #{aid} 是占位符,在后续被替换为真实值。但如果替换失败或未正确处理,最终渲染出来的 HTML 可能会是

<a οnclick="setDefault()" class="btn btn-xs add-def btn-default">设为默认</a>

        此时 setDefault() 调用缺少参数,如果函数定义要求必须传参(如 function setDefault(aid)),当点击按钮时就会因为参数缺失导致 JS 报错,甚至出现 Invalid or unexpected token 这类错误 

解决方法:

let tr = '<tr>\n' +'<td>#{tag}</td>\n' +'<td>#{name}</td>\n' +'<td>#{address}</td>\n' +'<td>#{phone}</td>\n' +'<td><a class="btn btn-xs btn-info"><span class="fa fa-edit"></span> 修改</a></td>\n' +'<td><a onclick="deleteById(#{aid})" class="btn btn-xs add-del btn-info"><span class="fa fa-trash-o"></span> 删除</a></td>\n' +'<td><a onclick="setDefault(#{aid})" class="btn btn-xs add-def btn-default">设为默认</a></td>\n' +'</tr>';tr = tr.replace("#{tag}", list[i].tag).replace("#{name}", list[i].name).replace("#{address}", list[i].address).replace("#{phone}", list[i].phone).replace(/#{aid}/g, list[i].aid); // 注意这里使用全局替换

        使用 .replace(/#{aid}/g, ...) 可以确保所有匹配的 #{aid} 都被替换

        重启项目运行就没有问题了✌


热销排行

1. 创建数据库表

CREATE TABLE t_product (id int(20) NOT NULL COMMENT '商品id',category_id int(20) DEFAULT NULL COMMENT '分类id',item_type varchar(100) DEFAULT NULL COMMENT '商品系列',title varchar(100) DEFAULT NULL COMMENT '商品标题',sell_point varchar(150) DEFAULT NULL COMMENT '商品卖点',price bigint(20) DEFAULT NULL COMMENT '商品单价',num int(10) DEFAULT NULL COMMENT '库存数量',image varchar(500) DEFAULT NULL COMMENT '图片路径',`status` int(1) DEFAULT '1' COMMENT '商品状态  1:上架   2:下架   3:删除',priority int(10) DEFAULT NULL COMMENT '显示优先级',created_time datetime DEFAULT NULL COMMENT '创建时间',modified_time datetime DEFAULT NULL COMMENT '最后修改时间',created_user varchar(50) DEFAULT NULL COMMENT '创建人',modified_user varchar(50) DEFAULT NULL COMMENT '最后修改人',PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2. 创建实体类

package com.cy.store.entity;import lombok.Data;/** 商品数据的实体类 */
@Data
public class Product extends BaseEntity {private Integer id;private Integer categoryId;private String itemType;private String title;private String sellPoint;private Long price;private Integer num;private String image;private Integer status;private Integer priority;
}

3. 持久层

3.1 编写sql

        priority根据优先级进行排序降序

select * from t_product where status=1 order by priority desc limit 0,4

3.2 编写mapper接口以及抽象方法

        创建ProductMapper 接口,编写抽象方法,返回值是一个集合

@Mapper
public interface ProductMapper {/*** 查询热销商品* @return 热销商品列表*/List<Product> findHotList();
}

3.3 编写sql映射

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.cy.store.mapper.ProductMapper"><resultMap id="ProductEntityMap" type="com.cy.store.entity.Product"><id column="id" property="id"/><result column="category_id" property="categoryId"/><result column="item_type" property="itemType"/><result column="sell_point" property="sellPoint"/><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><!-- 查询热销商品列表 --><!-- 返回值为商品列表,包含id,categoryId,itemType,sellPoint等字段 --><!-- SQL说明:从t_product表中查询状态为1(上架)的商品,按优先级降序排列,取前4条记录 --><select id="findHotList" resultMap="ProductEntityMap">select * from t_product where status=1 order by priority desc limit 0,4</select>
</mapper>

4. 业务层

4.1 service接口编写抽象方法

public interface ProductService {/** 查询热销商品 */List<Product> findHotList();
}

4.2 实现类实现接口,重写抽象方法

@Service
public class ProductServiceImpl implements ProductService {@Autowiredprivate ProductMapper productMapper;/*** 查询热销商品列表* @return 热销商品列表*/@Overridepublic List<Product> findHotList() {List<Product> list = productMapper.findHotList();
//        将前端用户到的数据设为null,减小体量for (Product product : list) {product.setPriority(null);product.setCreatedUser(null);product.setCreatedTime(null);product.setModifiedUser(null);product.setModifiedTime(null);}return list;}}

5. controller控制层

5.1 设计请求

请求路径:/products/hotList

请求方式:GET

响应结果:JsonResult<List<Product>>

5.2 将商品的页面进行白名单放行

        在LoginInterceptorConfigure类中配置放行白名单

5.3 PruductController类实现请求

package com.cy.store.controller;import com.cy.store.entity.Product;
import com.cy.store.service.ProductService;
import com.cy.store.util.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController
@RequestMapping("/products")
public class ProductController extends BaseController{@Autowiredprivate ProductService productService;@RequestMapping("/hotList")public JsonResult<List<Product>> getHotList(){List<Product> data = productService.findHotList();return new JsonResult<>(OK,data);}
}

6. 前端页面

  • 当页面展示时就调用方法获取热门商品列表信息进行渲染
  • href="product.html?id=#{id}" 将id拼接到href上,当点击商品信息时,跳转到对应的商品详情页
  • /#{image}/g,将所有的属性进行替换
<script type="text/javascript">$(document).ready(function() {showHotList();});function showHotList() {$("#hot-list").empty();$.ajax({url: "/products/hotList",type: "GET",success: function(json) {var list = json.data;for (var i = 0; i < list.length; i++) {console.log(list[i].title);//调试用var html = '<div class="col-md-12">'+ '<div class="col-md-7 text-row-2"><a href="product.html?id=#{id}">#{title}</a></div>'+ '<div class="col-md-2">¥#{price}</div>'+ '<div class="col-md-3"><img src="..#{image}collect.png" class="img-responsive" /></div>'+ '</div>';html = html.replace(/#{id}/g, list[i].id);html = html.replace(/#{title}/g, list[i].title);html = html.replace(/#{price}/g, list[i].price);html = html.replace(/#{image}/g, list[i].image);$("#hot-list").append(html);}}});}</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/910228.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/910228.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MIMIC-III 数据集文件简介

文件简介&#xff1a; 共26个文件 admissions.csv 患者入院信息&#xff08;入院时间、出院时间、入院类型、科室等&#xff09;。 callout.csv ICU 外科室请求 ICU 会诊的呼叫记录。 caregivers.csv 护理患者的医护人员信息&#xff08;身份、角色等&#xff09;。…

UL/CE双认证!光宝MOC3052-A双向可控硅输出光耦 智能家居/工业控制必备!

光宝MOC3052-A双向可控硅输出光耦详解 1. 产品定位 MOC3052-A 是光宝科技&#xff08;Lite-On&#xff09;推出的 双向可控硅驱动光耦&#xff0c;属于光电隔离型半导体器件&#xff0c;主要用于交流负载的隔离控制&#xff0c;实现低压控制电路&#xff08;如MCU&#xff09;…

让没有小窗播放的视频网站的视频小窗播放

让没有小窗播放的视频网站的视频小窗播放 // 视频小窗播放控制台脚本 // 将此代码复制到浏览器控制台运行 // 运行后&#xff0c;页面中的视频将添加小窗播放功能(function() {// 获取页面中的所有video元素const videos document.querySelectorAll(video);if (videos.length…

Linux内核在启动过程中挂载根文件系统rootfs的过程

一、挂载根文件系统rootfs的过程&#xff1a; 1. ‌初始虚拟根文件系统的挂载‌ 内核启动时首先会创建并挂载一个‌临时虚拟根文件系统&#xff08;如initramfs或rootfs&#xff09;‌‌15。该阶段主要作用&#xff1a; 提供基础的设备节点和目录结构&#xff0c;确保内核能访…

【LeetCode】力扣题——轮转数组、消失的数字、数组串联

&#x1f525;个人主页&#xff1a;艾莉丝努力练剑 ❄专栏传送门&#xff1a;《C语言》、《数据结构与算法》、C语言刷题12天IO强训 &#x1f349;学习方向&#xff1a;C/C方向 ⭐️人生格言&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;…

Java Stream详解

Java Stream详解 Stream 是 Java 8 引入的流式数据处理工具&#xff0c;可以像流水线一样对集合数据进行高效操作&#xff08;过滤、转换、统计等&#xff09;。核心特点&#xff1a; 链式操作&#xff1a;支持多个操作串联不修改原始数据&#xff1a;生成新结果支持并行处理…

Java回归循环理解

一、Java循环的四种 1. 传统for循环 - 精确控制的首选 // 遍历数组 int[] numbers {1, 2, 3, 4, 5}; for (int i 0; i < numbers.length; i) {System.out.println(numbers[i]); }// 嵌套示例&#xff1a;矩阵遍历 int[][] matrix {{1, 2}, {3, 4}}; for (int row 0; r…

飞腾D2000金融工控主板,点亮经济高质量发展

近年来&#xff0c;国家不断推出金融行业的政策和法规&#xff0c;推动金融业高质量发展。在国家大力推进金融行业改革和创新的大环境下&#xff0c;金融工控主板市场也迎来了新的发展机遇。随着国产CPU技术的不断突破&#xff0c;以及我国对金融安全重视程度的提高&#xff0c…

SimpleITK——创建nrrd体素模型

在介绍如何生成nrrd前&#xff0c;了解一下为什么医学影像上一般使用nrrd的体素模型&#xff1f; 为什么医学影像上一般使用nrrd的体素模型&#xff1f; 在医学影像领域&#xff0c;‌NRRD&#xff08;Nearly Raw Raster Data&#xff09;格式‌被广泛用于存储体素模型&#x…

Docker容器部署KES

一、安装部署 1&#xff0c;导入镜像 #导入镜像&#xff08;root用户&#xff09; [rootnode docker ]# mv kdb_x86_64_V008R006C009B0014.tar kingbase.tar [rootnode docker]# docker load -i kingbase.tar#查看镜像&#xff08;root用户&#xff09; [rootnode docker]# d…

C++基础练习 sort函数,用于排序函数

题目&#xff1a; https://acm.hdu.edu.cn/showproblem.php?pid2039 解答&#xff1a; #include <iostream> #include <cmath> #include <algorithm> using namespace std;double a[3]; int main(){int n;cin>>n;while(n--){cin>>a[0]>>…

棱镜观察|EMB“重构”卡钳,车企降本压力与Brembo困局

传统制动卡钳市场&#xff0c;正在迎来变革时刻。 一直以来&#xff0c;采埃孚、大陆集团、日立安斯泰莫等外资供应商占据中国乘用车卡钳前装市场&#xff08;包括前制动卡钳和后集成EPB卡钳&#xff09;的半壁江山。同时&#xff0c;伯特利、亚太股份、万向、弗迪等中国供应商…

《颠覆传统:CSS遮罩的图像创意设计指南》

想象有一块神奇的模板&#xff0c;上面有各种形状的镂空区域&#xff0c;当我们将这块模板覆盖在图像上时&#xff0c;只有透过镂空区域才能看到图像的部分&#xff0c;而模板遮挡的地方则被隐藏起来&#xff0c;这便是CSS遮罩的核心概念。遮罩&#xff0c;简单来说&#xff0c…

5.基于神经网络的时间序列预测

近年来&#xff0c;已经开发了一些深度学习方法并将其应用于单变量时间预测场景&#xff0c;其中时间序列由在等时间增量上按顺序记录的单个观测数据组成。 5.1 将深度学习用于时间序列预测的原因 机器学习的目标是提取特征来训练模型。模型将输入数据&#xff08;例如图片&am…

【软考高级系统架构论文】论软件设计方法及其应用

论文真题 软件设计 (Software Design,SD) 根据软件需求规格说明书设计软件系统的整体结构、划分功能模块、确定每个模块的实现算法以及程序流程等,形成软件的具体设计方案。软件设计把许多事物和问题按不同的层次和角度进行抽象,将问题或事物进行模块化分解,以便更容易解决…

什么是水平扩展

什么是水平扩展 在现代系统架构设计中&#xff0c;可扩展性&#xff08;Scalability&#xff09;是衡量系统面对业务增长时应对能力的重要指标。而“水平扩展”&#xff08;Horizontal Scaling&#xff09;&#xff0c;又称为“横向扩展”或“扩容节点”&#xff0c;正是应对高…

掌握openpyxl:Excel自动化处理全指南

openpyxl基础用法 openpyxl 是一个用于处理 Excel 文件&#xff08;.xlsx/.xlsm&#xff09;的 Python 库&#xff0c;支持读取、修改和创建 Excel 文档。以下是其常见用法的详细介绍&#xff1a; 一、基础操作&#xff1a;打开与保存文件 from openpyxl import load_workbo…

FastGPT:开启大模型应用新时代(4/6)

摘要&#xff1a;FastGPT是一种基于大语言模型&#xff08;LLM&#xff09;的知识库问答系统&#xff0c;致力于提供高效、精准的自然语言处理服务。它允许用户构建本地知识库以增强AI的理解能力&#xff0c;通过将用户的问题与知识库信息匹配推理&#xff0c;生成有针对性的回…

在MyBatis中$和#有什么区别

在 MyBatis 中&#xff0c;${} 和 #{} 是两种处理 SQL 参数的占位符&#xff0c;它们在实现机制、安全性、使用场景上存在显著差异。以下是详细对比&#xff1a; 核心区别对比 特性#{}${}底层机制预编译占位符&#xff08;PreparedStatement&#xff09;字符串直接替换安全性…

湖北理元理律师事务所债务优化方案:平衡还款与生活的法律实践

在个人债务问题日益突出的当下&#xff0c;如何科学规划还款路径成为社会性难题。湖北理元理律师事务所基于多年实务经验&#xff0c;提出“可持续债务优化”模型&#xff0c;其核心在于通过法律工具实现三重平衡&#xff1a; 债权债务的法律平衡&#xff1a;严格依据《民法典…