Spring Boot电商项目(六)

简介: Spring Boot电商项目

五. 商品模块的开发


1. 后台新增商品的接口以及图片上传接口的开发


先来了解一下图片上传,图片名我们采用的是UUID(Universally Unique Identifier),中文名为通用唯一识别码。使用UUID可以防止图片重名的问题,以及可以防止别人爬图。他的生成规则:日期和时间、MAC地址、HashCode 、随机数等。


相关代码如下:

controller:


package com.haiexijun.mall.controller;
import com.haiexijun.mall.common.ApiRestResponse;
import com.haiexijun.mall.common.Constant;
import com.haiexijun.mall.exception.MallException;
import com.haiexijun.mall.exception.MallExceptionEnum;
import com.haiexijun.mall.model.pojo.Product;
import com.haiexijun.mall.model.request.addProductReq;
import com.haiexijun.mall.service.ProductService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.UUID;
/**
 * 描述: 后台商品管理Controller
 */
@Controller
@Api(tags = "后台商品管理相关接口",description = "有后台添加商品的接口、图片上传的接口、更新和删除商品的接口、批量上下架商品的接口、后台商品列表和商品详情的接口")
public class ProductAdminController {
    @Autowired
    ProductService productService;
    @PostMapping("/admin/product/add")
    @ApiOperation("后台添加商品")
    @ResponseBody
    public ApiRestResponse addProduct(@Valid @RequestBody addProductReq addProductReq) throws MallException {
        productService.add(addProductReq);
        return ApiRestResponse.success();
    }
    @PostMapping("/admin/product/file")
    @ResponseBody
    @ApiOperation("商品图片上传")
    public ApiRestResponse upload(HttpServletRequest httpServletRequest,@RequestParam("file") MultipartFile file) throws MallException {
        // 获取图片的原始名字
        String fileName= file.getOriginalFilename();
        //获取图片的后缀
        String suffixName= fileName.substring(fileName.lastIndexOf("."));
        //生成图片的UUID名称
        UUID uuid=UUID.randomUUID();
        String newFileName=uuid.toString()+suffixName;
        //创建文件夹
        File fileDirectory= new File(Constant.FILE_UPLOAD_DIR);
        // 创建文件
        File destFile= new File(Constant.FILE_UPLOAD_DIR+newFileName);
        //判断文件夹是否存在
        if (!fileDirectory.exists()){
            //如果不存在,就创建这个文件夹
            if (!fileDirectory.mkdir()){
                //如果没有建立成功,抛出异常
                throw new MallException(MallExceptionEnum.MKDIR_FAILED);
            }
        }
        try {
            file.transferTo(destFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        //把地址给返回回去
        try {
            return ApiRestResponse.success(getHost(new URI(httpServletRequest.getRequestURL()+""))+"/images/"+newFileName);
        } catch (URISyntaxException e) {
            return ApiRestResponse.error(MallExceptionEnum.UPLOAD_FAILED);
        }
    }
    private URI getHost(URI uri){
        URI effectiveURI;
        try {
            effectiveURI=new URI(uri.getScheme(),uri.getUserInfo(),uri.getHost(),uri.getPort(),null,null,null);
        } catch (URISyntaxException e) {
            effectiveURI=null;
        }
        return effectiveURI;
    }
}


service层:


package com.haiexijun.mall.service.impl;
import com.haiexijun.mall.exception.MallException;
import com.haiexijun.mall.exception.MallExceptionEnum;
import com.haiexijun.mall.model.dao.ProductMapper;
import com.haiexijun.mall.model.pojo.Product;
import com.haiexijun.mall.model.request.addProductReq;
import com.haiexijun.mall.service.ProductService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
 *描述: 商品服务实现类
 */
@Service
public class ProductServiceImpl implements ProductService {
    @Autowired
    ProductMapper productMapper;
    @Override
    public void add(addProductReq addProductReq) throws MallException {
        Product product=new Product();
        BeanUtils.copyProperties(addProductReq,product);
        Product productOld=productMapper.selectByName(addProductReq.getName());
        if (productOld!=null){
            throw new MallException(MallExceptionEnum.NAME_EXISTED);
        }
        int count= productMapper.insertSelective(product);
        if (count==0){
            throw new MallException(MallExceptionEnum.CREATE_FAILED);
        }
    }
}


其他层这里不多写了。

图片上传的地址我们要在application.properties配置文件中进行配置:


# 上传图片的路径,根据部署情况,可自行修改
file.upload_dir=D:\\


然后还要在MallWebMvcConfig这个配置类中对图片的资源映射配置,addResourceHandlers方法里面添加代码:


registry.addResourceHandler("/images/**").addResourceLocations(
                "file:"+ Constant.FILE_UPLOAD_DIR);


2.更新和删除商品的接口


controller层:


    @PostMapping("/admin/product/update")
    @ResponseBody
    @ApiOperation("后台更新商品信息")
    public ApiRestResponse updateProduct(@Valid @RequestBody UpdateProductReq updateProductReq) throws MallException {
        Product product = new Product();
        BeanUtils.copyProperties(updateProductReq,product);
        productService.update(product);
        return ApiRestResponse.success();
    }
    @PostMapping("/admin/product/delete")
    @ResponseBody
    @ApiOperation("后台删除商品信息")
    public ApiRestResponse deleteProduct(@RequestParam Integer id) throws MallException {
        productService.delete(id);
        return ApiRestResponse.success();
    }



service层:


    @Override
    public void update(Product updateProduct) throws MallException {
        Product productOld=productMapper.selectByName(updateProduct.getName());
        //如果同名不同id,不能进行修改
        if (productOld!=null&&!productOld.getId().equals(updateProduct.getId())){
            throw new MallException(MallExceptionEnum.NAME_EXISTED) ;
        }
        int count=productMapper.updateByPrimaryKeySelective(updateProduct);
        if (count==0){
            throw new MallException(MallExceptionEnum.UPDATE_FAILED);
        }
    }
    @Override
    public void delete(Integer id) throws MallException {
        Product productOld=productMapper.selectByPrimaryKey(id);
        //如果查不到该记录,无法删除
        if (productOld==null){
            throw new MallException(MallExceptionEnum.DELETE_FAILED) ;
        }
        int count=productMapper.deleteByPrimaryKey(id);
        if (count==0){
            throw new MallException(MallExceptionEnum.DELETE_FAILED);
        }
    }


3. 批量上下架商品的接口


对于Mybatis而言,它的一个能力就是遍历List。比如说我们传进去一个列表,那想把这里面的所有符合这个列表Id的都进行上下架状态的更新。我们要实现的话,就要在where语句中进行拼接。

controller层:


    @PostMapping("/admin/product/batchUpdateSellStatus")
    @ResponseBody
    @ApiOperation("后台批量上下架")
    public ApiRestResponse batchUpdateSellStatus(@RequestParam Integer[] ids,@RequestParam Integer sellStatus){
        productService.batchUpdateSellStatus(ids, sellStatus);
        return ApiRestResponse.success();
    }


service层:


    @Override
    public void batchUpdateSellStatus(Integer[] ids,Integer sellStatus){
        productMapper.batchUpdateSellStatus(ids,sellStatus);
    }


mapper.xml:


  <update id="batchUpdateSellStatus">
    update mall_product
    set status=#{sellStatus}
    where id in
    <foreach collection="ids" close=")" item="id" open="(" separator=",">
      #{id}
    </foreach>
  </update>


六.购物车模块


1.部分业务流程


f4d1e1b186bf41c29e5427f46a3aaf5d.png


2. 核心代码


controller层:


package com.haiexijun.mall.controller;
import com.haiexijun.mall.common.ApiRestResponse;
import com.haiexijun.mall.exception.MallException;
import com.haiexijun.mall.filter.UserFilter;
import com.haiexijun.mall.service.CartService;
import com.haiexijun.mall.vo.CartVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
 * 描述: 购物车Controller
 */
@RestController
@Api(tags = "购物车相关的接口")
@RequestMapping("/cart")
public class CartController {
    @Autowired
    CartService cartService;
    @PostMapping("/add")
    @ApiOperation("商品加入购物车")
    public ApiRestResponse add(@RequestParam Integer productId,@RequestParam Integer count) throws MallException {
        //内部获取用户id防止越权操作别人的
        Integer userId= UserFilter.currentUser.getId();
        List<CartVO> cartVOList= cartService.add(userId,productId,count);
        return ApiRestResponse.success(cartVOList);
    }
    @ApiOperation("获取购物车列表")
    @GetMapping("/list")
    public ApiRestResponse list(){
        //内部获取用户id防止越权操作别人的
        Integer userId= UserFilter.currentUser.getId();
        List<CartVO> carList =cartService.list(userId);
        return ApiRestResponse.success(carList);
    }
    @ApiOperation("更新购物车")
    @PostMapping("/update")
    public ApiRestResponse update(@RequestParam Integer productId,@RequestParam Integer count) throws MallException {
        //内部获取用户id防止越权操作别人的
        Integer userId= UserFilter.currentUser.getId();
        List<CartVO> cartVOList=cartService.update(userId,productId,count);
        return ApiRestResponse.success(cartVOList);
    }
    @ApiOperation("删除购物车")
    @PostMapping("/delete")
    public ApiRestResponse update(@RequestParam Integer productId) throws MallException {
        //内部获取用户id防止越权操作别人的
        Integer userId= UserFilter.currentUser.getId();
        List<CartVO> cartVOList=cartService.delete(userId,productId);
        return ApiRestResponse.success(cartVOList);
    }
    @ApiOperation("单个选中/不选中购物车的商品")
    @PostMapping("/select")
    public ApiRestResponse select(@RequestParam Integer productId,@RequestParam Integer selected) throws MallException {
        //内部获取用户id防止越权操作别人的
        Integer userId= UserFilter.currentUser.getId();
        List<CartVO> cartVOList=cartService.selectOrNot(userId,productId,selected);
        return ApiRestResponse.success(cartVOList);
    }
    @ApiOperation("全部选中/不选中购物车的商品")
    @PostMapping("/selectAll")
    public ApiRestResponse selectAll(@RequestParam Integer selected) throws MallException {
        //内部获取用户id防止越权操作别人的
        Integer userId= UserFilter.currentUser.getId();
        List<CartVO> cartVOList=cartService.selectAll(userId,selected);
        return ApiRestResponse.success(cartVOList);
    }
}


service层:


package com.haiexijun.mall.service.impl;
import com.haiexijun.mall.common.Constant;
import com.haiexijun.mall.exception.MallException;
import com.haiexijun.mall.exception.MallExceptionEnum;
import com.haiexijun.mall.model.dao.CartMapper;
import com.haiexijun.mall.model.dao.ProductMapper;
import com.haiexijun.mall.model.pojo.Cart;
import com.haiexijun.mall.model.pojo.Product;
import com.haiexijun.mall.service.CartService;
import com.haiexijun.mall.vo.CartVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * 购物车Service的实现类
 */
@Service
public class CartServiceImpl implements CartService {
    @Autowired
    ProductMapper productMapper;
    @Autowired
    CartMapper cartMapper;
    @Override
    public List<CartVO> add(Integer userId, Integer productId, Integer count) throws MallException {
        validProduct(productId,count);
        Cart cart=cartMapper.selectCartByUserIdAndProductId(userId,productId);
        if (cart==null){
            //如果这个商品之前不在购物车里面,就要新增一个记录
            cart=new Cart();
            cart.setProductId(productId);
            cart.setUserId(userId);
            cart.setQuantity(count);
            cart.setSelected(Constant.Cart.CHECKED);
            cartMapper.insertSelective(cart);
        }else {
            //如果这个商品之前在购物车里面,则数量增加
            count=count+cart.getQuantity();
            Cart cartNew=new Cart();
            cartNew.setQuantity(count);
            cartNew.setId(cart.getId());
            cartNew.setProductId(cart.getProductId());
            cartNew.setUserId(cart.getUserId());
            cartNew.setSelected(Constant.Cart.CHECKED);
            cartMapper.updateByPrimaryKeySelective(cartNew);
        }
        return this.list(userId);
    }
    private void validProduct(Integer productId,Integer count) throws MallException {
        Product product=productMapper.selectByPrimaryKey(productId);
        // 判断商品是否存在,是否上架
        if (product==null||product.getStatus().equals(Constant.SaleStatus.NOT_SELL)){
            throw new MallException(MallExceptionEnum.NOT_SELL);
        }
        //判断商品库存,如果库存不足够也不行
        if (count>product.getStock()){
            throw new MallException(MallExceptionEnum.NOT_ENOUGH);
        }
    }
    @Override
    public List<CartVO> list(Integer userId){
       List<CartVO> cartVOS= cartMapper.selectList(userId);
        for (int i = 0; i < cartVOS.size(); i++) {
            CartVO cartVO=cartVOS.get(i);
            cartVO.setTotalPrice(cartVO.getPrice()*cartVO.getQuantity());
        }
        return cartVOS;
    }
    @Override
    public List<CartVO> update(Integer userId, Integer productId, Integer count) throws MallException {
        validProduct(productId,count);
        Cart cart=cartMapper.selectCartByUserIdAndProductId(userId,productId);
        if (cart==null){
            //如果这个商品之前不在购物车里面,要报错的,无法更新
            throw new MallException(MallExceptionEnum.UPDATE_FAILED);
        }else {
            //如果这个商品之前在购物车里面,则更新数量
            Cart cartNew=new Cart();
            cartNew.setQuantity(count);
            cartNew.setId(cart.getId());
            cartNew.setProductId(cart.getProductId());
            cartNew.setUserId(cart.getUserId());
            cartNew.setSelected(Constant.Cart.CHECKED);
            cartMapper.updateByPrimaryKeySelective(cartNew);
        }
        return this.list(userId);
    }
    @Override
    public List<CartVO> delete(Integer userId, Integer productId) throws MallException {
        Cart cart=cartMapper.selectCartByUserIdAndProductId(userId,productId);
        if (cart==null){
            //如果这个商品之前不在购物车里面,要报错的,无法删除
            throw new MallException(MallExceptionEnum.DELETE_FAILED);
        }else {
            //如果这个商品之前在购物车里面,则更新数量
            cartMapper.deleteByPrimaryKey(cart.getId());
        }
        return this.list(userId);
    }
    @Override
    public List<CartVO> selectOrNot(Integer userId, Integer productId, Integer selected) throws MallException {
        Cart cart=cartMapper.selectCartByUserIdAndProductId(userId,productId);
        if (cart==null){
            throw new MallException(MallExceptionEnum.UPDATE_FAILED);
        }else {
            cartMapper.selectOrNot(userId,productId,selected);
        }
        return this.list(userId);
    }
    @Override
    public List<CartVO> selectAll(Integer userId,Integer selected){
        cartMapper.selectOrNot(userId,null,selected);
        return this.list(userId);
    }
}


dao层:


package com.haiexijun.mall.model.dao;
import com.haiexijun.mall.model.pojo.Cart;
import com.haiexijun.mall.vo.CartVO;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface CartMapper {
    int deleteByPrimaryKey(Integer id);
    int insert(Cart record);
    int insertSelective(Cart record);
    Cart selectByPrimaryKey(Integer id);
    int updateByPrimaryKeySelective(Cart record);
    int updateByPrimaryKey(Cart record);
    Cart selectCartByUserIdAndProductId(@Param("userId") Integer userId,@Param("productId") Integer productId);
    List<CartVO> selectList(@Param("userId") Integer userId);
    Integer selectOrNot(@Param("userId") Integer userId,@Param("productId") Integer productId,@Param("selected") Integer selected);
}


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.haiexijun.mall.model.dao.CartMapper">
  <resultMap id="BaseResultMap" type="com.haiexijun.mall.model.pojo.Cart">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="product_id" jdbcType="INTEGER" property="productId" />
    <result column="user_id" jdbcType="INTEGER" property="userId" />
    <result column="quantity" jdbcType="INTEGER" property="quantity" />
    <result column="selected" jdbcType="INTEGER" property="selected" />
    <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
    <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
  </resultMap>
  <sql id="Base_Column_List">
    id, product_id, user_id, quantity, selected, create_time, update_time
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
    select 
    <include refid="Base_Column_List" />
    from mall_cart
    where id = #{id,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Integer">
    delete from mall_cart
    where id = #{id,jdbcType=INTEGER}
  </delete>
  <insert id="insert" parameterType="com.haiexijun.mall.model.pojo.Cart">
    insert into mall_cart (id, product_id, user_id, 
      quantity, selected, create_time, 
      update_time)
    values (#{id,jdbcType=INTEGER}, #{productId,jdbcType=INTEGER}, #{userId,jdbcType=INTEGER}, 
      #{quantity,jdbcType=INTEGER}, #{selected,jdbcType=INTEGER}, #{createTime,jdbcType=TIMESTAMP}, 
      #{updateTime,jdbcType=TIMESTAMP})
  </insert>
  <insert id="insertSelective" parameterType="com.haiexijun.mall.model.pojo.Cart">
    insert into mall_cart
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="productId != null">
        product_id,
      </if>
      <if test="userId != null">
        user_id,
      </if>
      <if test="quantity != null">
        quantity,
      </if>
      <if test="selected != null">
        selected,
      </if>
      <if test="createTime != null">
        create_time,
      </if>
      <if test="updateTime != null">
        update_time,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=INTEGER},
      </if>
      <if test="productId != null">
        #{productId,jdbcType=INTEGER},
      </if>
      <if test="userId != null">
        #{userId,jdbcType=INTEGER},
      </if>
      <if test="quantity != null">
        #{quantity,jdbcType=INTEGER},
      </if>
      <if test="selected != null">
        #{selected,jdbcType=INTEGER},
      </if>
      <if test="createTime != null">
        #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="updateTime != null">
        #{updateTime,jdbcType=TIMESTAMP},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.haiexijun.mall.model.pojo.Cart">
    update mall_cart
    <set>
      <if test="productId != null">
        product_id = #{productId,jdbcType=INTEGER},
      </if>
      <if test="userId != null">
        user_id = #{userId,jdbcType=INTEGER},
      </if>
      <if test="quantity != null">
        quantity = #{quantity,jdbcType=INTEGER},
      </if>
      <if test="selected != null">
        selected = #{selected,jdbcType=INTEGER},
      </if>
      <if test="createTime != null">
        create_time = #{createTime,jdbcType=TIMESTAMP},
      </if>
      <if test="updateTime != null">
        update_time = #{updateTime,jdbcType=TIMESTAMP},
      </if>
    </set>
    where id = #{id,jdbcType=INTEGER}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.haiexijun.mall.model.pojo.Cart">
    update mall_cart
    set product_id = #{productId,jdbcType=INTEGER},
      user_id = #{userId,jdbcType=INTEGER},
      quantity = #{quantity,jdbcType=INTEGER},
      selected = #{selected,jdbcType=INTEGER},
      create_time = #{createTime,jdbcType=TIMESTAMP},
      update_time = #{updateTime,jdbcType=TIMESTAMP}
    where id = #{id,jdbcType=INTEGER}
  </update>
  <select id="selectCartByUserIdAndProductId" parameterType="map" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List"/>
    from mall_cart
    where user_id=#{userId} and product_id=#{productId}
  </select>
  <select id="selectList" resultType="com.haiexijun.mall.vo.CartVO" parameterType="java.lang.Integer">
    select
    c.id as id,
    p.id as productId,
    c.user_id as userId,
    c.selected as selected,
    c.quantity as quantity,
    p.price as price,
    p.name as productName,
    p.image as productImage
    from mall_cart c
    left join mall_product p on p.id =c.product_id
    where c.user_id=#{userId}
    and p.status=1
  </select>
  <update id="selectOrNot" parameterType="map">
    update mall_cart
    set selected=#{selected}
    where user_id=#{userId}
    <if test="productId!=null">
        and product_id=#{productId}
    </if>
  </update>
</mapper>


七.订单模块的开发


1.下单流程


4b9542066f0d4773a24bcd8bdde03759.png


相关文章
|
4天前
|
Java 应用服务中间件 Maven
Spring Boot项目打war包(idea:多种方式)
Spring Boot项目打war包(idea:多种方式)
16 1
|
3天前
|
消息中间件 Java 数据安全/隐私保护
Spring Cloud 项目中实现推送消息到 RabbitMQ 消息中间件
Spring Cloud 项目中实现推送消息到 RabbitMQ 消息中间件
|
4天前
|
Java 应用服务中间件 Spring
【JavaEE】Spring Boot - 项目的创建和使用(下)
【JavaEE】Spring Boot - 项目的创建和使用
8 0
|
4天前
|
数据可视化 Java 应用服务中间件
【JavaEE】Spring Boot - 项目的创建和使用(上)
【JavaEE】Spring Boot - 项目的创建和使用
9 0
|
4天前
|
存储 Java 对象存储
【JavaEE】DI与DL的介绍-Spring项目的创建-Bean对象的存储与获取
【JavaEE】DI与DL的介绍-Spring项目的创建-Bean对象的存储与获取
9 0
|
4天前
|
Java 关系型数据库 MySQL
【Java Spring开源项目】新蜂(NeeBee)商城项目运行、分析、总结
【Java Spring开源项目】新蜂(NeeBee)商城项目运行、分析、总结
32 4
|
4天前
|
XML Java 数据格式
Spring 项目如何使用AOP
Spring 项目如何使用AOP
25 2
|
4天前
|
Java Spring
Spring boot项目如何发送邮件
Spring boot项目如何发送邮件
20 2
|
4天前
|
Java API 数据安全/隐私保护
【亮剑】如何在Java项目中结合Spring框架实现邮件发送功能
【4月更文挑战第30天】本文介绍了如何在Java项目中结合Spring框架实现邮件发送功能。首先,需在`pom.xml`添加Spring和JavaMail依赖。然后,在`applicationContext.xml`配置邮件发送器,包括SMTP服务器信息。接着,创建一个使用依赖注入的`EmailService`类,通过`JavaMailSender`发送邮件。最后,调用`EmailService`的`sendSimpleEmail`方法即可发送邮件。最佳实践包括:使用配置管理敏感信息,利用`MimeMessage`构造复杂邮件,异常处理和日志记录,以及在大量发送时考虑使用邮件队列。
|
4天前
|
Java Maven Docker
0.07 秒启动一个 SpringBoot 项目!Spring Native 很强!!
0.07 秒启动一个 SpringBoot 项目!Spring Native 很强!!
29 2