Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Logistics Management System Development and Technical Specification Based on Spring Boot + Vue.js

Tech 1

Backend: Spring Boot

Spring Boot embeds application servers including Tomcat, Jetty and Undertow out of the box, eliminating the need for separate server deployment and configuration. Its core auto-configuration mechanism dynamically loads matching configuration items based on introduced dependenceis, removing the complexity of manual bean registration and property configuration for developers. It also natively integrates with Spring ecosystem components such as Spring Data JPA, Spring Security and Spring Cloud, supporting rapid iteration of business logic and seamless extension for distributed architecture demands, which greatly reduces the threshold for building production-grade Java applications.

Frontend: Vue.js

Vue.js leverages virtual DOM technology to minimize real DOM manipulation overhead, improving page rendering efficiency significantly. It adopts responsive data binding, component-based development and diff algorithm optimization, enabling automatic UI synchronization when underlying data changes. Developers only need to focus on business data logic processing without manually manipulating DOM nodes, which effectively reduces code maintenance cost and improves development efficiency for medium and large front-end projects.

Persistence Layer: MyBatis-Plus

MyBatis-Plus is an enhanced tool built on top of native MyBatis, designed to simplify data access layer development. Its compatible with all mainstream relational databases including MySQL, Oracle, SQL Server and PostgreSQL, and provides a rich set of encapsulated CRUD APIs, annotation-based conditional constructors, and automatic paging plugins, eliminating the need to write repetitive basic SQL statements. Its built-in code generator can automatically generate entity classes, Mapper interfaces, service layer code and XML mapping files according to table structure, cutting down basic development workload by more than 60%. It also supports advanced features such as dynamic conditional query, optimistic locking, SQL performance monitoring and logical deletion, meeting diversified data operation demands in complex business scenarios.


System Testing

The core objective of system testing is to identify potential logic defects and function mismatches from multiple dimensions, modify discovered issues in time, and verify that all functions meet pre-defined requirement specifications before official launch.

Testing Objectives

System testing is a mandatory phase in the software development lifecycle, acting as the final checkpoint to ensure system stability and usability. It focuses on simulating real user operation scenarios to find hidden problems that may occur during actual use, so as to avoid abnormal usage experience for end users. The testing process also needs to verify the completeness of functional modules, rationality of business logic, and compliance with requirement documents, to ensure the final delivered system fully matches user expectations.

Functional Testing

Black-box testing method is adopted for functional verification, covering operation path clicking, boundary value input verification, required field verification and other scenarios. Test cases are compiled in advance for each functional module, and test results are recorded one by one according to execution of test cases.

Login Function Test Case

When a user attempts to log in, the system verifies the entered account, password and verification code against the data stored in the database, and checks whether the selected role matches the account permission. The specific test cases are as follows:

Input Parameters Expected Output Actual Output Result Verification
Username: admin, Password: Admin@123, Captcha: correct Successful login to system backend Normal login and jump to home page Consistent with expectation
Username: admin, Password: 123456, Captcha: correct Password mismatch prompt Popup "Incorrect username or password" Consistent with expectation
Username: admin, Password: Admin@123, Captcha: wrong Captcha error prompt Popup "Verification code input error" Consistent with expectation
Username: empty, Password: Admin@123, Captcha: correct Required field prompt Popup "Username cannot be empty" Consistent with expectation
Username: admin, Password: empty, Captcha: correct Required field prompt Popup "Password cannot be empty" Consistent with expectation
Username: user01, Password: User@123, Selected role: Administrator Permission mismatch prompt Popup "Account does not have administrator permission" Consistent with expectation

User Management Function Test Case

User management module includes functions of adding, modifying, deleting and querying user information. The specific test cases are as follows:

Operation Scenario Expected Output Actual Output Result Verification
Fill in all required user information and submit User added successfully, displayed in user list New user appears in user list, information is complete Consistent with expectation
Modify user phone number and submit Modification takes effect immediately User information in list shows updated phone number Consistent with expectation
Select a user and click delete, confirm in popup User is removed from system Deleted user no longer appears in user list Consistent with expectation
Submit add request without filling username Non-null verification prompt Popup "Username is a required field" Consistent with expectation
Submit add request with existing username Duplicate username prompt Popup "Username already exists, please change" Consistent with expectation

Test Conclusion

All functional modules of the system have passed the black-box test verification, and all test case execution results are consistent with expected outputs. The system has complete functions, smooth business logic, and meets the design requirements in both function and performance indicators, which can be officially deployed for use.


Core Code Implementation

User Authentication Interface

@IgnoreAccessCheck
@PostMapping("/auth/login")
public ResponseResult authenticate(String account, String passwd, String verifyCode, HttpServletRequest req) {
    AccountEntity accountInfo = accountService.getOne(new LambdaQueryWrapper<AccountEntity>().eq(AccountEntity::getAccountName, account));
    if (accountInfo == null || !passwd.equals(accountInfo.getPassword())) {
        return ResponseResult.fail("Invalid account or password");
    }
    String accessToken = tokenService.createAccessToken(accountInfo.getId(), account, accountInfo.getRole());
    return ResponseResult.success().put("access_token", accessToken);
}

Token Generation Logic

@Override
public String createAccessToken(Long accountId, String accountName, String role) {
    AccessTokenEntity existingToken = this.getOne(new LambdaQueryWrapper<AccessTokenEntity>()
            .eq(AccessTokenEntity::getAccountId, accountId)
            .eq(AccessTokenEntity::getRole, role));
    String newToken = CommonUtil.generateRandomStr(32);
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(new Date());
    calendar.add(Calendar.HOUR, 2); // Set token valid for 2 hours
    if (existingToken != null) {
        existingToken.setToken(newToken);
        existingToken.setExpireTime(calendar.getTime());
        this.updateById(existingToken);
    } else {
        AccessTokenEntity newTokenEntity = new AccessTokenEntity();
        newTokenEntity.setAccountId(accountId);
        newTokenEntity.setAccountName(accountName);
        newTokenEntity.setRole(role);
        newTokenEntity.setToken(newToken);
        newTokenEntity.setExpireTime(calendar.getTime());
        this.save(newTokenEntity);
    }
    return newToken;
}

Request Authorization Interceptor

@Component
public class AuthInterceptor implements HandlerInterceptor {
    public static final String ACCESS_TOKEN_HEADER = "Access-Token";
    @Autowired
    private AccessTokenService accessTokenService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // Configure cross-domain support
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, Access-Token, Origin, Content-Type, Accept, Authorization");
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        // Directly return success for preflight OPTIONS request
        if (RequestMethod.OPTIONS.name().equals(request.getMethod())) {
            response.setStatus(HttpStatus.OK.value());
            return false;
        }
        // Skip check for non-controller methods
        if (!(handler instanceof HandlerMethod)) {
            return true;
        }
        // Skip check for methods marked with ignore access annotation
        IgnoreAccessCheck ignoreAnnotation = ((HandlerMethod) handler).getMethodAnnotation(IgnoreAccessCheck.class);
        if (ignoreAnnotation != null) {
            return true;
        }
        // Extract token from request header
        String token = request.getHeader(ACCESS_TOKEN_HEADER);
        AccessTokenEntity validToken = null;
        if (StringUtils.hasText(token)) {
            validToken = accessTokenService.getValidToken(token);
        }
        if (validToken != null) {
            request.getSession().setAttribute("loginAccountId", validToken.getAccountId());
            request.getSession().setAttribute("loginRole", validToken.getRole());
            request.getSession().setAttribute("loginAccountName", validToken.getAccountName());
            return true;
        }
        // Return not logged in prompt if token is invalid
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=utf-8");
        try (PrintWriter writer = response.getWriter()) {
            writer.print(JSONObject.toJSONString(ResponseResult.fail(401, "Please log in first")));
        }
        return false;
    }
}

Database Table Reference

Access Token Table

DROP TABLE IF EXISTS `access_token`;
CREATE TABLE `access_token` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Primary key ID',
  `account_id` bigint(20) NOT NULL COMMENT 'Associated account ID',
  `account_name` varchar(100) NOT NULL COMMENT 'Account name',
  `role` varchar(100) DEFAULT NULL COMMENT 'Account permission role',
  `token` varchar(200) NOT NULL COMMENT 'Access token string',
  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Token creation time',
  `expire_time` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Token expiration time',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=35 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='Access token storage table';

INSERT INTO `access_token` VALUES 
(1, 1, 'admin', 'ADMIN', 'kf93jd72nxl0wqpr8tyu1vb6nm23zx78', '2024-05-10 09:23:12', '2024-05-10 11:23:12'),
(2, 5, 'logistics01', 'LOGISTICS_STAFF', 'pl02mnbv65cxz87lkjhgf34dsaqw90er', '2024-05-10 10:01:45', '2024-05-10 12:01:45'),
(3, 12, 'warehouse03', 'WAREHOUSE_MANAGER', 'mn87bvcx45dfgh09jklp12aqwzx34edc', '2024-05-10 10:30:22', '2024-05-10 12:30:22'),
(4, 28, 'driver07', 'DELIVERY_STAFF', 'bv45cxz87lkj09mnpoi12uytr67ewq09', '2024-05-10 11:05:37', '2024-05-10 13:05:37');

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.