开发工具:IDEA
服务器:Tomcat9.0, jdk1.8
项目构建:maven
数据库:mysql5.7
系统用户前台和管理后台两部分,项目采用前后端分离
前端技术:vue +elementUI
服务端技术:springboot+mybatis
项目功能描述:
一、前台功能
1、登录、注册、搜索商品、首页、商品详情
2、发送留言、回复留言、发布闲置、留言消息
3、下架闲置、收藏商品,取消收藏、立即购买
4、取消订单、立即支付、发货、确认收货
5、个人中心:修改头像、编辑个人信息、修改密码
6、我的发布、我的下架、我的收藏、我的卖出、我买到的
7、收货地址:添加、修改、删除、设置默认
退出登录等功能
二、后台功能
登录、闲置管理、订单管理、用户管理
前台截图:
后台截图:
package com.second.hand.trading.server.service.impl;
import com.second.hand.trading.server.dao.IdleItemDao;
import com.second.hand.trading.server.dao.OrderDao;
import com.second.hand.trading.server.model.IdleItemModel;
import com.second.hand.trading.server.model.OrderModel;
import com.second.hand.trading.server.service.OrderService;
import com.second.hand.trading.server.utils.OrderTask;
import com.second.hand.trading.server.utils.OrderTaskHandler;
import com.second.hand.trading.server.vo.PageVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;
@Service
public class OrderServiceImpl implements OrderService {
@Resource
private OrderDao orderDao;
@Resource
private IdleItemDao idleItemDao;
/**
* 新增订单,同时下架闲置
* 用了事务串行化,后续要优化,修改更新的sql,增加更新条件,而不是在代码中判断条件
* 业务逻辑可优化,改为支付时才下架。
* 新功能待做,需要新增订单超时处理
* (订单超时:
* 1、重新上架闲置;2、修改订单状态;
* 3、确保订单取消前不会影响用户的支付,支付前要判断订单状态并加读锁,取消订单时要判断订单状态为未支付才能取消;
* 4、保证延期任务一定执行,即确保任务不会因为系统异常而消失)
* @param orderModel
* @return
*/
private static HashMap<Integer,ReentrantLock> lockMap=new HashMap<>();
static {
// ReentrantLock lock=new ReentrantLock(true);
for(int i=0;i<100;i++){
lockMap.put(i,new ReentrantLock(true));
}
}
public boolean addOrder(OrderModel orderModel){
IdleItemModel idleItemModel=idleItemDao.selectByPrimaryKey(orderModel.getIdleId());
System.out.println(idleItemModel.getIdleStatus());
if(idleItemModel.getIdleStatus()!=1){
return false;
}
IdleItemModel idleItem=new IdleItemModel();
idleItem.setId(orderModel.getIdleId());
idleItem.setUserId(idleItemModel.getUserId());
idleItem.setIdleStatus((byte)2);
int key= (int) (orderModel.getIdleId()%100);
ReentrantLock lock=lockMap.get(key);
boolean flag;
try {
lock.lock();
flag=addOrderHelp(idleItem,orderModel);
}finally {
lock.unlock();
}
return flag;
}
@Transactional(rollbackFor = Exception.class)
public boolean addOrderHelp(IdleItemModel idleItem,OrderModel orderModel){
IdleItemModel idleItemModel=idleItemDao.selectByPrimaryKey(orderModel.getIdleId());
if(idleItemModel.getIdleStatus()!=1){
return false;
}
if(idleItemDao.updateByPrimaryKeySelective(idleItem)==1){
if(orderDao.insert(orderModel)==1){
orderModel.setOrderStatus((byte) 4);
//半小时未支付则取消订单
OrderTaskHandler.addOrder(new OrderTask(orderModel,30*60));
return true;
}else {
new RuntimeException();
}
}
return false;
}
/**
* 获取订单信息,同时获取对应的闲置信息
* @param id
* @return
*/
public OrderModel getOrder(Long id){
OrderModel orderModel=orderDao.selectByPrimaryKey(id);
orderModel.setIdleItem(idleItemDao.selectByPrimaryKey(orderModel.getIdleId()));
return orderModel;
}
/**
* 更新订单状态,无验证,后期修改为定制的更新sql
* 后期改为在支付时下架闲置
* @param orderModel
* @return
*/
@Transactional(rollbackFor = Exception.class)
public boolean updateOrder(OrderModel orderModel){
//不可修改的信息
orderModel.setOrderNumber(null);
orderModel.setUserId(null);
orderModel.setIdleId(null);
orderModel.setCreateTime(null);
if(orderModel.getOrderStatus()==4){
//取消订单,需要优化,减少数据库查询次数
OrderModel o=orderDao.selectByPrimaryKey(orderModel.getId());
if(o.getOrderStatus()!=0){
return false;
}
IdleItemModel idleItemModel=idleItemDao.selectByPrimaryKey(o.getIdleId());
if(idleItemModel.getIdleStatus()==2){
IdleItemModel idleItem=new IdleItemModel();
idleItem.setId(o.getIdleId());
idleItem.setUserId(idleItemModel.getUserId());
idleItem.setIdleStatus((byte)1);
if(orderDao.updateByPrimaryKeySelective(orderModel)==1){
if(idleItemDao.updateByPrimaryKeySelective(idleItem)==1){
return true;
}else {
new RuntimeException();
}
}
return false;
}else{
if(orderDao.updateByPrimaryKeySelective(orderModel)==1){
return true;
}else {
new RuntimeException();
}
}
}
return orderDao.updateByPrimaryKeySelective(orderModel)==1;
}
/**
* 获取我的所有订单
* 同时查询出对应的闲置信息,
* 未做分页
* userId建索引
* @param userId
* @return
*/
public List<OrderModel> getMyOrder(Long userId){
List<OrderModel> list=orderDao.getMyOrder(userId);
if(list.size()>0){
List<Long> idleIdList=new ArrayList<>();
for(OrderModel i:list){
idleIdList.add(i.getIdleId());
}
List<IdleItemModel> idleItemModelList=idleItemDao.findIdleByList(idleIdList);
Map<Long,IdleItemModel> map=new HashMap<>();
for(IdleItemModel idle:idleItemModelList){
map.put(idle.getId(),idle);
}
for(OrderModel i:list){
i.setIdleItem(map.get(i.getIdleId()));
}
}
return list;
}
/**
* 查询用户卖出的闲置
* @param userId
* @return
*/
@Transactional(isolation = Isolation.READ_COMMITTED)
public List<OrderModel> getMySoldIdle(Long userId){
List<IdleItemModel> list=idleItemDao.getAllIdleItem(userId);
List<OrderModel> orderList=null;
if(list.size()>0){
List<Long> idleIdList=new ArrayList<>();
for(IdleItemModel i:list){
idleIdList.add(i.getId());
}
orderList=orderDao.findOrderByIdleIdList(idleIdList);
Map<Long,IdleItemModel> map=new HashMap<>();
for(IdleItemModel idle:list){
map.put(idle.getId(),idle);
}
for(OrderModel o:orderList){
o.setIdleItem(map.get(o.getIdleId()));
}
}
return orderList;
}
public PageVo<OrderModel> getAllOrder(int page, int nums){
List<OrderModel> list=orderDao.getAllOrder((page-1)*nums,nums);
if(list.size()>0){
List<Long> idleIdList=new ArrayList<>();
for(OrderModel i:list){
idleIdList.add(i.getIdleId());
}
List<IdleItemModel> idleItemModelList=idleItemDao.findIdleByList(idleIdList);
Map<Long,IdleItemModel> map=new HashMap<>();
for(IdleItemModel idle:idleItemModelList){
map.put(idle.getId(),idle);
}
for(OrderModel i:list){
i.setIdleItem(map.get(i.getIdleId()));
}
}
int count=orderDao.countAllOrder();
return new PageVo<>(list,count);
}
public boolean deleteOrder(long id){
return orderDao.deleteByPrimaryKey(id)==1;
}
}
package com.second.hand.trading.server.service.impl;
import com.second.hand.trading.server.dao.UserDao;
import com.second.hand.trading.server.model.UserModel;
import com.second.hand.trading.server.service.UserService;
import com.second.hand.trading.server.vo.PageVo;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Resource
private UserDao userDao;
/**
* 查询一个用户的公开信息
* @param id
* @return
*/
public UserModel getUser(Long id){
return userDao.selectByPrimaryKey(id);
}
/**
* 登录,安全问题未解决
* @param accountNumber
* @param userPassword
* @return
*/
public UserModel userLogin(String accountNumber, String userPassword){
return userDao.userLogin(accountNumber,userPassword);
}
/**
*注册
* @param userModel
* @return
*/
public boolean userSignIn(UserModel userModel){
return userDao.insert(userModel) == 1;
}
/**
*修改用户公开信息,未验证用户身份
* @param userModel
* @return
*/
public boolean updateUserInfo(UserModel userModel){
return userDao.updateByPrimaryKeySelective(userModel)==1;
}
/**
* 修改密码
* @param newPassword
* @param oldPassword
* @param id
* @return
*/
public boolean updatePassword(String newPassword, String oldPassword,Long id){
return userDao.updatePassword(newPassword,oldPassword,id)==1;
}
public PageVo<UserModel> getUserByStatus(int status,int page ,int nums){
List<UserModel> list;
int count=0;
if(status==0){
count=userDao.countNormalUser();
list=userDao.getNormalUser((page-1)*nums, nums);
}else {
count=userDao.countBanUser();
list=userDao.getBanUser((page-1)*nums, nums);
}
return new PageVo<>(list,count);
}
}