Backend Development 13 min read

How to Quickly Bootstrap an E‑Commerce Backend with Mall‑Tiny: A Complete Guide

This article introduces mall‑tiny, a lightweight SpringBoot backend skeleton that retains a full technology stack while simplifying business logic to core product and permission tables, and provides step‑by‑step setup, code structure, API conventions, and deployment instructions.

macrozheng
macrozheng
macrozheng
How to Quickly Bootstrap an E‑Commerce Backend with Mall‑Tiny: A Complete Guide

Project Overview

mall‑tiny is a lightweight skeleton extracted from the mall project, retaining the full technology stack while simplifying business logic to only permission and core product tables, making it easy to customize.

Technology Stack

The project uses SpringBoot 2.1.3 (container + MVC), SpringSecurity 5.1.4 (authentication/authorization), MyBatis 3.4.6, MyBatisGenerator, PageHelper, Swagger‑UI, Elasticsearch 6.2.2, RabbitMQ 3.7.14, Redis 3.2, MongoDB 3.2, Docker 18.09.0, Druid, OSS, JWT, Lombok, and Druid connection pool.

Database Schema

Only 12 core tables related to products and permissions are kept.

SQL file available at the GitHub repository.

Setup and Usage

Environment

The application requires MySQL, Elasticsearch, Redis, MongoDB, RabbitMQ, etc. Follow the linked deployment guide for Windows and import

mall_tiny.sql

.

Project Structure

<code>src
├── common   // common utilities
│   ├── api
│   └── utils
├── component
├── config
├── controller
├── dao
├── dto
├── mbg
│   ├── mapper
│   └── model
├── nosql
│   ├── elasticsearch
│   └── mongodb
└── service
    └── impl
</code>

Resource Files

<code>res
├── com.macro.mall.tiny.mbg.mapper   // generated mapper XML
├── mapper                         // custom mapper XML
├── application.yml                // SpringBoot config
├── generator.properties
├── generatorConfig.xml
└── logback-spring.xml             // ELK logging config
</code>

API Conventions

POST /{controller}/create – create record

POST /{controller}/update/{id} – update record

POST /{controller}/delete/{id} – delete record

GET /{controller}/list – paginated query

GET /{controller}/{id} – get record detail

Detailed parameters and responses can be viewed via Swagger‑UI.

Running the Project

After installing dependencies, run the

main

method of

com.macro.mall.tiny.MallTinyApplication

.

Business Code Development Example (Brand Management)

Create Table

<code>CREATE TABLE `pms_brand` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) DEFAULT NULL,
  `first_letter` varchar(8) DEFAULT NULL COMMENT '首字母',
  `sort` int(11) DEFAULT NULL,
  `factory_status` int(1) DEFAULT NULL COMMENT '是否为品牌制造商:0->不是;1->是',
  `show_status` int(1) DEFAULT NULL,
  `product_count` int(11) DEFAULT NULL COMMENT '产品数量',
  `product_comment_count` int(11) DEFAULT NULL COMMENT '产品评论数量',
  `logo` varchar(255) DEFAULT NULL COMMENT '品牌logo',
  `big_pic` varchar(255) DEFAULT NULL COMMENT '专区大图',
  `brand_story` text COMMENT '品牌故事',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8 COMMENT='品牌表';
</code>

MyBatisGenerator

Run the

Generator

main method to generate mapper, model, and example classes.

Mapper Interface

<code>public interface PmsBrandMapper {
    long countByExample(PmsBrandExample example);
    int deleteByExample(PmsBrandExample example);
    int deleteByPrimaryKey(Long id);
    int insert(PmsBrand record);
    int insertSelective(PmsBrand record);
    List<PmsBrand> selectByExampleWithBLOBs(PmsBrandExample example);
    List<PmsBrand> selectByExample(PmsBrandExample example);
    PmsBrand selectByPrimaryKey(Long id);
    int updateByExampleSelective(@Param("record") PmsBrand record, @Param("example") PmsBrandExample example);
    int updateByExampleWithBLOBs(@Param("record") PmsBrand record, @Param("example") PmsBrandExample example);
    int updateByExample(@Param("record") PmsBrand record, @Param("example") PmsBrandExample example);
    int updateByPrimaryKeySelective(PmsBrand record);
    int updateByPrimaryKeyWithBLOBs(PmsBrand record);
    int updateByPrimaryKey(PmsBrand record);
}
</code>

Entity Class

<code>public class PmsBrand implements Serializable {
    private Long id;
    private String name;
    @ApiModelProperty(value = "首字母")
    private String firstLetter;
    private Integer sort;
    @ApiModelProperty(value = "是否为品牌制造商:0->不是;1->是")
    private Integer factoryStatus;
    private Integer showStatus;
    @ApiModelProperty(value = "产品数量")
    private Integer productCount;
    @ApiModelProperty(value = "产品评论数量")
    private Integer productCommentCount;
    @ApiModelProperty(value = "品牌logo")
    private String logo;
    @ApiModelProperty(value = "专区大图")
    private String bigPic;
    @ApiModelProperty(value = "品牌故事")
    private String brandStory;
    private static final long serialVersionUID = 1L;
    // getters, setters, toString omitted
}
</code>

Single‑Table Query Example

<code>@Override
public List<PmsBrand> list(int pageNum, int pageSize, String name) {
    PageHelper.startPage(pageNum, pageSize);
    PmsBrandExample example = new PmsBrandExample();
    if (StrUtil.isNotEmpty(name)) {
        example.createCriteria().andNameLike("%" + name + "%");
    }
    return brandMapper.selectByExample(example);
}
</code>

Pagination

<code>PageHelper.startPage(pageNum, pageSize);
</code>

Multi‑Table Query

Define a custom DAO (e.g.,

EsProductDao

) and its XML mapper to join product and attribute tables.

<code>public interface EsProductDao {
    List<EsProduct> getAllEsProductList(@Param("id") Long id);
}
</code>
<code>&lt;select id="getAllEsProductList" resultMap="esProductListMap"&gt;
    select ... from pms_product p
    left join pms_product_attribute_value pav on p.id = pav.product_id
    left join pms_product_attribute pa on pav.product_attribute_id = pa.id
    where delete_status = 0 and publish_status = 1
    &lt;if test="id!=null"&gt; and p.id=#{id} &lt;/if&gt;
&lt;/select&gt;
</code>

Deployment

The project includes a Docker plugin; you can build a Docker image and run it. See the linked Maven‑Docker guide.

Additional Notes

SpringSecurity

Some APIs require authentication. Use Swagger‑UI to obtain a JWT token and authorize requests.

Logging

All API accesses are logged via AOP and sent to ELK for centralized collection.

OSS Configuration

<code># OSS configuration
aliyun:
  oss:
    endpoint: oss-cn-shenzhen.aliyuncs.com
    accessKeyId: test
    accessKeySecret: test
    bucketName: macro-oss
    policy:
      expire: 300
    maxSize: 10
    callback: http://localhost:8080/aliyun/oss/callback
    dir:
      prefix: mall/images/
</code>

CORS

<code>@Configuration
public class GlobalCorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOrigin("*");
        config.setAllowCredentials(true);
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}
</code>

Source Code

https://github.com/macrozheng/mall-tiny

backende-commerceJavaDockerMyBatisSpringBoot
macrozheng
Written by

macrozheng

Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.