前言
在如今的互联网时代,电商平台已深度融入人们的生活。一个完善的电商系统,能为商家提供高效的商品管理、订单处理渠道,也能给用户带来便捷的购物体验。本次我选择对电商系统核心功能模块进行设计与实现,希望能打造出贴合实际业务场景、功能实用的模块。
目录
- 前言
- 技术栈
- 一.需求分析与规划
- 二.环境准备
- 三.模块设计与编码
-
- 1.先设计大概模块
- 2.代码展示
-
- [entity 包下类示例](#entity 包下类示例)
- dto包下类示例
- repository包下接口示例
- service包下接口及实现类示例
- controller包下类示例
- 四.遇到的问题及解决
- 五.自我感想
- 总结
技术栈
- 后端:采用Spring Boot框架,它能快速搭建项目,简化配置,提高开发效率;结合MyBatis实现数据持久化,方便对数据库进行操作。
- 数据库:使用MySQL,存储商品、订单、用户等相关数据,其性能稳定、开源免费且社区支持丰富。
- 前端:借助Thymeleaf模板引擎与HTML、CSS、JavaScript结合,实现页面的动态渲染和交互,提升用户使用感受。
一.需求分析与规划
功能需求
电商系统核心功能模块需要实现商品管理,包括商品的增删改查、分类等)、订单流程(订单的创建、支付、发货、收货等状态管理)、用户中心(用户的注册、登录、个人信息管理、地址管理等。
核心模块
将系统划分为商品模块、订单模块、用户模块,各模块之间通过接口进行数据交互,保证模块的独立性和可扩展性。
技术选型
综合考虑开发效率、性能、社区支持等因素,选择上述的Spring Boot、MyBatis、MySQL、Thymeleaf等技术进行开发。
从该图,我们可以清晰看到电商系统核心功能模块所需实现的各功能点以及模块划分,为后续开发明确了方向。
二.环境准备
1. 下载"IDEA"
我们选择把IDEA作为我们的编译器,进入IDEA官网
2.安装
按照引导进行安装
下载好是这样的:
3. 下载"飞算Java AI"扩展
打开插件市场,
搜索"飞算",选择第一个,下载
这样就是下载好了,
打开它,出现这个页面,点击登录
4.登录
登录成功
三.模块设计与编码
1.先设计大概模块
输入以下指令:
生成一个电商系统项目,包括商品的增删改查、分类等、订单流程(订单的创建、支付、发货、收货等状态管理)、用户中心(用户的注册、登录、个人信息管理、地址管理等。
我们可以看到,它先理解需求
然后设计接口
可选择表结构设计
然后处理逻辑(接口)
最后,生成源码
我们可以看到,它正在生成
生成的代码如下:
2.代码展示
entity 包下类示例
User.java
java
package com.feisuanyz.entity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* <p>
* 用户实体类
* </p>
* @author apple
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name = "users")
public class User {
/**
* 主键ID
*/
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
/**
* 用户名(唯一)
*/
@Column(unique = true, nullable = false)
private String username;
/**
* 密码
*/
@Column(nullable = false)
private String password;
/**
* 手机号
*/
private String phone;
/**
* 昵称
*/
private String nickname;
/**
* 邮箱
*/
private String email;
}
Goods.java
java
package com.feisuanyz.entity;
import jakarta.persistence.*;
import java.math.BigDecimal;
import lombok.*;
/**
* <p>
* 商品实体类
* </p>
* @author apple
*/
@Entity
@Table(name = "t_goods")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Goods {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long goodsId;
@Column(nullable = false)
private String goodsName;
@Column(nullable = false)
private Long categoryId;
@Column(precision = 10, scale = 2, nullable = false)
private BigDecimal price;
@Column(nullable = false)
private Integer stock;
private String description;
}
dto包下类示例
LoginRequestDTO.java
java
package com.feisuanyz.dto;
import jakarta.validation.constraints.NotBlank;
import lombok.Data;
/**
* <p>
* 用户登录请求参数封装对象
* </p>
* @author apple
*/
@Data
public class LoginRequestDTO {
/**
* 用户名(必填)
*/
@NotBlank(message = "用户名不能为空")
private String username;
/**
* 密码(必填)
*/
@NotBlank(message = "密码不能为空")
private String password;
}
GoodsAddDTO.java
java
package com.feisuanyz.dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import lombok.Data;
/**
* <p>
* 添加商品请求 DTO
* </p>
* @author apple
*/
@Data
public class GoodsAddDTO {
@NotBlank(message = "商品名称不能为空")
private String goodsName;
@NotNull(message = "分类ID不能为空")
private Long categoryId;
@NotNull(message = "价格不能为空")
private BigDecimal price;
@NotNull(message = "库存不能为空")
private Integer stock;
private String description;
}
repository包下接口示例
UserRepository.java
java
package com.feisuanyz.repository;
import com.feisuanyz.entity.UserDO;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
import org.springframework.stereotype.Repository;
import com.feisuanyz.entity.User;
/**
* <p>
* 用户查询接口
* </p>
* @author apple
*/
@Repository
public interface UserRepository extends JpaRepository<UserDO, Long> {
/**
* 根据用户名查找用户
* @param username 用户名
* @return Optional<User>
*/
Optional<User> findByUsername(String username);
}
GoodsRepository.java
java
package com.feisuanyz.repository;
import com.feisuanyz.entity.Goods;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import com.feisuanyz.entity.GoodsDO;
/**
* <p>
* 商品 Repository 接口
* </p>
* @author apple
*/
@Repository
public interface GoodsRepository extends JpaRepository<Goods, Long> {
Optional<Goods> findByGoodsName(String goodsName);
}
service包下接口及实现类示例
UserService.java
java
package com.feisuanyz.service;
import com.feisuanyz.dto.*;
import com.feisuanyz.dto.AddAddressRequestDTO;
import com.feisuanyz.dto.DeleteAddressRequestDTO;
import com.feisuanyz.dto.LoginRequestDTO;
import com.feisuanyz.dto.RegisterRequestDTO;
import com.feisuanyz.dto.UpdateUserInfoDTO;
/**
* <p>
* 用户服务接口
* </p>
* @author apple
*/
public interface UserService {
/**
* 用户注册
* @param request 注册请求参数
* @return RestResult 结果集
*/
com.feisuanyz.common.RestResult<?> register(RegisterRequestDTO request);
/**
* 用户登录
* @param request 登录请求参数
* @return RestResult 结果集
*/
com.feisuanyz.common.RestResult<?> login(LoginRequestDTO request);
/**
* 修改个人信息
* @param request 更新信息请求参数
* @return RestResult 结果集
*/
com.feisuanyz.common.RestResult<?> updateUserInfo(UpdateUserInfoDTO request);
/**
* 添加收货地址
* @param request 添加地址请求参数
* @return RestResult 结果集
*/
com.feisuanyz.common.RestResult<?> addAddress(AddAddressRequestDTO request);
/**
* 删除收货地址
* @param request 删除地址请求参数
* @return RestResult 结果集
*/
com.feisuanyz.common.RestResult<?> deleteAddress(DeleteAddressRequestDTO request);
}
UserServiceImpl.java
java
package com.feisuanyz.service.impl;
import com.feisuanyz.common.RestResult;
import com.feisuanyz.dto.*;
import com.feisuanyz.dto.AddAddressRequestDTO;
import com.feisuanyz.dto.DeleteAddressRequestDTO;
import com.feisuanyz.dto.LoginRequestDTO;
import com.feisuanyz.dto.RegisterRequestDTO;
import com.feisuanyz.dto.UpdateUserInfoDTO;
import com.feisuanyz.entity.Address;
import com.feisuanyz.entity.User;
import com.feisuanyz.repository.AddressRepository;
import com.feisuanyz.repository.UserRepository;
import com.feisuanyz.service.UserService;
import jakarta.transaction.Transactional;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* <p>
* 用户服务实现类
* </p>
* @author apple
*/
@Slf4j
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserRepository userRepository;
@Autowired
private AddressRepository addressRepository;
@Override
public RestResult<?> register(RegisterRequestDTO request) {
log.info("开始执行用户注册操作,用户名:{}", request.getUsername());
// 判断用户名是否已存在
if (userRepository.findByUsername(request.getUsername()).isPresent()) {
return RestResult.failure("000001", "用户名已存在");
}
try {
User user = new User();
user.setUsername(request.getUsername());
user.setPassword(request.getPassword()); // 注意实际应用中应加密存储
user.setPhone(request.getPhone());
userRepository.save(user);
log.info("用户注册成功,用户名:{}", request.getUsername());
return RestResult.success(user);
} catch (Exception e) {
log.error("用户注册失败,用户名:{},异常信息:{}", request.getUsername(), e.getMessage());
return RestResult.failure("999999", "系统错误,请稍后再试");
}
}
@Override
public RestResult<?> login(LoginRequestDTO request) {
log.info("开始执行用户登录操作,用户名:{}", request.getUsername());
Optional<User> optionalUser = userRepository.findByUsername(request.getUsername());
if (!optionalUser.isPresent()) {
return RestResult.failure("000001", "用户名或密码错误");
}
User user = optionalUser.get();
if (!request.getPassword().equals(user.getPassword())) { // 实际应用建议使用BCrypt等加密算法校验
return RestResult.failure("000001", "用户名或密码错误");
}
// 这里可以生成JWT token 或其他认证凭据
log.info("用户登录成功,用户名:{}", request.getUsername());
return RestResult.success(user);
}
@Override
public RestResult<?> updateUserInfo(UpdateUserInfoDTO request) {
log.info("开始执行更新用户信息操作,用户ID:{}", request.getUserId());
Optional<User> optionalUser = userRepository.findById(request.getUserId());
if (!optionalUser.isPresent()) {
return RestResult.failure("000001", "用户信息不存在");
}
try {
User user = optionalUser.get();
user.setNickname(request.getNickname());
user.setEmail(request.getEmail());
userRepository.save(user);
log.info("用户信息更新成功,用户ID:{}", request.getUserId());
return RestResult.success(user);
} catch (Exception e) {
log.error("用户信息更新失败,用户ID:{},异常信息:{}", request.getUserId(), e.getMessage());
return RestResult.failure("999999", "系统错误,请稍后再试");
}
}
@Override
public RestResult<?> addAddress(AddAddressRequestDTO request) {
log.info("开始执行添加收货地址操作,用户ID:{}", request.getUserId());
if (!userRepository.existsById(request.getUserId())) {
return RestResult.failure("000001", "用户信息不存在");
}
try {
Address address = new Address();
address.setUserId(request.getUserId());
address.setConsignee(request.getConsignee());
address.setPhone(request.getPhone());
address.setAddress(request.getAddress());
addressRepository.save(address);
log.info("收货地址添加成功,用户ID:{}", request.getUserId());
return RestResult.success(address);
} catch (Exception e) {
log.error("收货地址添加失败,用户ID:{},异常信息:{}", request.getUserId(), e.getMessage());
return RestResult.failure("999999", "系统错误,请稍后再试");
}
}
@Override
public RestResult<?> deleteAddress(DeleteAddressRequestDTO request) {
log.info("开始执行删除收货地址操作,地址ID:{}", request.getAddressId());
if (!addressRepository.existsById(request.getAddressId())) {
return RestResult.failure("000001", "收货地址不存在");
}
try {
addressRepository.deleteById(request.getAddressId());
log.info("收货地址删除成功,地址ID:{}", request.getAddressId());
return RestResult.success(null);
} catch (Exception e) {
log.error("收货地址删除失败,地址ID:{},异常信息:{}", request.getAddressId(), e.getMessage());
return RestResult.failure("999999", "系统错误,请稍后再试");
}
}
}
GoodsService.java
java
package com.feisuanyz.service;
import com.feisuanyz.common.RestResult;
import com.feisuanyz.dto.GoodsAddDTO;
import com.feisuanyz.dto.GoodsModifyDTO;
import com.feisuanyz.dto.GoodsPageQueryDTO;
import com.feisuanyz.dto.GoodsQueryDTO;
import com.feisuanyz.vo.GoodsVO;
import java.util.List;
/**
* <p>
* 商品服务接口
* </p>
* @author apple
*/
public interface GoodsService {
/**
* 新增商品
*
* @param dto 商品新增参数
* @return RestResult 结果
*/
RestResult<Void> add(GoodsAddDTO dto);
/**
* 删除商品
*
* @param id 商品 ID
* @return RestResult 结果
*/
RestResult<Void> delete(Long id);
/**
* 修改商品
*
* @param dto 商品修改参数
* @return RestResult 结果
*/
RestResult<Void> modify(GoodsModifyDTO dto);
/**
* 查询商品详情
*
* @param query 查询参数
* @return RestResult 结果
*/
RestResult<GoodsVO> detail(GoodsQueryDTO query);
/**
* 分页查询商品列表
*
* @param query 查询参数
* @return RestResult 结果
*/
RestResult<List<GoodsVO>> list(GoodsPageQueryDTO query);
}
GoodsServiceImpl.java
java
package com.feisuanyz.service.impl;
import com.feisuanyz.common.RestResult;
import com.feisuanyz.dto.GoodsAddDTO;
import com.feisuanyz.dto.GoodsModifyDTO;
import com.feisuanyz.dto.GoodsPageQueryDTO;
import com.feisuanyz.dto.GoodsQueryDTO;
import com.feisuanyz.entity.Goods;
import com.feisuanyz.repository.GoodsRepository;
import com.feisuanyz.service.GoodsService;
import com.feisuanyz.vo.GoodsVO;
import jakarta.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
/**
* <p>
* 商品服务实现类
* </p>
* @author apple
*/
@Slf4j
@Service
public class GoodsServiceImpl implements GoodsService {
@Autowired
private GoodsRepository goodsRepository;
@Override
public RestResult<Void> add(@Valid GoodsAddDTO dto) {
if (!StringUtils.hasText(dto.getGoodsName())) {
return RestResult.failure("000001", "参数不能为空");
}
// 检查商品名称是否已存在
if (goodsRepository.findByGoodsName(dto.getGoodsName()).isPresent()) {
return RestResult.failure("000001", "商品名称已存在");
}
try {
Goods entity = Goods.builder()
.goodsName(dto.getGoodsName())
.categoryId(dto.getCategoryId())
.price(dto.getPrice())
.stock(dto.getStock())
.description(dto.getDescription())
.build();
goodsRepository.save(entity);
log.info("新增商品成功,商品名称:{}", dto.getGoodsName());
return RestResult.success(null);
} catch (Exception e) {
log.error("新增商品失败", e);
return RestResult.failure("999999", "系统异常");
}
}
@Override
public RestResult<Void> delete(Long id) {
if (id == null || id <= 0) {
return RestResult.failure("000001", "参数错误");
}
Goods entity = goodsRepository.findById(id).orElse(null);
if (entity == null) {
return RestResult.failure("000001", "商品不存在");
}
try {
goodsRepository.deleteById(id);
log.info("删除商品成功,商品ID:{}", id);
return RestResult.success(null);
} catch (Exception e) {
log.error("删除商品失败", e);
return RestResult.failure("999999", "系统异常");
}
}
@Override
public RestResult<Void> modify(@Valid GoodsModifyDTO dto) {
if (dto.getGoodsId() == null || dto.getGoodsId() <= 0) {
return RestResult.failure("000001", "参数错误");
}
Goods entity = goodsRepository.findById(dto.getGoodsId()).orElse(null);
if (entity == null) {
return RestResult.failure("000001", "商品不存在");
}
try {
BeanUtils.copyProperties(dto, entity, "goodsId");
goodsRepository.save(entity);
log.info("修改商品成功,商品ID:{}", dto.getGoodsId());
return RestResult.success(null);
} catch (Exception e) {
log.error("修改商品失败", e);
return RestResult.failure("999999", "系统异常");
}
}
@Override
public RestResult<GoodsVO> detail(GoodsQueryDTO query) {
if (query.getGoodsId() == null || query.getGoodsId() <= 0) {
return RestResult.failure("000001", "参数错误");
}
Goods entity = goodsRepository.findById(query.getGoodsId()).orElse(null);
if (entity == null) {
return RestResult.failure("000001", "商品不存在");
}
GoodsVO vo = new GoodsVO();
BeanUtils.copyProperties(entity, vo);
return RestResult.success(vo);
}
@Override
public RestResult<List<GoodsVO>> list(GoodsPageQueryDTO query) {
if (query.getPageNo() == null || query.getPageSize() == null ||
query.getPageNo() <= 0 || query.getPageSize() <= 0) {
return RestResult.failure("000001", "分页参数错误");
}
Sort sort = Sort.by(Sort.Direction.DESC, "goodsId");
Pageable pageable = PageRequest.of(query.getPageNo() - 1, query.getPageSize(), sort);
Page<Goods> pageResult = goodsRepository.findAll(pageable);
List<GoodsVO> result = pageResult.getContent().stream()
.map(item -> {
GoodsVO vo = new GoodsVO();
BeanUtils.copyProperties(item, vo);
return vo;
})
.collect(Collectors.toList());
return RestResult.success(result);
}
}
controller包下类示例
UserController.java
java
package com.feisuanyz.controller;
import com.feisuanyz.common.RestResult;
import com.feisuanyz.dto.*;
import com.feisuanyz.dto.AddAddressRequestDTO;
import com.feisuanyz.dto.DeleteAddressRequestDTO;
import com.feisuanyz.dto.LoginRequestDTO;
import com.feisuanyz.dto.RegisterRequestDTO;
import com.feisuanyz.dto.UpdateUserInfoDTO;
import com.feisuanyz.service.UserService;
import jakarta.validation.Valid;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 用户控制器
* </p>
* @author apple
*/
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 用户注册接口
* @param request 注册请求参数
* @return RestResult 结果集
*/
@PostMapping("/register")
public RestResult<?> register(@RequestBody @Valid RegisterRequestDTO request) {
log.info("收到用户注册请求: {}", request.getUsername());
return userService.register(request);
}
/**
* 用户登录接口
* @param request 登录请求参数
* @return RestResult 结果集
*/
@PostMapping("/login")
public RestResult<?> login(@RequestBody @Valid LoginRequestDTO request) {
log.info("收到用户登录请求: {}", request.getUsername());
return userService.login(request);
}
/**
* 修改个人信息接口
* @param request 更新信息请求参数
* @return RestResult 结果集
*/
@PostMapping("/updateInfo")
public RestResult<?> updateUserInfo(@RequestBody @Valid UpdateUserInfoDTO request) {
log.info("收到修改用户信息请求,用户ID: {}", request.getUserId());
return userService.updateUserInfo(request);
}
/**
* 添加收货地址接口
* @param request 添加地址请求参数
* @return RestResult 结果集
*/
@PostMapping("/addAddress")
public RestResult<?> addAddress(@RequestBody @Valid AddAddressRequestDTO request) {
log.info("收到添加收货地址请求,用户ID: {}", request.getUserId());
return userService.addAddress(request);
}
/**
* 删除收货地址接口
* @param request 删除地址请求参数
* @return RestResult 结果集
*/
@PostMapping("/deleteAddress")
public RestResult<?> deleteAddress(@RequestBody @Valid DeleteAddressRequestDTO request) {
log.info("收到删除收货地址请求,地址ID: {}", request.getAddressId());
return userService.deleteAddress(request);
}
}
GoodsController.java
java
package com.feisuanyz.controller;
import com.feisuanyz.common.RestResult;
import com.feisuanyz.dto.GoodsAddDTO;
import com.feisuanyz.dto.GoodsModifyDTO;
import com.feisuanyz.dto.GoodsPageQueryDTO;
import com.feisuanyz.dto.GoodsQueryDTO;
import com.feisuanyz.service.GoodsService;
import com.feisuanyz.vo.GoodsVO;
import jakarta.validation.Valid;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* 商品控制器
* </p>
* @author apple
*/
@Slf4j
@RestController
@RequestMapping("/goods")
public class GoodsController {
@Autowired
private GoodsService goodsService;
/**
* 新增商品
*
* @param dto 商品新增参数
* @return RestResult 结果
*/
@PostMapping("/add")
public RestResult<Void> add(@RequestBody @Valid GoodsAddDTO dto) {
log.info("新增商品请求: {}", dto);
return goodsService.add(dto);
}
/**
* 删除商品
*
* @param id 商品 ID
* @return RestResult 结果
*/
@DeleteMapping("/delete/{id}")
public RestResult<Void> delete(@PathVariable Long id) {
log.info("删除商品请求: id={}", id);
return goodsService.delete(id);
}
/**
* 修改商品
*
* @param dto 商品修改参数
* @return RestResult 结果
*/
@PutMapping("/modify")
public RestResult<Void> modify(@RequestBody @Valid GoodsModifyDTO dto) {
log.info("修改商品请求: {}", dto);
return goodsService.modify(dto);
}
/**
* 查询商品详情
*
* @param query 查询参数
* @return RestResult 结果
*/
@GetMapping("/detail")
public RestResult<com.feisuanyz.vo.GoodsVO> detail(GoodsQueryDTO query) {
log.info("查询商品详情请求: {}", query);
return goodsService.detail(query);
}
/**
* 分页查询商品列表
*
* @param query 查询参数
* @return RestResult 结果
*/
@GetMapping("/list")
public RestResult<List<com.feisuanyz.vo.GoodsVO>> list(GoodsPageQueryDTO query) {
log.info("分页查询商品列表请求: {}", query);
return goodsService.list(query);
}
}
四.遇到的问题及解决
- 性能问题:在商品列表查询时,数据量较大,查询速度慢。通过分析SQL语句,发现没有添加合适的索引。于是在商品表的商品名称、分类ID等字段添加索引,优化后查询速度明显提升。
- 事务问题 :订单创建过程中,需要同时插入订单表和订单商品关联表数据,若其中一个插入失败,会导致数据不一致。使用Spring的
@Transactional
注解,将订单创建方法标记为事务方法,保证数据的一致性。
五.自我感想
在开发电商系统核心功能模块的过程中,我对电商业务有了更深入的理解,从商品的展示、用户的购买到订单的处理,每一个环节都紧密相连。技术方面,也更加熟练地运用了Spring Boot、MyBatis等框架,对数据库设计和优化也有了更多的实践经验。同时,在遇到问题时,学会了从不同角度去分析和解决,比如性能问题从SQL和索引入手,事务问题利用Spring的事务管理机制。
总结
通过本次电商系统核心功能模块的设计与实现,我成功构建了包含商品、订单、用户核心功能的模块,涵盖了从需求分析、模块设计、编码实现到优化调试的完整流程。在这个过程中,不仅提升了技术能力,也积累了电商系统开发的经验。后续,我会根据实际需求,对系统进行更多的功能拓展和优化,使其更加完善,更好地满足电商业务的需求。