Fading Coder

One Final Commit for the Last Sprint

Home > Notes > Content

Design and Implementation of a Vaccine Appointment Mini-Program Using Spring Boot and Vue.js

Notes Oct 8 16

System Architecture and Technology Stack

The application leverages a decoupled full-stack architecutre, utilizing Spring Boot for server-side orchestration, Vue.js for the client interface, and MyBatis for data persistence. This combination delivers rapid development cycles, high maintainability, and a responsive user experience tailored for healthcare scheduling workflows.

Backend Framework: Spring Boot

Spring Boot streamlines Java development by providing auto-configuration, embedded web servers, and a comprehensive ecosystem of libraries. It eliminates verbose XML configuration, allowing developers to concentrate on business logic. The framework's native support for RESTful services and dependency injection accelerates the construction of scalable applications.

Below is a refactored example demonstrating a basic REST endpoint for retrieving available vaccination slots:


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class ClinicSchedulerApp {

    public static void main(String[] args) {
        SpringApplication.run(ClinicSchedulerApp.class, args);
    }

    @GetMapping("/api/v1/slots/{targetDate}")
    public SlotResponse fetchAvailableSlots(@PathVariable String targetDate) {
        SlotResponse response = new SlotResponse();
        response.setDate(targetDate);
        response.setRemainingCount(15);
        response.setStatus("Slots retrieved successfully");
        return response;
    }

    public static class SlotResponse {
        private String date;
        private int remainingCount;
        private String status;
        // Getters and setters omitted for brevity
    }
}

This configuration initializes the embedded Tomcat server and maps the /api/v1/slots/{targetDate} path to a controller method. The response object is automatically serialized to JSON, demonstrating Spring Boot's seamless REST handling and reduced boilerplate.

Frontend Framework: Vue.js

Vue.js employs a reactive data-binding system and a virtual DOM to efficiently udpate the user interface. Its component-based architecture promotes code reusability and modularity. When underlying data models change, Vue automatically synchronizes the DOM, minimizing manual manipulation and reducing potential rendering errors.

The following snippet illustrates a reactive form component for user registration within the mini-program:



<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Vaccine Booking Interface</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
  <div id="booking-panel">
    <input type="text" v-model="patientName" placeholder="Enter full name">
    <span class="status-text">{{ validationStatus }}</span>
    <button @click="submitForm">Confirm Booking</button>
  </div>

  <script>
    const bookingApp = new Vue({
      el: '#booking-panel',
      data: {
        patientName: '',
        validationStatus: 'Awaiting input...'
      },
      watch: {
        patientName: function(newVal) {
          if (newVal.length > 0) {
            this.validationStatus = 'Name verified';
          } else {
            this.validationStatus = 'Awaiting input...';
          }
        }
      },
      methods: {
        submitForm: function() {
          if (this.patientName.trim() === '') {
            alert('Please provide a valid name');
          } else {
            console.log('Submitting:', this.patientName);
            this.validationStatus = 'Submission in progress...';
          }
        }
      }
    });
  </script>
</body>
</html>

The v-model directive establishes two-way binding between the input field and the patientName property. A watcher monitors changes, updating the status text dynamically. This approach abstracts direct DOM manipulation, ensuring the UI remains consistant with the application state.

Data Persistence: MyBatis

MyBatis serves as the object-relational mapping (ORM) layer, decoupling SQL queries from Java business logic. By utilizing XML mappers or annotations, developers can define complex queries, leverage dynamic SQL constructs, and implement caching strategies. This flexibility simplifies database interactions while maintaining precise control over query execution and performance tuning.

System Validation and Testing Procedures

To guarantee system reliability, a comprehensive black-box testing strategy was implemented. The testing phase focused on verifying functional requirements, handling edge cases, and ensuring data integrity across all modules. Test scenarios were designed to simulate real-world user interactions, with particular attention to input validation and workflow consistency.

Functional Test Scenarios

Critical operations such as authentication and record management were subjected to rigorous validation. The following tables outline representative test cases for the login module and appointment creation feature.

Input Parameters Expected Outcome Observed Outcome Analysis
Admin ID: root | Password: SecurePass123 | CAPTCHA: Valid Redirect to dashboard Dashboard loaded successfully Pass
Admin ID: root | Password: WrongPass | CAPTCHA: Valid Error message displayed "Invalid credentials" alert shown Pass
Admin ID: [Empty] | Password: SecurePass123 | CAPTCHA: Valid Validation warning "Username is required" prompt Pass

Similar validation matrices were applied to CRUD operations. For instance, creating a new appointment record required checking for duplicate scheduling times, verifying mandatory fields, and ensuring proper role-based access. All boundary conditions and error-handling pathways behaved as specified, confirming the robustness of the business logic.

Security and Access Control Mechanism

Authentication is managed through a custom request interceptor that validates session tokens before granting access to protected endpoints. The mechanism filters incoming HTTP requests, checks for valid credentials, and populates the user context for downstream processing.


import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.method.HandlerMethod;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class RequestGuardInterceptor implements HandlerInterceptor {

    public static final String AUTH_HEADER = "X-Auth-Token";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // Configure CORS headers
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", AUTH_HEADER + ", Content-Type, Accept");

        if (request.getMethod().equalsIgnoreCase("OPTIONS")) {
            response.setStatus(HttpServletResponse.SC_OK);
            return false;
        }

        // Skip validation for public endpoints
        if (handler instanceof HandlerMethod) {
            PublicAccess bypass = ((HandlerMethod) handler).getMethodAnnotation(PublicAccess.class);
            if (bypass != null) return true;
        }

        String credential = request.getHeader(AUTH_HEADER);
        if (credential != null && credential.length() >= 16) {
            // Simulate token verification
            request.setAttribute("authenticated_user", credential);
            return true;
        }

        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType("application/json");
        response.getWriter().write("{\"code\": 401, \"detail\": \"Authentication required\"}");
        return false;
    }
}

The interceptor intercepts requests prior to controller execution. It allows preflight OPTIONS requests, bypasses endpoints marked with @PublicAccess, and validates the presence of a valid token in the custom header. Unauthorized requests are terminated with a 401 status, while valid requests proceed with the user identity attached to the request scope.

Database Schema Design

The relational database schema is optimized for storing appointment records, user profiles, and clinic information. Below is the DDL for the primary scheduling table, designed to support efficient querying and transactional integrity.


CREATE TABLE `vaccination_schedule` (
  `record_id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
  `patient_id` BIGINT NOT NULL COMMENT 'User Identifier',
  `clinic_branch` VARCHAR(50) NOT NULL COMMENT 'Facility Location',
  `vaccine_type` VARCHAR(100) NOT NULL COMMENT 'Immunization Category',
  `appointment_dt` DATETIME NOT NULL COMMENT 'Scheduled Timestamp',
  `current_status` ENUM('PENDING','CONFIRMED','CANCELLED','COMPLETED') DEFAULT 'PENDING' COMMENT 'Booking State',
  `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Record Creation',
  `modified_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Last Update',
  PRIMARY KEY (`record_id`),
  KEY `idx_clinic_time` (`clinic_branch`, `appointment_dt`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Appointment Ledger';

The table includes composite indexing on location and scheduled time to accelerate range queries. Status enumeration ensures data consistency, while automatic timestamp fields facilitate audit tracking. Sample insertion operations demonstrate how records are populated and managed within the system.

Related Articles

Deploying a Maven Web Application to Tomcat 9 Using the Tomcat Manager

Tomcat 9 does not provide a dedicated Maven plugin. The Tomcat Manager interface, however, is backward-compatible, so the Tomcat 7 Maven Plugin can be used to deploy to Tomcat 9. This guide shows two...

Skipping Errors in MySQL Asynchronous Replication

When a replica halts because the SQL thread encounters an error, you can resume replication by skipping the problematic event(s). Two common approaches are available. Methods to Skip Errors 1) Skip a...

Spring Boot MyBatis with Two MySQL DataSources Using Druid

Required dependencies application.properties: define two data sources and poooling Java configuration for both data sources MyBatis mappers for each data source Controller endpoints to verify both co...

Leave a Comment

Anonymous

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