Notes of Xinfeng mall project

Keywords: Java Database MySQL

New bee mall project notes

1. Start the project and access the api online documentation

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

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-ge9fugsh-163811491017) (C: \ users \ Chen \ appdata \ roaming \ typora \ user images \ image-20211128181427273. PNG)]

1. result class

The author defines a result class for the returned results of api documents as a template for response results

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

    //Business code s, such as success, failure, insufficient permission and so on, can be defined by yourself
    @ApiModelProperty("Return code")
    private int resultCode;
    //Return information. After business processing, the back end returns a prompt message to the front end, which can be defined by itself
    @ApiModelProperty("Return information")
    private String message;
    //Data results, generic, can be lists, single objects, numbers, Booleans, etc
    @ApiModelProperty("Return data")
    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 +
                '}';
    }
}

Each response body includes three parts

  • resultCode
  • message
  • Data (where data is generic)

example:

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-qm9ukkru-163811491020) (C: \ users \ Chen \ appdata \ roaming \ typora \ user images \ image-20211128183745040. PNG)]

2.ResultGenerator

ResultGenerator is a response result generation tool

  • Success: there are three kinds of genSuccessResult(), the parameter is empty, message and data;
  • Failed: genFailResult()
  • Error: 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("No record found!"),

    PARAM_ERROR("Parameter error!"),

    SAME_CATEGORY_EXIST("A category with the same name already exists!"),

    SAME_LOGIN_NAME_EXIST("User name already exists!"),

    LOGIN_NAME_NULL("Please enter login name!"),

    LOGIN_NAME_IS_NOT_PHONE("Please enter the correct mobile phone number!"),

    LOGIN_PASSWORD_NULL("Please input a password!"),

    LOGIN_VERIFY_CODE_NULL("Please enter the verification code!"),

    LOGIN_VERIFY_CODE_ERROR("Verification code error!"),

    SAME_INDEX_CONFIG_EXIST("The same homepage configuration item already exists!"),

    GOODS_CATEGORY_ERROR("Classification data exception!"),

    SAME_GOODS_EXIST("The same product information already exists!"),

    GOODS_NOT_EXIST("Product does not exist!"),

    GOODS_PUT_DOWN("The product is off the shelf!"),

    SHOPPING_CART_ITEM_LIMIT_NUMBER_ERROR("The maximum purchase quantity of a single product is exceeded!"),

    SHOPPING_CART_ITEM_NUMBER_ERROR("Commodity quantity cannot be less than 1!"),

    SHOPPING_CART_ITEM_TOTAL_NUMBER_ERROR("The maximum capacity of the shopping cart is exceeded!"),

    SHOPPING_CART_ITEM_EXIST_ERROR("Already exists! No need to add again!"),

    LOGIN_ERROR("Login failed!"),

    NOT_LOGIN_ERROR("Not logged in!"),

    ADMIN_NOT_LOGIN_ERROR("Administrator is not logged in!"),

    TOKEN_EXPIRE_ERROR("Invalid authentication! Please login again!"),

    ADMIN_TOKEN_EXPIRE_ERROR("Administrator login expired! Please login again!"),

    USER_NULL_ERROR("Invalid user! Please login again!"),

    LOGIN_USER_LOCKED_ERROR("User has been forbidden to log in!"),

    ORDER_NOT_EXIST_ERROR("Order does not exist!"),

    NULL_ADDRESS_ERROR("Address cannot be empty!"),

    ORDER_PRICE_ERROR("Abnormal order price!"),

    ORDER_ITEM_NULL_ERROR("Order item exception!"),

    ORDER_GENERATE_ERROR("Abnormal order generation!"),

    SHOPPING_ITEM_ERROR("Shopping cart data exception!"),

    SHOPPING_ITEM_COUNT_ERROR("Insufficient inventory!"),

    ORDER_STATUS_ERROR("Abnormal order status!"),

    OPERATE_ERROR("Operation failed!"),

    REQUEST_FORBIDEN_ERROR("Prohibit this operation!"),

    NO_PERMISSION_ERROR("No permission!"),

    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. Interface analysis

1. New bee mall homepage interface New Bee Mall Index API

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-a5aso1rj-163811491022) (C: \ users \ Chen \ appdata \ roaming \ typora \ user images \ image-20211128224011589. PNG)]

/api/v1/index-infos

File: NewBeeMallIndexAPI.java

Function: get home page data

Code analysis:

The objects of two service s are obtained through @ Resource (Spring is injected by Name dependency, @ AutoWired is injected by Type dependency)

	@Resource
    private NewBeeMallCarouselService newBeeMallCarouselService;

    @Resource
    private NewBeeMallIndexConfigService newBeeMallIndexConfigService

IndexInfoVo class

The author defines an IndexInfoVO class that inherits Serializable

There are four lists in IndexInfoVO

  1. Rotation chart (list)
  2. Home page hot selling goods (list)
  3. Homepage new product recommendation (list)
  4. Home page recommended products (list)
@Data
public class IndexInfoVO implements Serializable {

    @ApiModelProperty("Rotation chart(list)")
    private List<NewBeeMallIndexCarouselVO> carousels;

    @ApiModelProperty("Home selling goods(list)")
    private List<NewBeeMallIndexConfigGoodsVO> hotGoodses;

    @ApiModelProperty("Homepage new product recommendation(list)")
    private List<NewBeeMallIndexConfigGoodsVO> newGoodses;

    @ApiModelProperty("Home page recommended products(list)")
    private List<NewBeeMallIndexConfigGoodsVO> recommendGoodses;
}

Rotation chart vo

/**
 * Home page configuration product VO
 */
@Data
public class NewBeeMallIndexCarouselVO implements Serializable {

    @ApiModelProperty("Carousel picture address")
    private String carouselUrl;

    @ApiModelProperty("Jump path after clicking the rotation chart")
    private String redirectUrl;
}

Commodity VO

/**
 * Home page configuration product VO
 */
@Data
public class NewBeeMallIndexConfigGoodsVO implements Serializable {

    @ApiModelProperty("commodity id")
    private Long goodsId;
    @ApiModelProperty("Trade name")
    private String goodsName;
    @ApiModelProperty("Product introduction")
    private String goodsIntro;
    @ApiModelProperty("Product picture address")
    private String goodsCoverImg;
    @ApiModelProperty("commodity price")
    private Integer sellingPrice;
    @ApiModelProperty("Commodity label")
    private String tag;
}

Get four list procedures

Call the methods in newBeeMallCarouselService and newBeeMallIndexConfigService to obtain four lists and set the four lists to the IndexInfoVO object.

  1. newBeeMallCarouselService.getCarouselsForIndex

Find the getCarouselsForIndex method of the NewBeeMallCarouselServiceImpl implementation class

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 corresponds to 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>

(possible) the method of BeanUtil.copyList is to convert some specific lists into generic lists?

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

Find the getconfiggoldesforindex method of the newBeeMallIndexConfigServiceImpl implementation class

Method key code

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>

The same conversion to generic processing

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

How to deal with the problem of text exceeding due to too long string

for (NewBeeMallIndexConfigGoodsVO newBeeMallIndexConfigGoodsVO : newBeeMallIndexConfigGoodsVOS) {
                String goodsName = newBeeMallIndexConfigGoodsVO.getGoodsName();
                String goodsIntro = newBeeMallIndexConfigGoodsVO.getGoodsIntro();
                // The string is too long, causing the text to exceed
                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 user operation related interface New Bee Mall Personal API

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-tf0cb6t7-163811491024) (C: \ users \ Chen \ appdata \ roaming \ typora \ user images \ image-20211128224037337. PNG)]

/api/v1/user

File: NewBeeMallPersonalAPI.java

Function: Mall user operation

Code analysis:

a. NewBeeMallPersonalAPI

Whether it is login interface, login interface, user registration and modification of user information subject are written in the same way

  1. Call the methods in NewBeeMallUserService (login, logout, register, updateUserInfo)
  2. Call the info method of Logger to add relevant information
  3. Handling success and failure situations

Example: login interface

	@PostMapping("/user/login")
    @ApiOperation(value = "Login interface", notes = "return 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);

        //Login succeeded
        if (!StringUtils.isEmpty(loginResult) && loginResult.length() == Constants.TOKEN_LENGTH) {
            Result result = ResultGenerator.genSuccessResult();
            result.setData(loginResult);
            return result;
        }
        //Login failed
        return ResultGenerator.genFailResult(loginResult);
    }

b. NewBeeMallUserServiceImpl

(personal idea: token is actually used to record the online situation)

login
  1. The selectbyloginnamenandpasswd method is in TB_ newbee_ mall_ The corresponding user is found in the user table. If there is no user, it will be null
MallUser user = mallUserMapper.selectByLoginNameAndPasswd(loginName, passwordMD5);
  1. Judge whether the returned user is null. Null directly returns the error information. If it is not null, continue to the next step.
if (user != null)
  1. There are three situations after login,

    The first case: TB for new users who have not logged in_ newbee_ mall_ user_ Add a new token data to the token;

    The second case: the user logs in and exits. The token table has no information about him, and he is in TB_ newbee_ mall_ user_ Add a new token data to the token;

    The third case: if the user logs in but does not log out, and there is his information in the token table, it will be directly sent to TB_ newbee_ mall_ user_ The user corresponding to the token modifies the token data;

    (the author is too clever)

    if (user.getLockedFlag() == 1) {
                    return ServiceResultEnum.LOGIN_USER_LOCKED_ERROR.getResult();
                }
                //After logging in, you can modify the token
                String token = getNewToken(System.currentTimeMillis() + "", user.getUserId());
                MallUserToken mallUserToken = newBeeMallUserTokenMapper.selectByPrimaryKey(user.getUserId());
                //current time 
                Date now = new Date();
                //Expiration time
                Date expireTime = new Date(now.getTime() + 2 * 24 * 3600 * 1000);//Expiration time: 48 hours
                if (mallUserToken == null) {
                    mallUserToken = new MallUserToken();
                    mallUserToken.setUserId(user.getUserId());
                    mallUserToken.setToken(token);
                    mallUserToken.setUpdateTime(now);
                    mallUserToken.setExpireTime(expireTime);
                    //Add a token data
                    if (newBeeMallUserTokenMapper.insertSelective(mallUserToken) > 0) {
                        //Return after adding successfully
                        return token;
                    }
                } else {
                    mallUserToken.setToken(token);
                    mallUserToken.setUpdateTime(now);
                    mallUserToken.setExpireTime(expireTime);
                    //to update
                    if (newBeeMallUserTokenMapper.updateByPrimaryKeySelective(mallUserToken) > 0) {
                        //Returned after modification
                        return token;
                    }
                }
    
logout

Directly call the delete method to delete the corresponding TB according to the logged in user id_ newbee_ mall_ user_ Token data of token table

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

insert method

@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

Write separately. First, find the corresponding user with the selett ID, save it to the user, modify the relevant information of the user object, and finally pass the user object to the update method

@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 the password is empty, it indicates that the user does not intend to change the password and saves it with the original password
    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;
}
Special: get user information
	@GetMapping("/user/info")
    @ApiOperation(value = "Get user information", notes = "")
    public Result<NewBeeMallUserVO> getUserDetail(@TokenToMallUser MallUser loginMallUser) {
        //If you have logged in, you can return directly
        NewBeeMallUserVO mallUserVO = new NewBeeMallUserVO();
        BeanUtil.copyProperties(loginMallUser, mallUserVO);
        return ResultGenerator.genSuccessResult(mallUserVO);
    }

The copyProperties method of a BeanUtil class is used, (doubt: why not use the select method?)

3. New Bee Mall Goods Category API

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-2cqswjg3-163811491025) (C: \ users \ Chen \ appdata \ roaming \ typora \ user images \ image-20211128224054900. PNG)]

/api/v1/categories

File: NewBeeMallGoodsCategoryAPI.java

Function: obtain classification data

Code analysis:

NewBeeMallGoodsCategoryAPI.java

NewBeeMallCategoryService object created

	@Resource
    private NewBeeMallCategoryService newBeeMallCategoryService;

    @GetMapping("/categories")
    @ApiOperation(value = "Get classification data", notes = "Classification page usage")
    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);
getCategoriesForIndex() method in NewBeeMallCategoryServiceImpl
1. Obtain three levels of data

First, take a look at the data part attributes in the table

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-odkwzdzl-163811491026) (C: \ users \ Chen \ appdata \ roaming \ typora \ user images \ image-20211128205531699. PNG)]

category_id: classification id

category_level: there are three levels of classification

parent_id: the classification id of the corresponding upper level

Call the selectByLevelAndParentIdsAndNumber method (GoodsCategoryMapper.xml)

According to three categories_ Level to get a list of three classification levels

//Obtain a fixed amount of data for the primary classification
        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());
            //Obtain secondary classification data
            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());
                //Obtain data of three-level classification
                List<GoodsCategory> thirdLevelCategories = goodsCategoryMapper.selectByLevelAndParentIdsAndNumber(secondLevelCategoryIds, NewBeeMallCategoryLevelEnum.LEVEL_THREE.getLevel(), 0);
2. Processing three levels of data

Let's look at some of the results

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-s7jgx0gi-163811491028) (C: \ users \ Chen \ appdata \ roaming \ typora \ user images \ image-20211128210511769. PNG)]

Processing steps

  1. Save the third level classification to the map according to the parentId
  2. Each group of parentids corresponds to the categoryId of the second level, and then add the corresponding map in 1 to the "thirdLevelCategoryVOS" attribute of the second level
  3. Save the second level classification to the map according to the parentId
  4. Each group of parentids corresponds to the categoryId of the first level, and then add the corresponding map in 3 to the "secondLevelCategoryVOS" attribute of the first level

code:

if (!CollectionUtils.isEmpty(thirdLevelCategories)) {
                    //Group thirdLevelCategories according to parentId
                    Map<Long, List<GoodsCategory>> thirdLevelCategoryMap = thirdLevelCategories.stream().collect(groupingBy(GoodsCategory::getParentId));
                    List<SecondLevelCategoryVO> secondLevelCategoryVOS = new ArrayList<>();
                    //Process secondary classification
                    for (GoodsCategory secondLevelCategory : secondLevelCategories) {
                        SecondLevelCategoryVO secondLevelCategoryVO = new SecondLevelCategoryVO();
                        BeanUtil.copyProperties(secondLevelCategory, secondLevelCategoryVO);
                        //If there is data under the secondary classification, it will be put into the secondLevelCategoryVOS object
                        if (thirdLevelCategoryMap.containsKey(secondLevelCategory.getCategoryId())) {
                            //Take out the three-level classification list in the thirdLevelCategoryMap group according to the id of the two-level classification
                            List<GoodsCategory> tempGoodsCategories = thirdLevelCategoryMap.get(secondLevelCategory.getCategoryId());
                            secondLevelCategoryVO.setThirdLevelCategoryVOS((BeanUtil.copyList(tempGoodsCategories, ThirdLevelCategoryVO.class)));
                            secondLevelCategoryVOS.add(secondLevelCategoryVO);
                        }
                    }
                    //Process primary classification
                    if (!CollectionUtils.isEmpty(secondLevelCategoryVOS)) {
                        //Group thirdLevelCategories according to parentId
                        Map<Long, List<SecondLevelCategoryVO>> secondLevelCategoryVOMap = secondLevelCategoryVOS.stream().collect(groupingBy(SecondLevelCategoryVO::getParentId));
                        for (GoodsCategory firstCategory : firstLevelCategories) {
                            NewBeeMallIndexCategoryVO newBeeMallIndexCategoryVO = new NewBeeMallIndexCategoryVO();
                            BeanUtil.copyProperties(firstCategory, newBeeMallIndexCategoryVO);
                            //If there is data under this primary classification, it will be put into the newBeeMallIndexCategoryVOS object
                            if (secondLevelCategoryVOMap.containsKey(firstCategory.getCategoryId())) {
                                //Take out the secondary classification list in the secondLevelCategoryVOMap group according to the id of the primary classification
                                List<SecondLevelCategoryVO> tempGoodsCategories = secondLevelCategoryVOMap.get(firstCategory.getCategoryId());
                                newBeeMallIndexCategoryVO.setSecondLevelCategoryVOS(tempGoodsCategories);
                                newBeeMallIndexCategoryVOS.add(newBeeMallIndexCategoryVO);
                            }
                        }
                    }
                }

Experience: learn the idea of classification and add the attributes to be used in the table of the database_ level ´╝îcaparent_id.

4. New Bee Mall Goods API

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-aedyyla1-163811491029) (C: \ users \ Chen \ appdata \ roaming \ typora \ user images \ image-20211128224108494. PNG)]

File: NewBeeMallGoodsAPI.java

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

Function: Commodity details interface

/api/v1/search

Function: product search interface

Code analysis:

1. Search interface

1.NewBeeMallGoodsAPI.java

Create NewBeeMallGoodsService object

	@Resource
    private NewBeeMallGoodsService newBeeMallGoodsService;

The author defines a PageQueryUtil, which is the parameter of paging query (you can refer to paging in the future)

public class PageQueryUtil extends LinkedHashMap<String, Object> {
    //Current page number
    private int page;
    //Number of entries per page
    private int limit;

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

        //Paging parameters
        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. Store the keyword ID, order page number and other data passed in from the search interface into the Map (the object name is params)
  2. Encapsulate the Map into a PageQueryUtil object
  3. Give the PageQueryUtil object to the searchNewBeeMallGoods method of newBeeMallGoodsService
@GetMapping("/search")
@ApiOperation(value = "Product search interface", notes = "According to keywords and classification id Search")
public Result<PageResult<List<NewBeeMallSearchGoodsVO>>> search(@RequestParam(required = false) @ApiParam(value = "Search keywords") String keyword,
                                                                @RequestParam(required = false) @ApiParam(value = "classification id") Long goodsCategoryId,
                                                                @RequestParam(required = false) @ApiParam(value = "orderBy") String orderBy,
                                                                @RequestParam(required = false) @ApiParam(value = "Page number") 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 both search parameters are empty, an exception is returned directly
    if (goodsCategoryId == null && StringUtils.isEmpty(keyword)) {
        NewBeeMallException.fail("Illegal search parameters");
    }
    if (pageNumber == null || pageNumber < 1) {
        pageNumber = 1;
    }
    params.put("goodsCategoryId", goodsCategoryId);
    params.put("page", pageNumber);
    params.put("limit", Constants.GOODS_SEARCH_PAGE_LIMIT);
    //Filter the keyword to remove spaces
    if (!StringUtils.isEmpty(keyword)) {
        params.put("keyword", keyword);
    }
    if (!StringUtils.isEmpty(orderBy)) {
        params.put("orderBy", orderBy);
    }
    //Search for goods on the shelf
    params.put("goodsSellStatus", Constants.SELL_STATUS_UP);
    //Encapsulate commodity data
    PageQueryUtil pageUtil = new PageQueryUtil(params);
    return ResultGenerator.genSuccessResult(newBeeMallGoodsService.searchNewBeeMallGoods(pageUtil));
}
2. NewBeeMallGoodsServiceImpl.java
  1. Find the goodsList product list according to the passed in PageUtil
  2. Record how many items were found
  3. Convert to generic list
  4. Handle the problem of long characters
  5. Save the final result with PageResult (the PageResult class is a paging tool class)
@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();
                // The string is too long, causing the text to exceed
                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. Detailed interface

Pass in the commodity id and get all the information of the corresponding commodity

1.NewBeeMallGoodsAPI.java
@GetMapping("/goods/detail/{goodsId}")
        @ApiOperation(value = "Product details interface", notes = "Pass reference to commodity id")
        public Result<NewBeeMallGoodsDetailVO> goodsDetail(@ApiParam(value = "commodity id") @PathVariable("goodsId") Long goodsId, @TokenToMallUser MallUser loginMallUser) {
            logger.info("goods detail api,goodsId={},userId={}", goodsId, loginMallUser.getUserId());
            if (goodsId < 1) {
                return ResultGenerator.genFailResult("Parameter exception");
            }
            NewBeeMallGoods goods = newBeeMallGoodsService.getNewBeeMallGoodsById(goodsId);
            if (goods == null) {
                return ResultGenerator.genFailResult("Parameter exception");
            }
            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

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-p0a0pahi-163811491030) (C: \ users \ Chen \ appdata \ roaming \ typora \ user images \ image-20211128222948995. PNG)]

1. NewBeeMallShoppingCartAPI.java

For each method, the code body is basically the same. Call the NewBeeMallShoppingCartService method to judge whether it is successful or not

@GetMapping("/shop-cart/page")
    @ApiOperation(value = "Shopping cart list(Default 5 entries per page)", notes = "Pass reference to page number")
    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);
        //Encapsulate paging request parameters
        PageQueryUtil pageUtil = new PageQueryUtil(params);
        return ResultGenerator.genSuccessResult(newBeeMallShoppingCartService.getMyShoppingCartItems(pageUtil));
    }

2. NewBeeMallShoppingCartServiceImpl.java

get method

The three get methods 1, getNewBeeMallCartItemById, getmyshopingcartitems, and getCartItemsForSettle are simple select operations,

delete method

Different userids should be considered and cannot be deleted

@Override
    public Boolean deleteById(Long shoppingCartItemId, Long userId) {
        NewBeeMallShoppingCartItem newBeeMallShoppingCartItem = newBeeMallShoppingCartItemMapper.selectByPrimaryKey(shoppingCartItemId);
        if (newBeeMallShoppingCartItem == null) {
            return false;
        }
        //userId is different and cannot be deleted
        if (!userId.equals(newBeeMallShoppingCartItem.getUserId())) {
            return false;
        }
        return newBeeMallShoppingCartItemMapper.deleteByPrimaryKey(shoppingCartItemId) > 0;
    }
insert method

Conditions to consider when adding items

  1. Item already exists
  2. Item is empty
  3. Maximum quantity of goods
@Override
public String saveNewBeeMallCartItem(SaveCartItemParam saveCartItemParam, Long userId) {
    NewBeeMallShoppingCartItem temp = newBeeMallShoppingCartItemMapper.selectByUserIdAndGoodsId(userId, saveCartItemParam.getGoodsId());
    if (temp != null) {
        //Modify the record if it already exists
        NewBeeMallException.fail(ServiceResultEnum.SHOPPING_CART_ITEM_EXIST_ERROR.getResult());
    }
    NewBeeMallGoods newBeeMallGoods = newBeeMallGoodsMapper.selectByPrimaryKey(saveCartItemParam.getGoodsId());
    //Item is empty
    if (newBeeMallGoods == null) {
        return ServiceResultEnum.GOODS_NOT_EXIST.getResult();
    }
    int totalItem = newBeeMallShoppingCartItemMapper.selectCountByUserId(userId);
    //The maximum quantity of a single item is exceeded
    if (saveCartItemParam.getGoodsCount() < 1) {
        return ServiceResultEnum.SHOPPING_CART_ITEM_NUMBER_ERROR.getResult();
    }
    //The maximum quantity of a single item is exceeded
    if (saveCartItemParam.getGoodsCount() > Constants.SHOPPING_CART_ITEM_LIMIT_NUMBER) {
        return ServiceResultEnum.SHOPPING_CART_ITEM_LIMIT_NUMBER_ERROR.getResult();
    }
    //Maximum quantity exceeded
    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);
    //Keep records
    if (newBeeMallShoppingCartItemMapper.insertSelective(newBeeMallShoppingCartItem) > 0) {
        return ServiceResultEnum.SUCCESS.getResult();
    }
    return ServiceResultEnum.DB_ERROR.getResult();
}
update method

update considerations

  1. Maximum quantity of goods
  2. userId different
  3. If there is no modification, the operation can be omitted
//The maximum quantity of a single item is exceeded
if (updateCartItemParam.getGoodsCount() > Constants.SHOPPING_CART_ITEM_LIMIT_NUMBER) {
    return ServiceResultEnum.SHOPPING_CART_ITEM_LIMIT_NUMBER_ERROR.getResult();
}
//The userId of the current login account is different from that in the cartItem to be modified. An error is returned
if (!newBeeMallShoppingCartItemUpdate.getUserId().equals(userId)) {
    return ServiceResultEnum.NO_PERMISSION_ERROR.getResult();
}
//If the values are the same, no data operation is performed
if (updateCartItemParam.getGoodsCount().equals(newBeeMallShoppingCartItemUpdate.getGoodsCount())) {
    return ServiceResultEnum.SUCCESS.getResult();
}

6. New Bee Mall User Address API

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-rnm8qn2d-163811491030) (C: \ users \ Chen \ appdata \ roaming \ typora \ user images \ image-20211128223411451. PNG)]

The method of calling NewBeeMallUserAddressService is a relatively simple operation of CRUD. There is one more default receiving address than usual, so there is no more analysis

Example: modify address

  1. incoming data
  2. CRUD operation
  3. Judge success or failure
@PutMapping("/address")
    @ApiOperation(value = "Modify address", 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);
        //Modified successfully
        if (updateResult) {
            return ResultGenerator.genSuccessResult();
        }
        //Modification failed
        return ResultGenerator.genFailResult("Modification failed");
    }

The receiving address of, no more analysis

Example: modify address

  1. incoming data
  2. CRUD operation
  3. Judge success or failure
@PutMapping("/address")
    @ApiOperation(value = "Modify address", 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);
        //Modified successfully
        if (updateResult) {
            return ResultGenerator.genSuccessResult();
        }
        //Modification failed
        return ResultGenerator.genFailResult("Modification failed");
    }

Posted by jdpatrick on Sun, 28 Nov 2021 16:33:55 -0800