The project is a multi-layered architecture Spring Boot RESTful Web Service based on Spring Boot Version: 2.2.6.RELEASE.
Layers include Spring MVC, Spring Service, Data Access Object(DAO), Data Transfer Object(DTO), Global Exception Handling, Unified Return Result Handling, etc. The CRUD functions are included to show how all of the layers interact with each other.
The application provides mature solutions for common development issues and elegant features to improve the ease of development. The basic architecture shows below.
Searching data with specified conditions is a common feature in web applications.
The simple way is to write the conditions in the backend service. However, such a way is hard-coding. You must rewrite the backend code when there is a need to change the search conditions.
This application provides a flexible way to decouple the search conditions from the backend service. The conditions are specified in the frontend. A query DTO object is to encapsulate the conditions in the backend service. The flexible object-oriented parameter management in Mybatis makes it easy to convert the object attributes into SQL statements.
Here is the simple example about seaching by page. You can trace com.longporo.dev.modules.user.controller.UserController#read
method for full details.
- Conditions in JSON format from the frontend
{
"page": 1,
"limit": 10,
"usernameAllLike": "user",
}
- Controller encapsulates the data with UserQueryDTO
@GetMapping
@ResponseBody
public Result read(@RequestBody UserQueryDTO userQueryDTO) {
return new Result()<>.ok(userService.pageList(userQueryDTO));
}
- Details in UserQueryDTO
@Data
public class UserQueryDTO {
// current page
private Long page = 1L;
// page size
private Long limit = 10L;
// all like
private String usernameAllLike;
}
- Details about converting into SQL statements in the XML file
<if test="user.usernameAllLike != null and user.usernameAllLike != ''">
and user.username like concat(concat('%',#{user.usernameAllLike,jdbcType=VARCHAR}),'%')
</if>
The RESTful API is supported within Spring. Spring provides a series of annotations to use the REST API easily. The UserController includes their use.
@GetMapping, @PostMapping, @PutMapping, @DeleteMapping
The Spring MVC Interceptor helps to intercept requests and handle them, which can be useful for logging and authorization checks. The simple implementation is in the class com.longporo.dev.common.intercepter.MvcInterceptor
.
MyBatis-Plus is a powerful enhanced toolkit of MyBatis for simplifying development. This toolkit provides some efficient, useful, out-of-the-box features for MyBatis, which effectively save the development time.
MyBatis-Plus offers elegant interfaces for writing SQL conditions in the OOP way(Object-Oriented Programming). The class com.longporo.dev.modules.user.service.impl.UserServiceImpl
provides the simple use of Mybatis-Plus.
@Override
public void deleteByEmail(String email) {
if (StringUtils.isEmpty(email)) {
throw new ErpException(ErrorCode.PARAMETER_ERROR);
}
QueryWrapper<UserEntity> queryWrapper = this.getQueryWrapper();
queryWrapper.eq("email", email);
boolean success = this.delete(queryWrapper);
if (!success) {
throw new ErpException(ErrorCode.DELETE_ERROR);
}
}
Exceptions are common in the Controller Layer since the Controller calls the service interfaces directly. Exceptions might be thrown consciously or occur accidentally. Trying and catching exceptions in each method in the Controller might lead to verbose code.
Handling exceptions in the Controller Layer globally helps to avoid repetitive work. It is implemented with Spring AOP (Aspect Oriented Programming). With the use of AOP, we can declare the new code and the new behaviors separately. The class com.longporo.dev.common.aop.WebLogAspect
is to enhance all the controller methods. All the controller methods proceed in the com.longporo.dev.common.aop.WebLogAspect#doAround
method which handles all the exceptions in the controller methods.
The full details of every request and response will be recorded in JSON string format into the specified logging file, which helps trace bugs, errors, and vicious attacks on the application. The full log trace feature is also implemented with the use of Spring AOP, see com.longporo.dev.common.aop.WebLogAspect
for details.
Tips: You can use Kibana (not in this project) to search and analyze the log data.
Using a uniform return result helps standardize the result handling in the frontend. In this case, all the response results are encapsulated in a Result object (com.longporo.dev.common.utils.Result
). The Result object includes three attributes: code (int), msg (String), and data (T). The code represents the result state where 0 stands for success and others for failure. By the agreed code, the frontend can handle the result globally so as in the backend. Here is a sample of the response result.
{
"code": 800,
"msg": "Wrong parameter",
"data": null
}
Internationalization can be easily added to a Spring Boot project. The config class (com.longporo.dev.common.config.LocaleConfig
) specifies the default locale and an interceptor which enables the user to change the locale dynamically. This project simply supports Chinese and English locales. It is used with the Result object, the code, and msg attribute corresponding to the key and value in the properties file.
Profiles are a useful feature in the Spring framework. We can activate different profiles in different environments. This project provides the dev (default) and prod profiles. The profiles are integrated with the Maven configuration file (pom.xml). You can activate the profile you want while building this project with a Maven command. See build.sh for details.
In the development process, we can always find the commonly used attributes or methods among a number of business interfaces or objects, thus it is necessary to abstract them which improves the reusability and cohesion of our code. Many inheritances or realizations are included in this project.
The module structure in this project is well-designed and organized. This project contains two main modules: the business module (longporo-business) and the common module (longporo-common). The common module abstracts all the common things from the business module, which consists of all the common configurations, abstract class, util objects, etc. So you can add any number of business modules you want in such a structure. All the necessary configurations have been done in the common module. You can even extend this project to a Spring Cloud project by simply adding the business module.
Create the “USER” table in your MySql database with the use of the user.sql file (in the root path of the project).
Change to your own MySql database connection information in application-*.yml.
Such a directory is used for saving the logging files. Change to your own logging directory in the pom.xml (in the root path of the project).
Such a directory is used for saving the packaged JAR file. Change to your own packaging directory in the pom.xml (in the root path of the project).
Simply run the build.sh file (in the root path) in the console panel. The project will automatically be packaged into an executable JAR file. The JAR file is saved in the directory that is configured in the root path pom.xml (jar.package.dir).
For example, package the project using the 'prod' environment (the application-prod.yml will be activated).
sh build.sh prod