SpringBoot e-commerce project mall (40K + STAR) address: github.com/macrozheng/…

Abstract

A project skeleton, Mall-Tiny, was opened source and inherited the entire technology stack of the Mall project. There is always a feeling that Mall – Tiny integrates too much middleware and is too complex. This time it has been simplified and upgraded, so that it has become a full rights management function of rapid development scaffolding, I hope to help you!

Introduction to the

Mall-tiny is a fast development scaffold based on SpringBoot+MyBatis-Plus, with complete permission management functions, can be connected to the Vue front-end, out of the box.

Project presentations

The mall- Tiny project can seamlessly connect with the mall- Admin – Web front – end project and change permissions in seconds management system. Front-end project address: github.com/macrozheng/…

Technology selection

technology version instructions
SpringBoot 2.3.0 Container +MVC framework
SpringSecurity 5.3.2 Authentication and authorization framework
MyBatis 3.5.4 ORM framework
MyBatis-Plus 3.3.2 rainfall distribution on 10-12 MyBatis enhancement tool
MyBatis-Plus Generator 3.3.2 rainfall distribution on 10-12 Data layer code generator
Swagger-UI 2.9.2 Document production tool
Redis 5.0 Distributed cache
Docker 18.09.0 Application container engine
Druid 1.1.10 Database connection pool
JWT 0.9.0 JWT login support
Lombok 1.18.12 Simplify object encapsulation tools

Database table structure

  • The complexity is simplified, and only 9 tables related to authority management function are reserved, which is convenient for free customization.

  • Database source file address: github.com/macrozheng/…

Using the process

Environment set up

To simplify dependent services, you only need to install the most commonly used MySql and Redis services. For details about service installation, see Mall Deployment in Windows. You need to import the mall_tiny. SQL script into the database.

Develop specifications

Project package structure

The SRC ├ ─ ─ common-- Used to store generic code| ├ ─ ─ APIGeneric result set wrapper class| ├ ─ ─config Generic configuration classes| ├ ─ ─ domainGeneric encapsulating object| ├ ─ ─ the exceptionGlobal exception handling related classes| └ ─ ─ the serviceGeneric business class├ ─ ─config Java configuration in SpringBoot├ ─ ─ domainShare encapsulated objects├ ─ ─ the generator-- MyBatis-Plus code generator├ ─ ─ modules-- The base package that houses the business code| └ ─ ─ ums-- Permission management module business code| ├ ─ ─ the controller-- Interface related to this module| ├ ─ ─ dto-- This module transmits data to encapsulate objects| ├ ─ ─ mapperThis module is associated with the Mapper interface| ├ ─ ─ model-- The entity class associated with this module| └ ─ ─ the service-- Business processing classes related to this module└ ─ ─ the security-- SpringSecurity authentication and authorization code├ ─ ─ the annotation-- Related notes├ ─ ─ the aspect-- Relevant section├ ─ ─ componentAuthentication and authorization-related components├ ─ ─config -- Related configuration└ ─ ─ util-- Related tool classes
Copy the code

Resource File Description

Resources ├ ─ ─ mapper-- Location of mapper. XML in MyBatis├ ─ ─ application. Yml-- SpringBoot common configuration file├ ─ ─ application - dev. Yml-- SpringBoot development environment configuration file├ ─ ─ application - prod. Yml-- SpringBoot production environment configuration file└ ─ ─ the generator. The properties-- MyBatis-Plus code generator configuration
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}

  • Specific parameters, and returns the definition can run code view Swagger, UI Api documentation: http://localhost:8080/swagger-ui.html

Project running

Run the main function that launches the MallTinyApplication class.

Business code development process

Create a business table

Create all the tables in the PMS module. Note that you must comment the table fields so that the entity class and interface documentation automatically generates field descriptions.

Using code generators

Run the main method of MyBatisPlusGenerator class to generate the code, which can directly generate the code of Controller, Service, mapper, Model, mapper.xml without manual creation.

  • Code generators support two modes, one that generates single-table code, such as just generatepms_brandThe table code can be entered firstpmsAfter the inputpms_brand;

  • Generate code structure overview;

  • Another type of code that directly generates an entire module, such as generatepmsThe module code can be entered firstpmsAfter the inputpms_*.

Write business code

Single table query

Thanks to the powerful enhancements provided by MyBatis-Plus, single-table queries rarely use hand-written SQL, instead using the methods provided in ServiceImpl and BaseMapper.

For example, the methods in our menu management business implementation class UmsMenuServiceImpl use these methods directly.

/** * Created by macro on 2020/2/2. */
@Service
public class UmsMenuServiceImpl extends ServiceImpl<UmsMenuMapper.UmsMenu>implements UmsMenuService {

    @Override
    public boolean create(UmsMenu umsMenu) {
        umsMenu.setCreateTime(new Date());
        updateLevel(umsMenu);
        return save(umsMenu);
    }

    @Override
    public boolean update(Long id, UmsMenu umsMenu) {
        umsMenu.setId(id);
        updateLevel(umsMenu);
        return updateById(umsMenu);
    }

    @Override
    public Page<UmsMenu> list(Long parentId, Integer pageSize, Integer pageNum) {
        Page<UmsMenu> page = new Page<>(pageNum,pageSize);
        QueryWrapper<UmsMenu> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(UmsMenu::getParentId,parentId)
                .orderByDesc(UmsMenu::getSort);
        return page(page,wrapper);
    }

    @Override
    public List<UmsMenuNode> treeList(a) {
        List<UmsMenu> menuList = list();
        List<UmsMenuNode> result = menuList.stream()
                .filter(menu -> menu.getParentId().equals(0L))
                .map(menu -> covertMenuNode(menu, menuList)).collect(Collectors.toList());
        return result;
    }

    @Override
    public boolean updateHidden(Long id, Integer hidden) {
        UmsMenu umsMenu = new UmsMenu();
        umsMenu.setId(id);
        umsMenu.setHidden(hidden);
        returnupdateById(umsMenu); }}Copy the code
Paging query

For paging queries native to MyBatis-Plus, you don’t need to integrate other plug-ins, just construct the Page object and call the Page method in ServiceImpl.

/** * Created by macro on 2020/2/2. */
@Service
public class UmsMenuServiceImpl extends ServiceImpl<UmsMenuMapper.UmsMenu>implements UmsMenuService {
    @Override
    public Page<UmsMenu> list(Long parentId, Integer pageSize, Integer pageNum) {
        Page<UmsMenu> page = new Page<>(pageNum,pageSize);
        QueryWrapper<UmsMenu> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(UmsMenu::getParentId,parentId)
                .orderByDesc(UmsMenu::getSort);
        returnpage(page,wrapper); }}Copy the code
Multi-table query

For multi-table query, we need to hand-write the SQL implementation in mapper. XML, because we have generated mapper. XML file before, so we directly define the method in mapper interface, and then write the SQL implementation in mapper. XML.

  • Let’s say we need to write a method to get the menu assigned by the user IDUmsMenuMapperAdd good interfacegetMenuListMethods;
/** * <p> * </p> **@author macro
 * @sinceThe 2020-08-21 * /
public interface UmsMenuMapper extends BaseMapper<UmsMenu> {

    /** * Get menu */ according to background user ID
    List<UmsMenu> getMenuList(@Param("adminId") Long adminId);

}
Copy the code
  • Then, inUmsMenuMapper.xmlAdd the corresponding SQL implementation of this method.

      
<! DOCTYPEmapper PUBLIC "- / / mybatis.org//DTD Mapper / 3.0 / EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.macro.mall.tiny.modules.ums.mapper.UmsMenuMapper">

    <select id="getMenuList" resultType="com.macro.mall.tiny.modules.ums.model.UmsMenu">
        SELECT
            m.id id,
            m.parent_id parentId,
            m.create_time createTime,
            m.title title,
            m.level level,
            m.sort sort,
            m.name name,
            m.icon icon,
            m.hidden hidden
        FROM
            ums_admin_role_relation arr
                LEFT JOIN ums_role r ON arr.role_id = r.id
                LEFT JOIN ums_role_menu_relation rmr ON r.id = rmr.role_id
                LEFT JOIN ums_menu m ON rmr.menu_id = m.id
        WHERE
            arr.admin_id = #{adminId}
          AND m.id IS NOT NULL
        GROUP BY
            m.id
    </select>
    
</mapper>
Copy the code

Project deployment

Mall-tiny has integrated the Docker plugin and can be packaged as a Docker image for deployment. For details, see: “Building a Docker Image for SpringBoot Application using Maven Plugin”.

Other instructions

SpringSecurity related

Because SpringSecurity is used to implement authentication and authorization, some interfaces need tokens to access. The authentication and authorization interface flow is as follows.

  • Access to Swagger – UI interface document: http://localhost:8080/swagger-ui.html

  • Invoke login interface to obtain token;

  • Click the Authorize button in the upper right corner to enter the token and then access the related interface.

Request parameter verification

Default integrates the Jakarta Bean Validation parameters calibration framework, simply by adding javax.mail parameter object properties. The Validation. The constraints in annotations annotations Validation function can be realized, login here to parameter calibration, for example.

  • First add it in the login request parameter@NotEmptyAnnotations;
/** * Created by macro on 2018/4/26. */
@Data
@EqualsAndHashCode(callSuper = false)
public class UmsAdminLoginParam {
    @NotEmpty
    @APIModelProperty (value = "username ", Required = true)
    private String username;
    @NotEmpty
    @APIModelProperty (value = "password ", Required = true)
    private String password;
}
Copy the code
  • Then add it in the login interface@ValidatedNote Enable the parameter verification function.
/** * Created by macro on 2018/4/26. */
@Controller
@API (tags = "UmsAdminController", description = "background user management ")
@RequestMapping("/admin")
public class UmsAdminController {

    @apiOperation (value = "return token after login ")
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult login(@Validated @RequestBody UmsAdminLoginParam umsAdminLoginParam) {
        String token = adminService.login(umsAdminLoginParam.getUsername(), umsAdminLoginParam.getPassword());
        if (token == null) {
            return CommonResult.validateFailed("Wrong username or password");
        }
        Map<String, String> tokenMap = new HashMap<>();
        tokenMap.put("token", token);
        tokenMap.put("tokenHead", tokenHead);
        returnCommonResult.success(tokenMap); }}Copy the code

The project address

Open source is not easy, feel the project is helpful to point a Star to support it!

Github.com/macrozheng/…