springboot网上商城项目(一)

news/2024/11/29 7:48:53/

springboot网上商城项目(一)

    • (一)项目分析
        • 1.项目分析
        • 2.开发顺序
        • 3.前端资源测试
    • (二)用户注册
        • 1.创建数据库
        • 2.实体类编写
        • 3.注册(持久层)
        • 4.注册(业务层)
        • 5.注册(控制层)
        • 6.注册前端页面
      • 后记

🎁🎁静态资源及sql文件
链接:https://pan.baidu.com/s/1X-yjmQcPD3PqS21x0HplNA?pwd=23gr
提取码:23gr

(一)项目分析

1.项目分析

📝​📝项目功能:登录,注册,热销商品,用户管理(密码,个人信息,头像,收货地址),购物车(展示,增加,删除),订单模块
📝​📝开发顺序:注册,登录,用户管理,购物车,商品,订单模块

2.开发顺序

模块的开发顺序:
持久层开发:依据前端页面的设置规划相关的SQL语句,以及进行配置
业务层开发:核心功能控制,业务操作以及异常的处理
控制层开发:接收请求,处理响应
前端开发:JS,Query,AJAX这些技术来连接后台

3.前端资源测试

创建一个springboot项目导入前端静态资源 ,检测是否能够正常显示。如果这个过程访问失败,原因是idea对于JS代码的兼容性较差,编写了js代码但是有的时候不能正常去加载,解决办法有以下四种:

1.clear-install:依次点击MavenProject->store->Lifecycle->clean,等待清理项目完毕后点击同目录下的install重新部署

2.idea缓存清理:点击File下的Invalidate Caches/Restart…然后在弹出的窗口中选择Invalidate and Restart,此时就会自动清除缓存并重新启动idea

3.rebuild重新构建:点击工具栏的Build下的Rebuild Project

4.重启电脑

(二)用户注册

1.创建数据库

创建数据库t_user

CREATE TABLE t_user (uid INT AUTO_INCREMENT COMMENT '用户id',username VARCHAR(20) NOT NULL UNIQUE COMMENT '用户名',password CHAR(32) NOT NULL COMMENT '密码',salt CHAR(36) COMMENT '盐值',phone VARCHAR(20) COMMENT '电话号码',email VARCHAR(30) COMMENT '电子邮箱',gender INT COMMENT '性别:0-女,1-男',avatar VARCHAR(50) COMMENT '头像',is_delete INT COMMENT '是否删除:0-未删除,1-已删除',created_user VARCHAR(20) COMMENT '日志-创建人',created_time DATETIME COMMENT '日志-创建时间',modified_user VARCHAR(20) COMMENT '日志-最后修改执行人',modified_time DATETIME COMMENT '日志-最后修改时间',PRIMARY KEY (uid)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

2.实体类编写

创建用户表实体类(因为在用户表的设计中有4个公共字段,所以将这些字段字段提取出来放在一个实体基类baseEntity中)

//基类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class baseEntity implements Serializable {private String createdUser;private Date createdTime;private String modifiedUser;private Date modifiedTime;

实体类User继承baseEntity(实体类User因为要在网络中以流的形式传输,所以需要serialize序列化

//实体类
@Data
public class User extends baseEntity implements Serializable {
private Integer uid;
private String username;
private String password;
private String salt;
private String phone;
private String email;
private Integer gender;
private String avatar;
private Integer isDelete;

3.注册(持久层)

mapper接口

//用户模块持久层
//@Mapper
public interface UserMapper {//插入用户数据Integer insert(User user);//根据用户名查找用户数据User findByUsername(String username);
}

mapper的xml映射文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace用于指定当前的映射文件和哪个接口进行映射,需要指定接口的文件路径,路径需要是包的完整路径结构-->
<mapper namespace="com.cy.store.mapper.UserMapper"><resultMap id="UserEntityMap" type="com.cy.store.entity.User"><id column="uid" property="uid"></id><result column="is_delete" property="isDelete"></result><result column="created_user" property="createdUser"></result><result column="created_time" property="createdTime"></result><result column="modified_user" property="modifiedUser"></result><result column="modified_time" property="modifiedTime"></result></resultMap>
<insert id="insert" useGeneratedKeys="true" keyProperty="uid">insert into t_user(username,password,salt,phone,email,gender,avatar,is_delete,created_user,created_time,modified_user,modified_time) values (#{username},#{password},#{salt},#{phone},#{email},#{gender},#{avatar},#{isDelete},#{createdUser},#{createdTime},#{modifiedUser},#{modifiedTime})</insert><select id="findByUsername" resultMap="UserEntityMap">
select * from t_user where  username=#{username}</select>
</map

4.注册(业务层)

service层
接受前端从控制器流转过来的数据
结合真实的注册业务来完成功能业务逻辑的调转和流程

异常规划
比如,用户在进行注册时可能会产生用户名被占用的错误,这时需要抛出一个异常

1.异常不能用RuntimeException,太笼统了,开发者没办法第一时间定位到具体的错误类型上,我们可以定义具体的异常类型来继承这个异常。
2.正常的开发中异常又要分等级,可能是在业务层产生异常,可能是在控制层产生异常,所以可以创建一个业务层异常的基类,起名ServiceException异常,并使其继承RuntimeException异常。
3.后期开发业务层时具体的异常可以再继承业务层的异常ServiceException。

在service包下创建一个ex包再在下创建ServiceException类作为业务层异常的基类

public class ServiceException extends RuntimeException{public ServiceException() {super();}public ServiceException(String message) {super(message);}public ServiceException(String message, Throwable cause) {super(message, cause);}public ServiceException(Throwable cause) {super(cause);}protected ServiceException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {super(message, cause, enableSuppression, writableStackTrace);}
}

分别创建查询异常UsernameDuplicatedException 和插入异常的InsertException 类

public class UsernameDuplicatedException extends ServiceException{/**重写ServiceException的所有构造方法*/
}
//数据插入过程中产生异常
public class InsertException extends ServiceException{/**重写ServiceException的所有构造方法*/
}

创建IUserService接口(接口命名的默认规则:I+业务名字+层的名字)

//用户模块业务层接口
public interface IUserService {void reg(User user);
}

service实现serviceimpl类

@Service
public class UserServiceImpl implements IUserService {@Resourceprivate UserMapper userMapper;@Overridepublic void reg(User user) {String username=user.getUsername();
//调用findbyusername判断用户是否被注册User result= userMapper.findByUsername(username);if (result!=null){throw new UsernameDuplicatedException("用户已经存在");}//密码加密 md5加密算法//串(盐值)+password+串 ---md5进行加密 连续加载三次//盐值就是随机字符串
String oldPassword=user.getPassword();String salt= UUID.randomUUID().toString().toUpperCase();//记录盐值 登录进行密码比较user.setSalt(salt);
//将密码和盐值作为一个整体 加密
String md5password=getMd5Password(oldPassword,salt);
//重新加入
user.setPassword(md5password);
//补全数据user.setIsDelete(0);Date date=new Date();user.setCreatedTime(date);user.setModifiedTime(date);user.setCreatedUser(user.getUsername());user.setModifiedUser(user.getModifiedUser());Integer rows=userMapper.insert(user);
if (rows!=1){throw new InsertException("注册异常");
}}
//定义md5算法加密private String getMd5Password(String password,String salt){for (int i=0 ;i<3;i++){password=DigestUtils.md5DigestAsHex((salt+password+salt).getBytes()).toUpperCase();}return password;}
}

5.注册(控制层)

Controller层
请求路径:/users/reg
请求参数:User user
请求类型:POST
响应结果:JsonResult< void >

在controller包下创建BaseController 类作为控制层下类的基类,用来做统一的异常捕获:

public class BaseController {public static final int ok = 200;//请求处理方法,这个方法的返回值就是需要传递给前端数据//自动将异常对象传递给此方法的参数列表上//当前项目中产生了异常,被统一拦截到此方法中,这个方法此时充当的是请求处理方法,方法的返回值直接给前端@ExceptionHandler(ServiceException.class)//用于统一处理抛出异常public JsonResult<Void> handleException(Throwable e) {JsonResult<Void> result = new JsonResult<>(e);if (e instanceof UsernameDuplicatedException) {result.setState(400);result.setMessage("用户名存在");} else if (e instanceof InsertException){result.setState(500);result.setMessage("注册出现异常");}return result;}
}

创建UserController类,依赖于业务层的接口,继承BaseController并重构UserController下的reg方法。

@RestController
@RequestMapping("/users")
public class UserController extends BaseController{@Autowiredprivate IUserService userService;@PostMapping("/reg")public JsonResult<Void> reg(@RequestBody User user){userService.reg(user);return new JsonResult<>(ok);}
}

6.注册前端页面

ajax函数:
这是jQuery封装的一个函数,称为$.ajax()函数,通过对象调用ajax()函数用来异步加载相关的请求.依靠的是JavaScript提供的一个对象:XHR(全称XmlHttpResponse)

ajax()函数的语法结构:
使用ajax()时需要传递一个方法体作为方法的参数来使用(一对大括号就是一个方法体)
ajax接受多个参数时,参数与参数之间使用",“分割
每一组参数之间使用”:"进行分割
参数的组成部分一个是参数的名称(不能随便定义),另一个是参数的值(必须用字符串来表示)
参数的声明顺序没有要求
语法结构:

$.ajax({url: "",type: "",data: "",dataType: "",success: function() {},error: function() {}
});

在这里插入图片描述

前端js代码

        <script>//1.监听注册按钮是否被点击,如果被点击可以执行一个方法(这里不能像ajax函数那样删去function()只留下{},这是官方规定的!)$("#btn-reg").click(function () {//let username = $("#username").val();//let pwd = $("#password").val();//上面这两行是动态获取表单中控件的数据,但是如果这样获取的话ajax函数中//就是data: "username="+username + "&password="+pwd,但太麻烦了,如// 果这个表单提交的是用户的兴趣爱好,那数据就很多了,一个表单20个数据都很正// 常,如果此时还用这种方式就太麻烦了,所以不建议用这种方式//2.发送ajax()的异步请求来完成用户的注册功能$.ajax({url: "/users/reg",type: "POST",//serialize这个API会自动检测该表单有什么控件,每个控件检测后还会获取每个控// 件的值,拿到这个值后并自动拼接成形如username=Tom&password=123的结构data: $("#form-reg").serialize(),dataType: "JSON",success: function (json) { //1.js是弱数据类型,这个地方不用声明json的数据类型//2.如果服务器成功响应就会将返回的数据传给形参,比如{state: 4000,message: "用户名// 已经被占用",data: null}if (json.state == 200) {alert("注册成功")} else {alert("注册失败")}},error: function (xhr) { //如果问题不在可控范围内,服务器就不会返回自己定//义的json字符串:{state: 4000,message: "用户名已经被占用",data: null}//而是返回一个XHR类型的对象,该对象也有一个状态码名字是statusalert("注册时产生未知的错误!"+xhr.status);}});});</script>

浏览器上输入http://localhost:8080/web/register.html 测试注册功能是否可以注册。此时可能会出现点击注册提交表单时没有任何响应,原因是idea对于JS代码的兼容性较差,编写了js代码但是有的时候不能正常去加载,解决办法有四种,同前面的:项目环境搭建->项目测试->测试静态资源能否正常加载

后记

👉👉💕💕美好的一天,到此结束,下次继续努力!,写作不易,感谢大家的支持!! 🌹🌹🌹


http://www.ppmy.cn/news/61634.html

相关文章

【深度学习】模型如何加载至 cpu 和 gpu

【深度学习】模型如何加载至 cpu 和 gpu 文章目录 【深度学习】模型如何加载至 cpu 和 gpu1. 采用 from_pretrained 的方式2. 采用 load_state_dict 的方式参考 1. 采用 from_pretrained 的方式 这种情况下&#xff0c;BertMoldel.from_pretrained() 是会 load 在 cpu 上的&am…

归排、计排深度理解

归并排序&#xff1a;是创建在归并操作上的一种有效的排序算法。算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用&#xff0c;且各层分治递归可以同时进行。归并排序思路简单&#xff0c;速度仅次于快速排序&#xff0c;为稳定排序算法&#…

SpringCloud 分布式事务组件之Seata

目录 背景介绍什么是分布式事务什么叫做逆向补偿呢互联网最流行的分布式事务组件seata总结 背景 大家好&#xff0c;今天给大家分享一个在2022年出去面试Java几乎必问的一个技术&#xff0c;那就是seata。什么&#xff1f;&#xff1f;你才看了第一句话心里有闪现了无数个问…

面了一圈,还没拿到offer.....

最近收到很多小伙伴的留言&#xff0c;金三银四过完了一个offer都没收到。还有遇到那种特别喜欢怼人的面试官&#xff0c;直接面到怀疑人生&#xff0c;真是让人费解。。。 其实面试受打击是正常的&#xff0c;关键是要在面试中总结自己的不足&#xff01;提前做好面试准备和技…

数控新代系统解锁解密 数控机床车床使用期限破解

时效性保证了良好的用户体验&#xff0c;根据经验在交易环节&#xff0c;延迟越低转化效果也会越好。传统的直播延迟问题已经成为了一个不容忽视的问题&#xff0c;高延迟不仅破坏了用户的观看体验&#xff0c;也让主播难以实时获取到用户的反馈。为了进一步优化直播时效体验&a…

自行车和电动自行车上亚马逊标准有什么区别?UL2849,16CFR1512

自行车 自行车是一种两轮的或三轮的交通工具&#xff0c;完全靠人力驱动后轮前进。本政策所涵盖的自行车包括当座位调整到最高位置时&#xff0c;座位离地面超过 25 英寸的自行车&#xff0c;以及座位高度为 25 英寸或以下的人行道自行车。本政策也适用于公路使用的卧式自行车…

Okta 即代码:云原生时代的身份管理

我们为什么应该将 Okta 配置作为代码进行管理&#xff1f; 对于需要跨多个应用程序和环境管理对其数字资源的访问的组织来说&#xff0c;Okta 可能是最受欢迎的选择&#xff0c;因为它提供了一系列使其在身份验证和授权方面很受欢迎的功能&#xff0c;例如&#xff1a; 单点登…

高级IO涉及的编程模型

目录 五种IO模型引入IO模型阻塞IO非阻塞IO信号驱动IOO多路转接异步IO IO重要概念同步通信 vs 异步通信阻塞 vs 非阻塞 其他高级IO 非阻塞IOfcntl基于fcntl将文件描述符设置为非阻塞轮询方式读取标准输入 I/O多路转接之select初识selectselect函数原型参数timeout取值fd_set结构…