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 generate
pms_brand
The table code can be entered firstpms
After the inputpms_brand
;
- Generate code structure overview;
- Another type of code that directly generates an entire module, such as generate
pms
The module code can be entered firstpms
After 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 ID
UmsMenuMapper
Add good interfacegetMenuList
Methods;
/** * <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, in
UmsMenuMapper.xml
Add 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
@NotEmpty
Annotations;
/** * 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
@Validated
Note 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/…