新蜂商城 项目笔记作业部分

新蜂商城 项目笔记

1、启动项目,访问api在线文档

http://localhost:8080/swagger-ui.html

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BoaSZ1T1-1638114613547)(C:\Users\chen\AppData\Roaming\Typora\typora-user-images\image-20211128181427273.png)]

1. result类

作者为api文档的返回结果定义了一个result类作为响应结果的模板

public class Result<T> implements Serializable {
    private static final long serialVersionUID = 1L;

    //业务码,比如成功、失败、权限不足等 code,可自行定义
    @ApiModelProperty("返回码")
    private int resultCode;
    //返回信息,后端在进行业务处理后返回给前端一个提示信息,可自行定义
    @ApiModelProperty("返回信息")
    private String message;
    //数据结果,泛型,可以是列表、单个对象、数字、布尔值等
    @ApiModelProperty("返回数据")
    private T data;

    public Result() {
    }

    public Result(int resultCode, String message) {
        this.resultCode = resultCode;
        this.message = message;
    }

    public int getResultCode() {
        return resultCode;
    }

    public void setResultCode(int resultCode) {
        this.resultCode = resultCode;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    @Override
    public String toString() {
        return "Result{" +
                "resultCode=" + resultCode +
                ", message='" + message + '\'' +
                ", data=" + data +
                '}';
    }
}

每次responsebody 都包括了三个部分

  • resultCode
  • message
  • data(其中data是泛型)

例子 :

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zjtZn5cF-1638114613550)(C:\Users\chen\AppData\Roaming\Typora\typora-user-images\image-20211128183745040.png)]

2.ResultGenerator

ResultGenerator是一个响应结果生成工具

  • 成功: genSuccessResult()三种,参数为空,message,data;
  • 失败: genFailResult()
  • 错误:genErrorResult()
public class ResultGenerator {
    private static final String DEFAULT_SUCCESS_MESSAGE = "SUCCESS";
    private static final String DEFAULT_FAIL_MESSAGE = "FAIL";
    private static final int RESULT_CODE_SUCCESS = 200;
    private static final int RESULT_CODE_SERVER_ERROR = 500;

    public static Result genSuccessResult() {
        Result result = new Result();
        result.setResultCode(RESULT_CODE_SUCCESS);
        result.setMessage(DEFAULT_SUCCESS_MESSAGE);
        return result;
    }

    public static Result genSuccessResult(String message) {
        Result result = new Result();
        result.setResultCode(RESULT_CODE_SUCCESS);
        result.setMessage(message);
        return result;
    }

    public static Result genSuccessResult(Object data) {
        Result result = new Result();
        result.setResultCode(RESULT_CODE_SUCCESS);
        result.setMessage(DEFAULT_SUCCESS_MESSAGE);
        result.setData(data);
        return result;
    }

    public static Result genFailResult(String message) {
        Result result = new Result();
        result.setResultCode(RESULT_CODE_SERVER_ERROR);
        if (StringUtils.isEmpty(message)) {
            result.setMessage(DEFAULT_FAIL_MESSAGE);
        } else {
            result.setMessage(message);
        }
        return result;
    }

    public static Result genErrorResult(int code, String message) {
        Result result = new Result();
        result.setResultCode(code);
        result.setMessage(message);
        return result;
    }
}

3. ServiceResultEnum

public enum ServiceResultEnum {
    ERROR("error"),

    SUCCESS("success"),

    DATA_NOT_EXIST("未查询到记录!"),

    PARAM_ERROR("参数错误!"),

    SAME_CATEGORY_EXIST("已存在同级同名的分类!"),

    SAME_LOGIN_NAME_EXIST("用户名已存在!"),

    LOGIN_NAME_NULL("请输入登录名!"),

    LOGIN_NAME_IS_NOT_PHONE("请输入正确的手机号!"),

    LOGIN_PASSWORD_NULL("请输入密码!"),

    LOGIN_VERIFY_CODE_NULL("请输入验证码!"),

    LOGIN_VERIFY_CODE_ERROR("验证码错误!"),

    SAME_INDEX_CONFIG_EXIST("已存在相同的首页配置项!"),

    GOODS_CATEGORY_ERROR("分类数据异常!"),

    SAME_GOODS_EXIST("已存在相同的商品信息!"),

    GOODS_NOT_EXIST("商品不存在!"),

    GOODS_PUT_DOWN("商品已下架!"),

    SHOPPING_CART_ITEM_LIMIT_NUMBER_ERROR("超出单个商品的最大购买数量!"),

    SHOPPING_CART_ITEM_NUMBER_ERROR("商品数量不能小于 1 !"),

    SHOPPING_CART_ITEM_TOTAL_NUMBER_ERROR("超出购物车最大容量!"),

    SHOPPING_CART_ITEM_EXIST_ERROR("已存在!无需重复添加!"),

    LOGIN_ERROR("登录失败!"),

    NOT_LOGIN_ERROR("未登录!"),

    ADMIN_NOT_LOGIN_ERROR("管理员未登录!"),

    TOKEN_EXPIRE_ERROR("无效认证!请重新登录!"),

    ADMIN_TOKEN_EXPIRE_ERROR("管理员登录过期!请重新登录!"),

    USER_NULL_ERROR("无效用户!请重新登录!"),

    LOGIN_USER_LOCKED_ERROR("用户已被禁止登录!"),

    ORDER_NOT_EXIST_ERROR("订单不存在!"),

    NULL_ADDRESS_ERROR("地址不能为空!"),

    ORDER_PRICE_ERROR("订单价格异常!"),

    ORDER_ITEM_NULL_ERROR("订单项异常!"),

    ORDER_GENERATE_ERROR("生成订单异常!"),

    SHOPPING_ITEM_ERROR("购物车数据异常!"),

    SHOPPING_ITEM_COUNT_ERROR("库存不足!"),

    ORDER_STATUS_ERROR("订单状态异常!"),

    OPERATE_ERROR("操作失败!"),

    REQUEST_FORBIDEN_ERROR("禁止该操作!"),

    NO_PERMISSION_ERROR("无权限!"),

    DB_ERROR("database error");

    private String result;

    ServiceResultEnum(String result) {
        this.result = result;
    }

    public String getResult() {
        return result;
    }

    public void setResult(String result) {
        this.result = result;
    }
}

2、 接口分析

1. 新蜂商城首页接口 New Bee Mall Index API

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pQOlnUvp-1638114613552)(C:\Users\chen\AppData\Roaming\Typora\typora-user-images\image-20211128224011589.png)]

/api/v1/index-infos

文件: NewBeeMallIndexAPI.java

作用: 获取首页数据

代码分析:

通过@Resource(Spring按Name依赖注入,@AutoWired是按Type依赖注入)获取了两个service的对象

	@Resource
    private NewBeeMallCarouselService newBeeMallCarouselService;

    @Resource
    private NewBeeMallIndexConfigService newBeeMallIndexConfigService
IndexInfoVo类

作者定义了一个IndexInfoVO继承Serializable类

IndexInfoVO里有四个列表

  1. 轮播图(列表)
  2. 首页热销商品(列表)
  3. 首页新品推荐(列表)
  4. 首页推荐商品(列表)
@Data
public class IndexInfoVO implements Serializable {

    @ApiModelProperty("轮播图(列表)")
    private List<NewBeeMallIndexCarouselVO> carousels;

    @ApiModelProperty("首页热销商品(列表)")
    private List<NewBeeMallIndexConfigGoodsVO> hotGoodses;

    @ApiModelProperty("首页新品推荐(列表)")
    private List<NewBeeMallIndexConfigGoodsVO> newGoodses;

    @ApiModelProperty("首页推荐商品(列表)")
    private List<NewBeeMallIndexConfigGoodsVO> recommendGoodses;
}

轮播图vo

/**
 * 首页配置商品VO
 */
@Data
public class NewBeeMallIndexCarouselVO implements Serializable {

    @ApiModelProperty("轮播图图片地址")
    private String carouselUrl;

    @ApiModelProperty("轮播图点击后的跳转路径")
    private String redirectUrl;
}

商品VO

/**
 * 首页配置商品VO
 */
@Data
public class NewBeeMallIndexConfigGoodsVO implements Serializable {

    @ApiModelProperty("商品id")
    private Long goodsId;
    @ApiModelProperty("商品名称")
    private String goodsName;
    @ApiModelProperty("商品简介")
    private String goodsIntro;
    @ApiModelProperty("商品图片地址")
    private String goodsCoverImg;
    @ApiModelProperty("商品价格")
    private Integer sellingPrice;
    @ApiModelProperty("商品标签")
    private String tag;
}
获取四个列表过程

调用newBeeMallCarouselService和newBeeMallIndexConfigService里的方法获取四个列表,并把四个列表set给IndexInfoVO对象。

  1. newBeeMallCarouselService.getCarouselsForIndex

顺藤摸瓜找到NewBeeMallCarouselServiceImpl实现类的getCarouselsForIndex方法

NewBeeMallCarouselServiceImpl.java

@Override
    public List<NewBeeMallIndexCarouselVO> getCarouselsForIndex(int number) {
        List<NewBeeMallIndexCarouselVO> newBeeMallIndexCarouselVOS = new ArrayList<>(number);
        List<Carousel> carousels = carouselMapper.findCarouselsByNum(number);
        if (!CollectionUtils.isEmpty(carousels)) {
            newBeeMallIndexCarouselVOS = BeanUtil.copyList(carousels, NewBeeMallIndexCarouselVO.class);
        }
        return newBeeMallIndexCarouselVOS;
    }

findCarouselsByNum对应了CarouselMapper.xml

<select id="findCarouselList" parameterType="Map" resultMap="BaseResultMap">
        select
        <include refid="Base_Column_List"/>
        from tb_newbee_mall_carousel
        where is_deleted = 0
        order by carousel_rank desc
        <if test="start!=null and limit!=null">
            limit #{start},#{limit}
        </if>
    </select>

(可能)其中BeanUtil.copyList的方法为了将一些具体list转成泛型list?

if (!CollectionUtils.isEmpty(carousels)) {
            newBeeMallIndexCarouselVOS = BeanUtil.copyList(carousels, NewBeeMallIndexCarouselVO.class);
        }

BeanUtil.java

public static <T> List<T> copyList(List sources, Class<T> clazz) {
        return copyList(sources, clazz, null);
    }

    public static <T> List<T> copyList(List sources, Class<T> clazz, Callback<T> callback) {
        List<T> targetList = new ArrayList<>();
        if (sources != null) {
            try {
                for (Object source : sources) {
                    T target = clazz.newInstance();
                    copyProperties(source, target);
                    if (callback != null) {
                        callback.set(source, target);
                    }
                    targetList.add(target);
                }
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return targetList;
    }
  1. newBeeMallIndexConfigService.getConfigGoodsesForIndex

顺藤摸瓜找到newBeeMallIndexConfigServiceImpl实现类的getConfigGoodsesForIndex方法

方法关键代码

List<NewBeeMallGoods> newBeeMallGoods = goodsMapper.selectByPrimaryKeys(goodsIds);

NewBeeMallGoodsMapper.xml

<select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="ResultMapWithBLOBs">
        select
        <include refid="Base_Column_List"/>
        ,
        <include refid="Blob_Column_List"/>
        from tb_newbee_mall_goods_info
        where goods_id = #{goodsId,jdbcType=BIGINT}
</select>

同样的转泛型处理

newBeeMallIndexConfigGoodsVOS = BeanUtil.copyList(newBeeMallGoods, NewBeeMallIndexConfigGoodsVO.class);

字符串过长导致文字超出的问题处理方法

for (NewBeeMallIndexConfigGoodsVO newBeeMallIndexConfigGoodsVO : newBeeMallIndexConfigGoodsVOS) {
                String goodsName = newBeeMallIndexConfigGoodsVO.getGoodsName();
                String goodsIntro = newBeeMallIndexConfigGoodsVO.getGoodsIntro();
                // 字符串过长导致文字超出的问题
                if (goodsName.length() > 30) {
                    goodsName = goodsName.substring(0, 30) + "...";
                    newBeeMallIndexConfigGoodsVO.setGoodsName(goodsName);
                }
                if (goodsIntro.length() > 22) {
                    goodsIntro = goodsIntro.substring(0, 22) + "...";
                    newBeeMallIndexConfigGoodsVO.setGoodsIntro(goodsIntro);
                }
            }

2. 新蜂商城用户操作相关接口 New Bee Mall Personal API

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dvY15n7L-1638114613555)(C:\Users\chen\AppData\Roaming\Typora\typora-user-images\image-20211128224037337.png)]

/api/v1/user

文件: NewBeeMallPersonalAPI.java

作用: 商城用户操作

代码分析:

a. NewBeeMallPersonalAPI

无论是登录接口 登出接口 用户注册 修改用户信息 主体都是同一套写法

  1. 调用NewBeeMallUserService中的方法(login,logout,register ,updateUserInfo)
  2. 调用Logger的info方法,添加相关信息
  3. 处理成功和失败的情况

例子: 登录接口

	@PostMapping("/user/login")
    @ApiOperation(value = "登录接口", notes = "返回token")
    public Result<String> login(@RequestBody @Valid MallUserLoginParam mallUserLoginParam) {
        if (!NumberUtil.isPhone(mallUserLoginParam.getLoginName())){
            return ResultGenerator.genFailResult(ServiceResultEnum.LOGIN_NAME_IS_NOT_PHONE.getResult());
        }
        String loginResult = newBeeMallUserService.login(mallUserLoginParam.getLoginName(), mallUserLoginParam.getPasswordMd5());

        logger.info("login api,loginName={},loginResult={}", mallUserLoginParam.getLoginName(), loginResult);

        //登录成功
        if (!StringUtils.isEmpty(loginResult) && loginResult.length() == Constants.TOKEN_LENGTH) {
            Result result = ResultGenerator.genSuccessResult();
            result.setData(loginResult);
            return result;
        }
        //登录失败
        return ResultGenerator.genFailResult(loginResult);
    }
b. NewBeeMallUserServiceImpl

(个人想法:token其实是记录在线情况)

login
  1. selectByLoginNameAndPasswd方法在tb_newbee_mall_user表中找到对应的user,无则为null
MallUser user = mallUserMapper.selectByLoginNameAndPasswd(loginName, passwordMD5);
  1. 判断返回的user是不是null,null直接返回错误信息,不是null就继续下一步。
if (user != null)
  1. 登录后分三种情况,

    第一种情况:新用户,没有登陆过,则为tb_newbee_mall_user_token添加一条新的token数据;

    第二种情况:用户登陆过并退出了,token表没有他的信息,也为他在tb_newbee_mall_user_token添加一条新的token数据;

    第三种情况:用户登陆过但没有退出,token表里有他的信息,则直接给tb_newbee_mall_user_token对应的用户修改token数据;

    (作者太聪明了)

    if (user.getLockedFlag() == 1) {
                    return ServiceResultEnum.LOGIN_USER_LOCKED_ERROR.getResult();
                }
                //登录后即执行修改token的操作
                String token = getNewToken(System.currentTimeMillis() + "", user.getUserId());
                MallUserToken mallUserToken = newBeeMallUserTokenMapper.selectByPrimaryKey(user.getUserId());
                //当前时间
                Date now = new Date();
                //过期时间
                Date expireTime = new Date(now.getTime() + 2 * 24 * 3600 * 1000);//过期时间 48 小时
                if (mallUserToken == null) {
                    mallUserToken = new MallUserToken();
                    mallUserToken.setUserId(user.getUserId());
                    mallUserToken.setToken(token);
                    mallUserToken.setUpdateTime(now);
                    mallUserToken.setExpireTime(expireTime);
                    //新增一条token数据
                    if (newBeeMallUserTokenMapper.insertSelective(mallUserToken) > 0) {
                        //新增成功后返回
                        return token;
                    }
                } else {
                    mallUserToken.setToken(token);
                    mallUserToken.setUpdateTime(now);
                    mallUserToken.setExpireTime(expireTime);
                    //更新
                    if (newBeeMallUserTokenMapper.updateByPrimaryKeySelective(mallUserToken) > 0) {
                        //修改成功后返回
                        return token;
                    }
                }
    
logout

直接调用delete方法,根据登录的用户id删除对应tb_newbee_mall_user_token表的token数据

@Override
    public Boolean logout(Long userId) {
        return newBeeMallUserTokenMapper.deleteByPrimaryKey(userId) > 0;
    }
register

insert方法

@Override
    public String register(String loginName, String password) {
        if (mallUserMapper.selectByLoginName(loginName) != null) {
            return ServiceResultEnum.SAME_LOGIN_NAME_EXIST.getResult();
        }
        MallUser registerUser = new MallUser();
        registerUser.setLoginName(loginName);
        registerUser.setNickName(loginName);
        registerUser.setIntroduceSign(Constants.USER_INTRO);
        String passwordMD5 = MD5Util.MD5Encode(password, "UTF-8");
        registerUser.setPasswordMd5(passwordMD5);
        if (mallUserMapper.insertSelective(registerUser) > 0) {
            return ServiceResultEnum.SUCCESS.getResult();
        }
        return ServiceResultEnum.DB_ERROR.getResult();
    }
updateUserInfo

分开写,先seletct id找到对应的用户,存入user,修改user对象的相关信息,最后将user对象传给update方法

@Override
public Boolean updateUserInfo(MallUserUpdateParam mallUser, Long userId) {
    MallUser user = mallUserMapper.selectByPrimaryKey(userId);
    if (user == null) {
        NewBeeMallException.fail(ServiceResultEnum.DATA_NOT_EXIST.getResult());
    }
    user.setNickName(mallUser.getNickName());
    //user.setPasswordMd5(mallUser.getPasswordMd5());
    //若密码为空字符,则表明用户不打算修改密码,使用原密码保存
    if (!MD5Util.MD5Encode("", "UTF-8").equals(mallUser.getPasswordMd5())){
        user.setPasswordMd5(mallUser.getPasswordMd5());
    }
    user.setIntroduceSign(mallUser.getIntroduceSign());
    if (mallUserMapper.updateByPrimaryKeySelective(user) > 0) {
        return true;
    }
    return false;
}
特殊 :获取用户信息
	@GetMapping("/user/info")
    @ApiOperation(value = "获取用户信息", notes = "")
    public Result<NewBeeMallUserVO> getUserDetail(@TokenToMallUser MallUser loginMallUser) {
        //已登录则直接返回
        NewBeeMallUserVO mallUserVO = new NewBeeMallUserVO();
        BeanUtil.copyProperties(loginMallUser, mallUserVO);
        return ResultGenerator.genSuccessResult(mallUserVO);
    }

用到的是一个BeanUtil类的copyProperties方法,(存疑:为什么不用select方法呢?)

3.新蜂商城分类页面接口 New Bee Mall Goods Category API

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VBRNetJW-1638114613557)(C:\Users\chen\AppData\Roaming\Typora\typora-user-images\image-20211128224054900.png)]

/api/v1/categories

文件: NewBeeMallGoodsCategoryAPI.java

作用: 获取分类数据

代码分析:

NewBeeMallGoodsCategoryAPI.java

创建了NewBeeMallCategoryService对象

	@Resource
    private NewBeeMallCategoryService newBeeMallCategoryService;

    @GetMapping("/categories")
    @ApiOperation(value = "获取分类数据", notes = "分类页面使用")
    public Result<List<NewBeeMallIndexCategoryVO>> getCategories() {
        List<NewBeeMallIndexCategoryVO> categories = newBeeMallCategoryService.getCategoriesForIndex();
        if (CollectionUtils.isEmpty(categories)) {
            NewBeeMallException.fail(ServiceResultEnum.DATA_NOT_EXIST.getResult());
        }
        return ResultGenerator.genSuccessResult(categories);
NewBeeMallCategoryServiceImpl 中的 getCategoriesForIndex()方法
1. 获取三个级的数据

首先看一下表里的数据部分属性

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0Qg5w7o9-1638114613558)(C:\Users\chen\AppData\Roaming\Typora\typora-user-images\image-20211128205531699.png)]

category_id :分类id

category_level : 分类等级 有三级

parent_id : 它对应的上一级的分类id

调用selectByLevelAndParentIdsAndNumber方法(GoodsCategoryMapper.xml)

根据三种category_level来获取三个分类等级的列表

//获取一级分类的固定数量的数据
        List<GoodsCategory> firstLevelCategories = goodsCategoryMapper.selectByLevelAndParentIdsAndNumber(Collections.singletonList(0L), NewBeeMallCategoryLevelEnum.LEVEL_ONE.getLevel(), Constants.INDEX_CATEGORY_NUMBER);
        if (!CollectionUtils.isEmpty(firstLevelCategories)) {
            List<Long> firstLevelCategoryIds = firstLevelCategories.stream().map(GoodsCategory::getCategoryId).collect(Collectors.toList());
            //获取二级分类的数据
            List<GoodsCategory> secondLevelCategories = goodsCategoryMapper.selectByLevelAndParentIdsAndNumber(firstLevelCategoryIds, NewBeeMallCategoryLevelEnum.LEVEL_TWO.getLevel(), 0);
            if (!CollectionUtils.isEmpty(secondLevelCategories)) {
                List<Long> secondLevelCategoryIds = secondLevelCategories.stream().map(GoodsCategory::getCategoryId).collect(Collectors.toList());
                //获取三级分类的数据
                List<GoodsCategory> thirdLevelCategories = goodsCategoryMapper.selectByLevelAndParentIdsAndNumber(secondLevelCategoryIds, NewBeeMallCategoryLevelEnum.LEVEL_THREE.getLevel(), 0);
2.处理三个级的数据

我们看看部分处理结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sxx63pPQ-1638114613559)(C:\Users\chen\AppData\Roaming\Typora\typora-user-images\image-20211128210511769.png)]

处理步骤

  1. 根据parentId给第三级分类保存到map中
  2. 每一组parentId对应第二级的categoryId,然后把1中对应的map添加到第二级的"thirdLevelCategoryVOS"属性
  3. 根据parentId给第二级分类保存到map中
  4. 每一组parentId对应第一级的categoryId,然后把3中对应的map添加到第一级的"secondLevelCategoryVOS"属性

代码:

if (!CollectionUtils.isEmpty(thirdLevelCategories)) {
                    //根据 parentId 将 thirdLevelCategories 分组
                    Map<Long, List<GoodsCategory>> thirdLevelCategoryMap = thirdLevelCategories.stream().collect(groupingBy(GoodsCategory::getParentId));
                    List<SecondLevelCategoryVO> secondLevelCategoryVOS = new ArrayList<>();
                    //处理二级分类
                    for (GoodsCategory secondLevelCategory : secondLevelCategories) {
                        SecondLevelCategoryVO secondLevelCategoryVO = new SecondLevelCategoryVO();
                        BeanUtil.copyProperties(secondLevelCategory, secondLevelCategoryVO);
                        //如果该二级分类下有数据则放入 secondLevelCategoryVOS 对象中
                        if (thirdLevelCategoryMap.containsKey(secondLevelCategory.getCategoryId())) {
                            //根据二级分类的id取出thirdLevelCategoryMap分组中的三级分类list
                            List<GoodsCategory> tempGoodsCategories = thirdLevelCategoryMap.get(secondLevelCategory.getCategoryId());
                            secondLevelCategoryVO.setThirdLevelCategoryVOS((BeanUtil.copyList(tempGoodsCategories, ThirdLevelCategoryVO.class)));
                            secondLevelCategoryVOS.add(secondLevelCategoryVO);
                        }
                    }
                    //处理一级分类
                    if (!CollectionUtils.isEmpty(secondLevelCategoryVOS)) {
                        //根据 parentId 将 thirdLevelCategories 分组
                        Map<Long, List<SecondLevelCategoryVO>> secondLevelCategoryVOMap = secondLevelCategoryVOS.stream().collect(groupingBy(SecondLevelCategoryVO::getParentId));
                        for (GoodsCategory firstCategory : firstLevelCategories) {
                            NewBeeMallIndexCategoryVO newBeeMallIndexCategoryVO = new NewBeeMallIndexCategoryVO();
                            BeanUtil.copyProperties(firstCategory, newBeeMallIndexCategoryVO);
                            //如果该一级分类下有数据则放入 newBeeMallIndexCategoryVOS 对象中
                            if (secondLevelCategoryVOMap.containsKey(firstCategory.getCategoryId())) {
                                //根据一级分类的id取出secondLevelCategoryVOMap分组中的二级级分类list
                                List<SecondLevelCategoryVO> tempGoodsCategories = secondLevelCategoryVOMap.get(firstCategory.getCategoryId());
                                newBeeMallIndexCategoryVO.setSecondLevelCategoryVOS(tempGoodsCategories);
                                newBeeMallIndexCategoryVOS.add(newBeeMallIndexCategoryVO);
                            }
                        }
                    }
                }

心得:学会分类思想,在数据库的表时添加要用的属性,category_level ,caparent_id。

4.新蜂商城商品相关接口 New Bee Mall Goods API

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ua3wM5BT-1638114613560)(C:\Users\chen\AppData\Roaming\Typora\typora-user-images\image-20211128224108494.png)]

文件: NewBeeMallGoodsAPI.java

/api/v1/goods/detail/{goodsId}

作用: 商品详情接口

/api/v1/search

作用: 商品搜索接口

代码分析:

1. 搜索接口
1.NewBeeMallGoodsAPI.java

创建NewBeeMallGoodsService对象

	@Resource
    private NewBeeMallGoodsService newBeeMallGoodsService;

作者自己定义了一个PageQueryUtil,分页查询的参数(以后分页可以参考)

public class PageQueryUtil extends LinkedHashMap<String, Object> {
    //当前页码
    private int page;
    //每页条数
    private int limit;

    public PageQueryUtil(Map<String, Object> params) {
        this.putAll(params);

        //分页参数
        this.page = Integer.parseInt(params.get("page").toString());
        this.limit = Integer.parseInt(params.get("limit").toString());
        this.put("start", (page - 1) * limit);
        this.put("page", page);
        this.put("limit", limit);
    }


    public int getPage() {
        return page;
    }

    public void setPage(int page) {
        this.page = page;
    }

    public int getLimit() {
        return limit;
    }

    public void setLimit(int limit) {
        this.limit = limit;
    }

    @Override
    public String toString() {
        return "PageUtil{" +
                "page=" + page +
                ", limit=" + limit +
                '}';
    }
}

  1. 将搜索接口传入的关键字 id order 页码等数据存入到Map中(对象名为params)
  2. 将Map封装到PageQueryUtil对象中
  3. 将PageQueryUtil对象交给newBeeMallGoodsService的searchNewBeeMallGoods方法
@GetMapping("/search")
@ApiOperation(value = "商品搜索接口", notes = "根据关键字和分类id进行搜索")
public Result<PageResult<List<NewBeeMallSearchGoodsVO>>> search(@RequestParam(required = false) @ApiParam(value = "搜索关键字") String keyword,
                                                                @RequestParam(required = false) @ApiParam(value = "分类id") Long goodsCategoryId,
                                                                @RequestParam(required = false) @ApiParam(value = "orderBy") String orderBy,
                                                                @RequestParam(required = false) @ApiParam(value = "页码") Integer pageNumber,
                                                                @TokenToMallUser MallUser loginMallUser) {
    
    logger.info("goods search api,keyword={},goodsCategoryId={},orderBy={},pageNumber={},userId={}", keyword, goodsCategoryId, orderBy, pageNumber, loginMallUser.getUserId());

    Map params = new HashMap(8);
    //两个搜索参数都为空,直接返回异常
    if (goodsCategoryId == null && StringUtils.isEmpty(keyword)) {
        NewBeeMallException.fail("非法的搜索参数");
    }
    if (pageNumber == null || pageNumber < 1) {
        pageNumber = 1;
    }
    params.put("goodsCategoryId", goodsCategoryId);
    params.put("page", pageNumber);
    params.put("limit", Constants.GOODS_SEARCH_PAGE_LIMIT);
    //对keyword做过滤 去掉空格
    if (!StringUtils.isEmpty(keyword)) {
        params.put("keyword", keyword);
    }
    if (!StringUtils.isEmpty(orderBy)) {
        params.put("orderBy", orderBy);
    }
    //搜索上架状态下的商品
    params.put("goodsSellStatus", Constants.SELL_STATUS_UP);
    //封装商品数据
    PageQueryUtil pageUtil = new PageQueryUtil(params);
    return ResultGenerator.genSuccessResult(newBeeMallGoodsService.searchNewBeeMallGoods(pageUtil));
}
2. NewBeeMallGoodsServiceImpl.java
  1. 根据传入的PageUtil找到goodsList商品列表
  2. 记录找到多少个商品
  3. 转为泛型列表
  4. 处理字符过长问题
  5. 拿PageResult保存最后结果(PageResult类是分页工具类)
@Override
    public PageResult searchNewBeeMallGoods(PageQueryUtil pageUtil) {
        List<NewBeeMallGoods> goodsList = goodsMapper.findNewBeeMallGoodsListBySearch(pageUtil);
        int total = goodsMapper.getTotalNewBeeMallGoodsBySearch(pageUtil);
        List<NewBeeMallSearchGoodsVO> newBeeMallSearchGoodsVOS = new ArrayList<>();
        if (!CollectionUtils.isEmpty(goodsList)) {
            newBeeMallSearchGoodsVOS = BeanUtil.copyList(goodsList, NewBeeMallSearchGoodsVO.class);
            for (NewBeeMallSearchGoodsVO newBeeMallSearchGoodsVO : newBeeMallSearchGoodsVOS) {
                String goodsName = newBeeMallSearchGoodsVO.getGoodsName();
                String goodsIntro = newBeeMallSearchGoodsVO.getGoodsIntro();
                // 字符串过长导致文字超出的问题
                if (goodsName.length() > 28) {
                    goodsName = goodsName.substring(0, 28) + "...";
                    newBeeMallSearchGoodsVO.setGoodsName(goodsName);
                }
                if (goodsIntro.length() > 30) {
                    goodsIntro = goodsIntro.substring(0, 30) + "...";
                    newBeeMallSearchGoodsVO.setGoodsIntro(goodsIntro);
                }
            }
        }
        PageResult pageResult = new PageResult(newBeeMallSearchGoodsVOS, total, pageUtil.getLimit(), pageUtil.getPage());
        return pageResult;
    }
2.详情接口

传入商品id,获取对应商品所有信息

1.NewBeeMallGoodsAPI.java
@GetMapping("/goods/detail/{goodsId}")
        @ApiOperation(value = "商品详情接口", notes = "传参为商品id")
        public Result<NewBeeMallGoodsDetailVO> goodsDetail(@ApiParam(value = "商品id") @PathVariable("goodsId") Long goodsId, @TokenToMallUser MallUser loginMallUser) {
            logger.info("goods detail api,goodsId={},userId={}", goodsId, loginMallUser.getUserId());
            if (goodsId < 1) {
                return ResultGenerator.genFailResult("参数异常");
            }
            NewBeeMallGoods goods = newBeeMallGoodsService.getNewBeeMallGoodsById(goodsId);
            if (goods == null) {
                return ResultGenerator.genFailResult("参数异常");
            }
            if (Constants.SELL_STATUS_UP != goods.getGoodsSellStatus()) {
                NewBeeMallException.fail(ServiceResultEnum.GOODS_PUT_DOWN.getResult());
            }
            NewBeeMallGoodsDetailVO goodsDetailVO = new NewBeeMallGoodsDetailVO();
            BeanUtil.copyProperties(goods, goodsDetailVO);
            goodsDetailVO.setGoodsCarouselList(goods.getGoodsCarousel().split(","));
            return ResultGenerator.genSuccessResult(goodsDetailVO);
    }
2. NewBeeMallGoodsServiceImpl.java
@Override
    public NewBeeMallGoods getNewBeeMallGoodsById(Long id) {
        return goodsMapper.selectByPrimaryKey(id);
    }

5.新蜂商城购物车相关接口 New Bee Mall Shopping Cart API

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MzWWTgHf-1638114613562)(C:\Users\chen\AppData\Roaming\Typora\typora-user-images\image-20211128222948995.png)]

1. NewBeeMallShoppingCartAPI.java

每一种方法,代码主体都基本一样,调用NewBeeMallShoppingCartService的方法,判断成功与否

@GetMapping("/shop-cart/page")
    @ApiOperation(value = "购物车列表(每页默认5条)", notes = "传参为页码")
    public Result<PageResult<List<NewBeeMallShoppingCartItemVO>>> cartItemPageList(Integer pageNumber, @TokenToMallUser MallUser loginMallUser) {
        Map params = new HashMap(8);
        if (pageNumber == null || pageNumber < 1) {
            pageNumber = 1;
        }
        params.put("userId", loginMallUser.getUserId());
        params.put("page", pageNumber);
        params.put("limit", Constants.SHOPPING_CART_PAGE_LIMIT);
        //封装分页请求参数
        PageQueryUtil pageUtil = new PageQueryUtil(params);
        return ResultGenerator.genSuccessResult(newBeeMallShoppingCartService.getMyShoppingCartItems(pageUtil));
    }
2. NewBeeMallShoppingCartServiceImpl.java
get方法

三种get方法1,getNewBeeMallCartItemById,getMyShoppingCartItems,getCartItemsForSettle都是简单的select操作,

delete方法

需要考虑userId不同,不能删除

@Override
    public Boolean deleteById(Long shoppingCartItemId, Long userId) {
        NewBeeMallShoppingCartItem newBeeMallShoppingCartItem = newBeeMallShoppingCartItemMapper.selectByPrimaryKey(shoppingCartItemId);
        if (newBeeMallShoppingCartItem == null) {
            return false;
        }
        //userId不同不能删除
        if (!userId.equals(newBeeMallShoppingCartItem.getUserId())) {
            return false;
        }
        return newBeeMallShoppingCartItemMapper.deleteByPrimaryKey(shoppingCartItemId) > 0;
    }
insert方法

添加商品要考虑的情况

  1. 商品已存在
  2. 商品为空
  3. 商品最大数量问题
@Override
public String saveNewBeeMallCartItem(SaveCartItemParam saveCartItemParam, Long userId) {
    NewBeeMallShoppingCartItem temp = newBeeMallShoppingCartItemMapper.selectByUserIdAndGoodsId(userId, saveCartItemParam.getGoodsId());
    if (temp != null) {
        //已存在则修改该记录
        NewBeeMallException.fail(ServiceResultEnum.SHOPPING_CART_ITEM_EXIST_ERROR.getResult());
    }
    NewBeeMallGoods newBeeMallGoods = newBeeMallGoodsMapper.selectByPrimaryKey(saveCartItemParam.getGoodsId());
    //商品为空
    if (newBeeMallGoods == null) {
        return ServiceResultEnum.GOODS_NOT_EXIST.getResult();
    }
    int totalItem = newBeeMallShoppingCartItemMapper.selectCountByUserId(userId);
    //超出单个商品的最大数量
    if (saveCartItemParam.getGoodsCount() < 1) {
        return ServiceResultEnum.SHOPPING_CART_ITEM_NUMBER_ERROR.getResult();
    }
    //超出单个商品的最大数量
    if (saveCartItemParam.getGoodsCount() > Constants.SHOPPING_CART_ITEM_LIMIT_NUMBER) {
        return ServiceResultEnum.SHOPPING_CART_ITEM_LIMIT_NUMBER_ERROR.getResult();
    }
    //超出最大数量
    if (totalItem > Constants.SHOPPING_CART_ITEM_TOTAL_NUMBER) {
        return ServiceResultEnum.SHOPPING_CART_ITEM_TOTAL_NUMBER_ERROR.getResult();
    }
    NewBeeMallShoppingCartItem newBeeMallShoppingCartItem = new NewBeeMallShoppingCartItem();
    BeanUtil.copyProperties(saveCartItemParam, newBeeMallShoppingCartItem);
    newBeeMallShoppingCartItem.setUserId(userId);
    //保存记录
    if (newBeeMallShoppingCartItemMapper.insertSelective(newBeeMallShoppingCartItem) > 0) {
        return ServiceResultEnum.SUCCESS.getResult();
    }
    return ServiceResultEnum.DB_ERROR.getResult();
}
update方法

update考虑情况

  1. 商品最大数量
  2. userId不同
  3. 没有修改的情况,可以不用操作
//超出单个商品的最大数量
if (updateCartItemParam.getGoodsCount() > Constants.SHOPPING_CART_ITEM_LIMIT_NUMBER) {
    return ServiceResultEnum.SHOPPING_CART_ITEM_LIMIT_NUMBER_ERROR.getResult();
}
//当前登录账号的userId与待修改的cartItem中userId不同,返回错误
if (!newBeeMallShoppingCartItemUpdate.getUserId().equals(userId)) {
    return ServiceResultEnum.NO_PERMISSION_ERROR.getResult();
}
//数值相同,则不执行数据操作
if (updateCartItemParam.getGoodsCount().equals(newBeeMallShoppingCartItemUpdate.getGoodsCount())) {
    return ServiceResultEnum.SUCCESS.getResult();
}

6.新蜂商城个人地址相关接口 New Bee Mall User Address API

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PiBj40HO-1638114613564)(C:\Users\chen\AppData\Roaming\Typora\typora-user-images\image-20211128223411451.png)]

调用NewBeeMallUserAddressService的方法,都是CRUD 的比较简单的操作 比一般多一个默认的收货地址,不多做分析

例子:修改地址

  1. 传入数据
  2. 进行CRUD操作
  3. 判断成功或失败
@PutMapping("/address")
    @ApiOperation(value = "修改地址", notes = "")
    public Result<Boolean> updateMallUserAddress(@RequestBody UpdateMallUserAddressParam updateMallUserAddressParam,
                                                 @TokenToMallUser MallUser loginMallUser) {
        MallUserAddress mallUserAddressById = mallUserAddressService.getMallUserAddressById(updateMallUserAddressParam.getAddressId());
        if (!loginMallUser.getUserId().equals(mallUserAddressById.getUserId())) {
            return ResultGenerator.genFailResult(ServiceResultEnum.REQUEST_FORBIDEN_ERROR.getResult());
        }
        MallUserAddress userAddress = new MallUserAddress();
        BeanUtil.copyProperties(updateMallUserAddressParam, userAddress);
        userAddress.setUserId(loginMallUser.getUserId());
        Boolean updateResult = mallUserAddressService.updateMallUserAddress(userAddress);
        //修改成功
        if (updateResult) {
            return ResultGenerator.genSuccessResult();
        }
        //修改失败
        return ResultGenerator.genFailResult("修改失败");
    }

的收货地址,不多做分析

例子:修改地址

  1. 传入数据
  2. 进行CRUD操作
  3. 判断成功或失败
@PutMapping("/address")
    @ApiOperation(value = "修改地址", notes = "")
    public Result<Boolean> updateMallUserAddress(@RequestBody UpdateMallUserAddressParam updateMallUserAddressParam,
                                                 @TokenToMallUser MallUser loginMallUser) {
        MallUserAddress mallUserAddressById = mallUserAddressService.getMallUserAddressById(updateMallUserAddressParam.getAddressId());
        if (!loginMallUser.getUserId().equals(mallUserAddressById.getUserId())) {
            return ResultGenerator.genFailResult(ServiceResultEnum.REQUEST_FORBIDEN_ERROR.getResult());
        }
        MallUserAddress userAddress = new MallUserAddress();
        BeanUtil.copyProperties(updateMallUserAddressParam, userAddress);
        userAddress.setUserId(loginMallUser.getUserId());
        Boolean updateResult = mallUserAddressService.updateMallUserAddress(userAddress);
        //修改成功
        if (updateResult) {
            return ResultGenerator.genSuccessResult();
        }
        //修改失败
        return ResultGenerator.genFailResult("修改失败");
    }
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值