SpringBoot actual combat e-commerce project mall (18K + STAR) Address: github.com/macrozheng/…

Abstract

Mall – Tiny is the skeleton of the project extracted from the Mall project, retains the whole technology stack of the Mall project, and simplifies the business logic, reserving only the permission and core table of commodities, which is convenient for development and use, and can customize the business logic freely.

Technology selection

technology version instructions
SpringBoot 2.1.3 Container +MVC framework
SpringSecurity 5.1.4 ensuring Authentication and authorization framework
MyBatis 3.4.6 ORM framework
MyBatisGenerator 1.3.3 Data layer code generation
PageHelper 5.1.8 MyBatis physical paging plugin
Swagger-UI 2.7.0 Document production tool
Elasticsearch 6.2.2 Search engine
RabbitMq 3.7.14 The message queue
Redis 3.2 Distributed cache
MongoDb 3.2 No database
Docker 18.09.0 Application container engine
Druid 1.1.10 Database connection pool
OSS 2.5.0 Object storage
JWT 0.9.0 JWT login support
Lombok 1.18.6 Simplify object encapsulation tools

Database table structure

  • There are only 12 core tables related to commodities and permissions, and the business logic is simple.
  • Database source file address: github.com/macrozheng/…

Using the process

Environment set up

This project relies on the MySql, Elasticsearch, Redis, MongoDb, and RabbitMq services to start. For details about how to install these services, see Deploying mall on Windows. The mall_Tiny. SQL script needs to be imported into the database.

Develop specifications

Project package structure

The SRC ├ ─ ─ commonStore common code and utility classes| ├ ─ ─ APIGeneric result set wrapper class| └ ─ ─ utils- tools├ ─ ─ component-- Various components defined in the project├ ─ ─config Java configuration in SpringBoot├ ─ ─ the controllerController layer code├ ─ ─ the dao-- Data access layer code, store our custom query DAO interface, named xxxDao├ ─ ─ dtoData transfer object encapsulation├ ─ ─ MBG-- MyBatisGenerator related code| ├ ─ ─ mapper-- Mapper interface automatically generated by MyBatisGenerator (do not change)| └ ─ ─ model-- MyBatisGenerator automatically generates entity classes and Example objects (do not change them)├ ─ ─ no-- NoSQL database operations related classes| ├ ─ ─ elasticsearchElasticsearch data manipulation classes| | ├ ─ ─ the documentElasticsearch stores the document object wrapper| | └ ─ ─ the repositoryElasticsearch data manipulation class| └ ─ ─ mongo-- Mongodb data manipulation classes| ├ ─ ─ the documentMongodb stores document object encapsulation| └ ─ ─ the repository-- mongodb data manipulation classes└ ─ ─ the service-- Business layer interface code└ ─ ─ impl-- Business layer interface implementation class code
Copy the code

Resource File Description

Res ├ ─ ─ com. Macro. Mall. Tiny. MBG. Mapper-- Mapper.xml file automatically generated by MBG (do not change it)├ ─ ─ mapper-- User-defined mapper. XML file, corresponding to the query interface in the DAO package, named xxxdao.xml├ ─ ─ application. Yml-- SpringBoot configuration file├ ─ ─ the generator. The properties-- Data source information used to configure MyBatisGenerator to generate code├ ─ ─ generatorConfig. XMLMyBatisGenerator generates code rule configuration└ ─ ─ logback - spring. XML-- Integrate ELK configuration for log collection
Copy the code

Interface definition rules

  • Create table records: POST /{controller route name}/create
  • Modify table record: POST /{controller route name}/update/{id}
  • Delete the specified table record: POST /{controller route name}/delete/{id}
  • Paging query table records: GET /{controller route name}/list
  • GET /{controller route name}/{id}

Swagger UI Api: Swagger UI Api: Swagger UI Api

Project running

Com. After installation related rely on direct start macro. Mall. Tiny. MallTinyApplication the main function of a class.

Business code development process

The brand management function is used as an example to illustrate the business code development process.

Create a table

When creating a pMS_brand table, make sure to comment the table fields, so that when generating code, there will be comments in the entity class, and there will be comments in the document generated by Swagger-UI, so that you don’t have to write comments again.

CREATE TABLE `pms_brand` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) DEFAULT NULL.`first_letter` varchar(8) DEFAULT NULL COMMENT 'Initial'.`sort` int(11) DEFAULT NULL.`factory_status` int(1) DEFAULT NULL COMMENT 'Brand manufacturer: 0-> No; 1 - > '.`show_status` int(1) DEFAULT NULL.`product_count` int(11) DEFAULT NULL COMMENT 'Product Quantity'.`product_comment_count` int(11) DEFAULT NULL COMMENT 'Number of product Reviews'.`logo` varchar(255) DEFAULT NULL COMMENT 'brand logo'.`big_pic` varchar(255) DEFAULT NULL COMMENT 'Zone map'.`brand_story` text COMMENT 'Brand Story',
  PRIMARY KEY (`id`))ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8 COMMENT='Brand list';
Copy the code

Use MyBatisGenerator to generate the code

Run com. Macro. Mall. Tiny. MBG. The main method to generate code Generator class, after the generation will have the following several files.

PmsBrandMapper interface

Contains common interfaces for single table queries

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);
}
Copy the code
PmsBrand entity class

Swagger-ui annotations have been added based on the entity class generated by the database table.

package com.macro.mall.tiny.mbg.model;

import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable;

public class PmsBrand implements Serializable {
    private Long id;

    private String name;

    @ApiModelProperty(value = "Initials")
    private String firstLetter;

    private Integer sort;

    @ApiModelProperty(value = "Brand manufacturer: 0-> No; 1 - >")
    private Integer factoryStatus;

    private Integer showStatus;

    @ApiModelProperty(value = "Product Quantity")
    private Integer productCount;

    @ApiModelProperty(value = "Number of product reviews")
    private Integer productCommentCount;

    @ApiModelProperty(value = "Brand logo")
    private String logo;

    @ApiModelProperty(value = "Zone map")
    private String bigPic;

    @ApiModelProperty(value = "Brand Story")
    private String brandStory;

    private static final long serialVersionUID = 1L;
    // omit getter, setter, toString methods
}
Copy the code
PmsBrandExample Query constructor

Used to construct query conditions in complex queries.

PmsBrandMapper. XML file

Corresponding to the mapper. XML implementation in the PmsBrandMapper interface, the specific query implementation of the method in the PmsBrandMapper interface are here.

Write data access layer code

Single table query

Single-table queries are recommended using query constructors rather than handwritten SQL statements such as fuzzy queries by brand name as shown below.

@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);
}
Copy the code
Paging query

Paging queries are implemented using the PageHelper paging plug-in and simply add the following code before the query statement.

 PageHelper.startPage(pageNum, pageSize);
Copy the code
Multi-table query

Multi-table query needs to write mapper interface and mapper. XML implementation, and MyBatis usage is consistent, here to query goods containing attributes as an example.

  • First, you need to define a custom Dao interface. To distinguish it from the MAPper interface generated by MBG, the customized Mapper interfaces in Mall-Tiny are named xxxDao.
public interface EsProductDao {
    List<EsProduct> getAllEsProductList(@Param("id") Long id);
}
Copy the code
  • Then write an XML query implementation of the interface named xxxdao.xml in mall-tiny.
<select id="getAllEsProductList" resultMap="esProductListMap">
    select
        p.id id,
        p.product_sn productSn,
        p.brand_id brandId,
        p.brand_name brandName,
        p.product_category_id productCategoryId,
        p.product_category_name productCategoryName,
        p.pic pic,
        p.name name,
        p.sub_title subTitle,
        p.price price,
        p.sale sale,
        p.new_status newStatus,
        p.recommand_status recommandStatus,
        p.stock stock,
        p.promotion_type promotionType,
        p.keywords keywords,
        p.sort sort,
        pav.id attr_id,
        pav.value attr_value,
        pav.product_attribute_id attr_product_attribute_id,
        pa.type attr_type,
        pa.name attr_name
    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
    <if test="id! =null">
        and p.id=#{id}
    </if>
</select>
Copy the code

Write business layer code

  • First in com. Macro. Mall. Tiny. The service package add PmsBrandService interface;
  • In com again. Macro. Mall. Tiny. ServiceImpl add its implementation class.

Write controller layer code

In com. Macro. Mall. Tiny. The controller add PmsBrandController class package.

Project deployment

Mall-tiny has integrated the Docker plug-in, which can be packaged into a Docker image and deployed using Docker. For details, see: Using Maven plug-in to build a Docker image for SpringBoot application

Other instructions

SpringSecurity related

Because SpringSecurity is used to implement authentication and authorization, some interfaces can be accessed only after login. The process for accessing login interfaces is as follows.

  • Access to Swagger – UI interface document: http://localhost:8080/swagger-ui.html
  • Invoke login interface to obtain token:
  • Click on the upper-right Authorize button to enter the real token:

About Log Collection

The project has logged all interface access using AOP facets and integrated ELK for log collection. For details about how to set up an ELK log collection environment, see: The SpringBoot application integrates ELK to collect logs.

Oss file upload related

The OSS file needs to be modified to your own configuration when it is uploaded and used. The configuration needs to be modified as follows:

# OSS configuration information
aliyun:
  oss:
    endpoint: oss-cn-shenzhen.aliyuncs.com Access domain name for oss external services
    accessKeyId: test Use the user id in access authentication
    accessKeySecret: test # key used by the user to encrypt the signature string and used by OSS to verify the signature string
    bucketName: macro-oss # Storage space for OSS
    policy:
      expire: 300 Signature validity period (S)
    maxSize: 10 # Upload file size (M)
    callback: http://localhost:8080/aliyun/oss/callback The callback address of the file after uploading successfully (must be accessible from the public network)
    dir:
      prefix: mall/images/ # upload folder path prefix
Copy the code

On cross-domain problems

Global filters have been configured to allow cross-access, and SpringSecurity also allows cross-domain pre-checked OPTIONS requests.

/** * Global cross-domain configuration * Created by macro on 2019/7/27
@Configuration
public class GlobalCorsConfig {

    /** * filters that allow cross-domain calls */
    @Bean
    public CorsFilter corsFilter(a) {
        CorsConfiguration config = new CorsConfiguration();
        // Allow all domain names to make cross-domain calls
        config.addAllowedOrigin("*");
        // Allow cookies to be sent across
        config.setAllowCredentials(true);
        // Release all original headers
        config.addAllowedHeader("*");
        // Allow all request methods to be invoked across domains
        config.addAllowedMethod("*");
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/ * *", config);
        return newCorsFilter(source); }}Copy the code
// added to the configure method of SecurityConfig
.antMatchers(HttpMethod.OPTIONS)// Cross-domain requests start with an options request
.permitAll()
Copy the code

Project source code address

Github.com/macrozheng/…

The public,

Mall project full set of learning tutorials serialized, attention to the public number the first time access.