项目学习小结(store(商城项目))
1. 项目分析
-
在开发某个项目之前,应先分析这个项目中可能涉及哪些种类的数据。本项目中涉及的数据:用户、商品、商品类别、收藏、订单、购物车、收货地址。
-
关于数据,还应该要确定这些数据的开发顺序。设计开发顺序的原则是:先开发基础、简单或熟悉的数据。以上需要处理的数据的开发流程是:用户-收货地址-商品类别-商品-收藏-购物车-订单。
-
在开发每种数据的相关功能时,先分析该数据涉及哪些功能。在本项目中以用户数据为例,需要开发的功能有:登录、注册、修改密码、修改资料、上传头像。
-
然后,在确定这些功能的开发顺序。原则上,应先做基础功能,并遵循增查删改的顺序来开发。则用户相关功能的开发顺序应该是:注册-登录-修改密码-修改个人资料-上传头像。
-
在实际开发中,应先创建该项目的数据库,当每次处理一种新的数据时,应先创建该数据在数据库中的数据表,然后在项目中创建该数据表对应的实体类。
-
在开发某个具体的功能时,应遵循开发顺序:持久层-业务层-控制器-前端页面。
2. 配置运行项目
-
选择spring脚手架快速搭建项目
-
选择一般web项目中几个常用的包:
- Spring Boot DevTools:可以提高开发者的开发效率,无需手动重启Spring Boot应用就能实现自动加载
- Lombok:简化开发,可以使用注解快速生成一些Getter/Setter、构造器方法、字符串输出的ToString方法和Equals/HashCode方法等。
- Spring Configuration Processor:便捷开发,在自定义配置配置文件(application.properties或application.yml)时会出现代码提示
- Spring Web:集成了web开发环境
- MySQL Driver:mysql数据库连接池,可以不用选择,在配置文件中配置数据库连接池(spring.datasource.type)时选择SpringBoot自带的hikari数据库连接池HikariDataSource
- MyBatis Framework:集成MyBatis 开发环境
-
进行配置文件的基础配置:
#配置端口号 server.port=8080 #定义应用名称 spring.application.name=商城 #配置地址前缀 默认地址为 / #server.servlet.context-path= #配置数据库 spring.datasource.type=com.mysql.cj.jdbc.MysqlDataSource spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/store?serverTimezone=UTC&useUnicode=true spring.datasource.username=root spring.datasource.password=123456 #关掉前端页面缓存 spring.thymeleaf.cache=false #配置mybatis映射文件位置 mybatis.mapper-locations=classpath:mapper/*.xml #配置mapper的dao接口位置 mybatis.type-aliases-package=com.cy.store.mapper #开启mybatis驼峰映射 mybatis.configuration.map-underscore-to-camel-case=true
-
找到项目的启动类(被@SpringBootApplication注解修饰),然后运行启动类;启动过程如果控制台输出Spring图形则表示启动成功。
Spring图形:
3. 用户注册
3.1 创建实体类
项目中许多实体类都会有日志相关的四个属性,所以在创建实体类之前,应先创建这些实体类的基类,将4个日志属性声明在基类中。
sql文件中可以看到日志相关的属性:
在com.cy.store.entity包下创建BaseEntity类,作为实体类的基类。
因为这个基类的作用就是用于被其它实体类继承的,所以应声明为抽象类。
package com.cy.store.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import java.io.Serializable;
import java.util.Date;
/**
* @author 且听风吟
* @version 1.0
* @description: 作为实体类的基类
* Serializable:对象转换为有序字节流,以便在网络上传输或者保存在本地文件中
* @date 2022/4/12 0012 0:54
*/
@Data
@EqualsAndHashCode
@ToString
public class BaseEntity implements Serializable {
/**
* 日志-创建人
*/
private String createdUser;
/**
* 日志-创建时间
*/
private Date createdTime;
/**
* 日志-最后修改执行人
*/
private String modifiedUser;
/**
* 日志-最后修改时间
*/
private Date modifiedTime;
}
其中需要这个积累实现Serializable接口实现序列化,简单介绍序列化的相关知识:
-
序列化其实可以看成是一种机制,按照一定的格式将 Java 对象的某状态转成介质可接受的形式,以方便存储或传输。
-
序列化时将 Java 对象相关的类信息、属性及属性值等等保存起来,反序列化时再根据这些信息构建出 Java 对象。而过程可能涉及到其他对象的引用,所以这里引用的对象的相关信息也要参与序列化。
-
序列化的作用:
-
提供一种简单又可扩展的对象保存恢复机制。
-
对于远程调用,能方便对对象进行编码和解码,就像实现对象直接传输。
-
可以将对象持久化到介质中,就像实现对象直接存储。
-
允许对象自定义外部存储的格式。
-
创建用户数据的实体类,继承自BaseEntity类,在类中声明与数据表中对应的属性。
package com.cy.store.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
/**
* @author 且听风吟
* @version 1.0
* @description: 用户的实体类
* 实体类应重写的方法:get、set、toString、equals、HashCode
* @date 2022/4/12 0012 1:48
*/
@Data
@ToString
@EqualsAndHashCode
public class User extends BaseEntity{
/**
* 用户id
*/
private Integer uid;
/**
* 用户名
*/
private String username;
/**
* 用户密码
*/
private String password;
/**
* 盐值
*/
private String salt;
/**
* 电话号码
*/
private String phone;
/**
* 电子邮件
*/
private String email;
/**
* 性别:0-女,1-男
*/
private Integer gender;
/**
* 头像
*/
private String avatar;
/**
* 是否删除:0-未删除,1-已删除
*/
private Integer isDelete;
}
此处注意,实体类应重写的方法:get和set、equals和HashCode、ToString方法,使用lombok插件的注解快速生成,@Data、@ToString、@EqualsAndHashCode
-
为什么要重写get、set方法?
方便设置、获取对象的属性,必要时为了简便开发可以使用
-
为什么要重写equals方法?
如果不重写equals方法,当将自定义对象放到 map或者 set中时,如果这时两个对象的 hashCode相同,会调用 Object中默认的 equals方法,而默认的 equals方法只是比较了两个对象的引用是否指向了同一个对象,显然大多数时候都不会指向,这样就会将重复对象存入 map或者 set中。这就破坏了 map与 set不能存储重复对象的特性,会造成内存溢出
-
为什么重写equals方法要重写HashCode方法?
1.使用hashcode方法提前校验,可以避免每一次比对都调用equals方法,提高效率
2.保证是同一个对象,如果重写了equals方法,而没有重写hashcode方法,会出现equals相等的对象,hashcode不相等的情况,重写hashcode方法就是为了避免这种情况的出现。
两者关系:
-
equals()相等的两个对象,hashcode()一定相等;
-
反过来:hashcode()不等,一定能推出equals()也不等;
-
hashcode()相等,equals()可能相等,也可能不等
-
-
为什么要重写ToString方法?
如果不重写的话会默认调用父类Object类型的toString方法,这个默认的父类方法在调用时会直接打印字符串,打印对象时会直接打印对象的hash码