Architecture and Implementation of a Campus Dormitory Management System via Spring Boot and WeChat Mini-Program

Core Technology Stack and Architecture

The system is constructed using a decoupled full-stack architecture, combining enterprise-level backend processing with cross-platform frontend deployment.

Backend: Spring Boot

The server layer leverages Spring Boot to streamline dependency injection and deployment. By utilizing embedded servlet containers, the application eliminates the need for external server configuration. The auto-configuration mechanism automatically binds starter dependencies to runtime beans, significantly reducing boilerplate setup. Integration with Spring Data and security modules further accelerates development by providing standardized interfaces for transaction management and request routing.

Frontend: Vue.js and uni-app

The user interface relies on Vue.js, which employs a reactive data-binding engine and a virtual DOM diffing algorithm. When application state mutates, the framework efficiently calculates the minimal set of DOM updates required, optimizing render performance. This component-driven approach is extended through uni-app, which compiles Vue codebases into native WeChat Mini-Program packages, enabling seamless cross-platform execution without rewriting business logic.

ORM Layer: MyBatis-Plus

Database interactions are managed via MyBatis-Plus, an extension of the classic MyBatis framework. It introduces a fluent API for constructing dynamic SQL queries at runtime, eliminating repetitive mapper XML definitions. Built-in capabilities include automatic primary key generation, logical deletion, pagination interceptors, and an integrated code generation module that scaffolds entity classes, data access objects, and service layers from existing database schemas.

Token-Based Authentication Flow

Access control is implemented using a stateless session token mechanism. Upon successful credential verification, the backend issues a unique string that clients must include in subsequent HTTP headers. A custom request interceptor validates the token payload and expiration timestamp before allowing controller execution.

@RestController
@RequestMapping("/api/security")
public class AuthController {

    @Autowired
    private CredentialValidator credentialValidator;
    
    @Autowired
    private SessionRegistry sessionRegistry;

    @IgnorePermission
    @PostMapping("/verify")
    public ApiResponse authenticate(@RequestParam String account, 
                                    @RequestParam String pass,
                                    @RequestParam String verifyCode) {
        
        if (!credentialValidator.validateCredentials(account, pass)) {
            return ApiResponse.failure("Invalid credentials provided");
        }
        
        AuthContext ctx = credentialValidator.resolveContext(account);
        String accessKey = sessionRegistry.issue(ctx.getId(), ctx.getRole(), ctx.getSourceTable());
        return ApiResponse.success().data("accessKey", accessKey);
    }
}

public interface SessionRegistry {
    String issue(Long userId, String role, String sourceTable);
    SessionRecord validate(String accessKey);
    void invalidate(String accessKey);
}

public class TokenSessionRegistry implements SessionRegistry {
    
    private final TokenMapper tokenMapper;
    private final RandomStringGenerator generator = new RandomStringGenerator();

    @Override
    public String issue(Long userId, String role, String sourceTable) {
        String freshKey = generator.alphanumeric(32);
        LocalDateTime expiry = LocalDateTime.now().plusHours(1);
        
        TokenRecord existing = tokenMapper.findByUserAndRole(userId, role);
        if (existing != null) {
            existing.setAccessKey(freshKey);
            existing.setValidUntil(expiry);
            tokenMapper.updateRecord(existing);
        } else {
            tokenMapper.insert(new TokenRecord(userId, "default_user", sourceTable, role, freshKey, LocalDateTime.now(), expiry));
        }
        return freshKey;
    }

    @Override
    public SessionRecord validate(String accessKey) {
        TokenRecord record = tokenMapper.findByAccessKey(accessKey);
        if (record != null && record.getValidUntil().isAfter(LocalDateTime.now())) {
            return record.toSessionRecord();
        }
        return null;
    }
}

The request validation logic is encapsulated in a Spring MVC interceptor that intercepts all non-annotated endpoints, extracting the authorization header and resolving the active session context.

@Component
public class AccessValidationInterceptor implements HandlerInterceptor {
    
    private static final String HEADER_AUTH = "Authorization-Token";

    @Autowired
    private SessionRegistry registry;

    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
        res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        res.setHeader("Access-Control-Max-Age", "7200");
        res.setHeader("Access-Control-Allow-Headers", "Content-Type, " + HEADER_AUTH + ", X-Requested-With");
        res.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));

        if (req.getMethod().equals("OPTIONS")) {
            res.setStatus(HttpServletResponse.SC_OK);
            return false;
        }

        boolean isExempt = extractExemption(handler);
        if (isExempt) return true;

        String providedToken = req.getHeader(HEADER_AUTH);
        SessionRecord activeSession = StringUtils.hasText(providedToken) ? registry.validate(providedToken) : null;

        if (activeSession != null) {
            req.setAttribute("context_user_id", activeSession.getUserId());
            req.setAttribute("context_role", activeSession.getRole());
            req.setAttribute("context_source", activeSession.getTableRef());
            return true;
        }

        res.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        res.setContentType("application/json;charset=UTF-8");
        try (PrintWriter writer = res.getWriter()) {
            writer.write("{\"status\":401,\"message\":\"Authentication required\"}");
        }
        return false;
    }

    private boolean extractExemption(Object handler) {
        if (handler instanceof HandlerMethod methodHandler) {
            return methodHandler.hasMethodAnnotation(IgnorePermission.class);
        }
        return true;
    }
}

Data base Schema for Session Tracking

The persistent storage layer utilizes MySQL to maintain token lifecycles and association mappings. The schema below tracks issued credentials, expiration windows, and role assignments.

CREATE TABLE IF NOT EXISTS session_registry (
    record_id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'Unique record identifier',
    user_ref BIGINT NOT NULL COMMENT 'Foreign key to user table',
    account_label VARCHAR(128) NOT NULL COMMENT 'Human-readable username',
    domain_table VARCHAR(128) DEFAULT NULL COMMENT 'Associated entity domain',
    privilege_level VARCHAR(64) DEFAULT NULL COMMENT 'Access role designation',
    access_hash VARCHAR(255) NOT NULL COMMENT 'Cryptographically generated session token',
    issued_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 'Token creation timestamp',
    valid_until DATETIME DEFAULT '9999-12-31 23:59:59' COMMENT 'Expiration deadline'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='Active session registry';

INSERT INTO session_registry (user_ref, account_label, domain_table, privilege_level, access_hash, issued_at, valid_until) VALUES 
(101, 'stu_alpha', 'residents', 'tenant', '9f8a7b6c5d4e3f2a1b0c9d8e7f6a5b4c', '2024-01-10 09:00:00', '2024-01-10 10:00:00'),
(102, 'warden_beta', 'staff', 'supervisor', '1a2b3c4d5e6f7g8h9i0j1k2l3m4n5o6p', '2024-01-11 14:20:00', '2024-01-11 15:20:00'),
(100, 'sys_master', 'administrators', 'root', 'q1w2e3r4t5y6u7i8o9p0a1s2d3f4g5h6', '2024-01-12 08:30:00', '2024-01-12 09:30:00');

System Validation and Testing Methodology

Quality assurance follows a black-box testing paradigm, evaluating functional correctness against specification requirements without examining internal code paths. Test cases are constructed to verify boundary conditions, mandatory field enforcement, and role-based access restrictions.

Authentication Verification

The login module undergoes systematic validation to ensure credential matching, format enforcement, and role separation. The following table outlines executed scenarios.

Test Input Expected Outcome Observed Behavior Status
Account: admin_root | Pass: securePass1 | Code: Valid Successful authentication Session established and token returned Pass
Account: admin_root | Pass: wrongValue | Code: Valid Credential mismatch alert Error 400: Invalid credentials Pass
Account: admin_root | Pass: securePass1 | Code: Expired Verification failure Error 400: Captcha invalid Pass
Account: (empty) | Pass: securePass1 | Code: Valid Missing field notification Validation error on account field Pass
Account: student_01 | Role: supervisor Role conflict rejection Access denied due to privilege mismatch Pass

User Account Management Validation

Administrative endpoints for user lifecycle operations are validated against CRUD operations, duplicate prevention, and data integrity rules.

Operation Input Expected Outcome Observed Behavior Status
Submit valid profile data Record created, list updated New entry visible in management view Pass
Modify existing profile fields Update persisted, view refreshed Changes reflected accurately in UI Pass
Trigger deletion confirmation Soft-delete flag set, record hidden Entity removed from active queries Pass
Submit with empty account name Required field validation failure Form submission blocked, tooltip shown Pass
Attempt duplicate account creation Uniqueness constraint violation API returns 409 Conflict status Pass

The validation cycles confirm that all core modules adhere to the initial architectural specifications. By simulating real-world usage patterns and edge-case inputs, the system demonstrates stable performance, accurate state transitions, and appropriate error handling across the authentication and administrative domains.

Tags: spring-boot Vue.js mybatis-plus wechat-miniprogram UniApp

Posted on Thu, 01 Oct 2026 16:30:11 +0000 by bogdan