Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Developing a University Innovation and Entrepreneurship Platform Competition Management Subsystem with Spring Boot, Vue.js, and Uni-app

Tech Aug 15 15

This article details the development of a competition management subsystem for a university innovation and entrepreneurship platform. The project utilizes a robust technology stack, including Spring Boot for the backend, Vue.js for the frontend web interface, and Uni-app for cross-platform mobile application development.

Technology Stack Overview

Backend Framework: Spring Boot

Spring Boot simplifies the development of production-ready Spring applications. Its key advantages include embedded servers (Tomcat, Jetty, Undertow) eliminating the need for external installations, powerful auto-configuration capabilities that adapt to project dependencies, and a rich ecosystem of starters for rapid integration of functionalities like data access (Spring Data), security (Spring Security), and microservices (Spring Cloud). Spring Boot's flexible configuration management, swift development and deployment cycles, strong community support, built-in monitoring tools, and reliable testing support make it an excellent choice for building high-quality, scalable, and maintainable applications.

Here's a minimal Spring Boot application example:


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

@SpringBootApplication
@RestController
public class InnovationPlatformApplication {

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

    @GetMapping("/status")
    public String getStatus() {
        return "Platform service is operational.";
    }
}

This code snippet defines the entry point for a Spring Boot application. The @SpringBootApplication annotation enables auto-configuration and component scanning, while @RestController marks it as a controller handling web requests. The /status endpoint provides a simple health check.

Frontend Framework: Vue.js

Vue.js is a progressive JavaScript framework renowned for its flexibility and ease of integration. Its core strength lies in its reactivity system and component-based architecture, which efficiently updates the Document Object Model (DOM). Developers can focus on data logic without manual DOM manipulation, leading to more efficient development.

Consider this basic Vue.js example:



<html>
<head>
  <title>Vue.js Competition UI</title>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
  <div id="competitionApp">
    <h3>{{ competitionTitle }}</h3>
    <button @click="updateTitle">Refresh Title</button>
  </div>

  <script>
    var competitionApp = new Vue({
      el: '#competitionApp',
      data: {
        competitionTitle: 'University Entrepreneurship Challenge'
      },
      methods: {
        updateTitle: function() {
          this.competitionTitle = 'Upcoming Competition Details';
        }
      }
    });
  </script>
</body>
</html>

This HTML snippet demonstrates a Vue instance bound to a div. The competitionTitle data property is reactive and displayed using {{ competitionTitle }}. The updateTitle method modifies this property, and Vue automatically updates the UI.

Persistence Layer: MyBatis

MyBatis is a popular persistence framework that streamlines database interactions. It decouples SQL statements from Java code, allowing for flexible management through XML or annotations. Key benefits include simplified data mapping, dynamic SQL generation for complex queries, efficient caching mechanisms (first and second-level), and a plugin architecture for extensibility.

System Testing

Rigorous testing is essential to ensure the quality and reliability of the competition management subsystem. The testing strategy encompasses functional, usability, and performance aspects to identify and rectify defects, ultimately enhancing the user experience.

System Testing Objectives

The primary goal of system testing is to validate that the subsystem meets all specified requirements and functions correctly from an end-user perspective. This involves simulating various usage scenarios to uncover potential issues and insure a seamless user experience. Testing also serves to evaluate the overall system quality, completeness of features, and logical flow.

Functional Testing Example: User Authentication

Functional testing verifies individual components and features. For user authentication, we test login scenarios:

Input Data (Username, Password, Captcha) Expected Result Actual Result Analysis
admin, securePass123, valid Successful login as administrator Login successful, admin dashboard displayed Match
admin, wrongPass, valid Error: Invalid credentials Error message: "Invalid username or password" Match
user, correctPass, invalid Error: Invalid captcha Error message: "Invalid captcha" Match
, correctPass, valid Error: Username is required Error message: "Username cannot be empty" Match

Functional Testing Example: Participant Management

Testing participant management includes adding, editing, and deleting participants:

Add Participant Test Cases:

Input Data (Name, Email, Team) Expected Result Actual Result Analysis
Alice, alice@example.com, Alpha Participant added successfully Alice appears in the participant list Match
Bob, bob@example.com, Beta Participant added succesfully Bob appears in the participant list Match
Alice, alice_updated@example.com, Alpha Add failed: Participant 'Alice' already exists Add failed: "Participant 'Alice' already exists" Match
, charlie@example.com, Gamma Add failed: Name is required Add failed: "Participant name cannot be empty" Match

Edit Participant Test Cases:

Action Expected Result Actual Result Analysis
Select Alice, change email to alice.new@example.com Edit successful, email updated Alice's email is now alice.new@example.com Match
Select Bob, change team to Delta Edit successful, team updated Bob's team is now Delta Match
Select Alice, clear name Edit failed: Name is required Edit failed: "Participant name cannot be empty" Match

Delete Participant Test Cases:

Action Expected Result Actual Result Analysis
Select Alice for deletion, confirm Deletion successful, Alice removed Alice is removed from the participant list Match
Select Bob for deletion, cancel Deletion cancelled, Bob remains Bob remains in the participant list Match

System Testing Conclusion

Through comprehensive black-box testing, simulating user interactions, and executing test cases, the subsystem's functional correctness and logical flow have been validated. System testing is crucial for refining the application, ensuring it meets design specifications, and providing a intuitive user experience tailored to participant needs.

Code Snippets

Authentication and Token Generation (Java/Spring Boot)


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.Calendar;
import java.util.Date;

// Assuming User and Token entities/services exist
// import com.example.platform.entity.UsersEntity;
// import com.example.platform.entity.TokenEntity;
// import com.example.platform.service.UserService;
// import com.example.platform.service.TokenService;

@Component
public class SecurityInterceptor implements HandlerInterceptor {

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

    @Autowired
    private TokenService tokenService; // Assume this service handles token operations
    // @Autowired
    // private UserService userService; // Assume this service handles user operations

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // CORS handling
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, X-Auth-Token");
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));

        if (request.getMethod().equals("OPTIONS")) {
            response.setStatus(HttpStatus.OK.value());
            return false;
        }

        // Check for custom annotation to skip authentication
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        if (handlerMethod.getMethodAnnotation(IgnoreAuth.class) != null) {
            return true;
        }

        // Get token from header
        String authToken = request.getHeader(AUTH_TOKEN_HEADER);

        if (authToken == null || authToken.isEmpty()) {
            return unauthorizedResponse(response, "Authentication token is missing.");
        }

        TokenEntity tokenDetails = tokenService.getTokenDetails(authToken);

        if (tokenDetails == null || tokenDetails.getExpirationTime().before(new Date())) {
            return unauthorizedResponse(response, "Invalid or expired authentication token.");
        }

        // Optionally, fetch user details and set them in the request or session
        // UsersEntity user = userService.getUserById(tokenDetails.getUserId());
        request.setAttribute("userId", tokenDetails.getUserId());
        request.setAttribute("userRole", tokenDetails.getRole());
        request.setAttribute("userTable", tokenDetails.getTableName());
        request.setAttribute("username", tokenDetails.getUsername());

        return true;
    }

    private boolean unauthorizedResponse(HttpServletResponse response, String message) {
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.setContentType("application/json; charset=utf-8");
        try (PrintWriter writer = response.getWriter()) {
            JSONObject jsonResponse = new JSONObject();
            jsonResponse.put("code", 401);
            jsonResponse.put("msg", message);
            writer.print(jsonResponse.toJSONString());
        } catch (Exception e) {
            // Log error
        }
        return false;
    }

    // Other HandlerInterceptor methods (postHandle, afterCompletion) can be implemented if needed
    // ...
}

// Assuming TokenService interface and implementation
interface TokenService {
    TokenEntity getTokenDetails(String token);
    String createOrUpdateToken(Long userId, String username, String tableName, String role);
}

// Assuming TokenEntity class
class TokenEntity {
    private Long userId;
    private String username;
    private String tableName;
    private String role;
    private String tokenValue;
    private Date expirationTime;

    // Constructor, getters, setters...
    public Long getUserId() { return userId; }
    public String getUsername() { return username; }
    public String getTableName() { return tableName; }
    public String getRole() { return role; }
    public Date getExpirationTime() { return expirationTime; }
    // ...
}

// Assuming IgnoreAuth annotation exists
@interface IgnoreAuth {}

// Example of Login Endpoint
// @RestController
// @RequestMapping("/auth")
// public class AuthController {
//     @Autowired
//     private UserService userService;
//     @Autowired
//     private TokenService tokenService;

//     @IgnoreAuth // This endpoint does not require authentication
//     @PostMapping("/login")
//     public R login(String username, String password, String captcha) {
//         // User validation logic...
//         UsersEntity user = userService.findUserByUsername(username);
//         if (user == null || !user.getPassword().equals(password)) {
//             return R.error("Invalid username or password.");
//         }
//         // Generate token
//         String token = tokenService.createOrUpdateToken(user.getId(), user.getUsername(), "users", user.getRole());
//         return R.ok().put("token", token);
//     }
// }

This Java code implements an authentication interceptor. The SecurityInterceptor checks for a custom token in the request headers. If a valid, non-expired token is found, user details are extracted and made available. The @IgnoreAuth annotation allows specific endpoints, like login, to bypass this authentication check. The interceptor also handles CORS requests and returns a 401 Unauthorized response for failed authentication attempts.

Database Schema Example: Product Table

A sample product table schema for managing items within the platform:


-- ----------------------------
-- Table structure for inventory_item
-- ----------------------------
DROP TABLE IF EXISTS `inventory_item`;
CREATE TABLE `inventory_item` (
  `item_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'Unique identifier for the item',
  `item_name` VARCHAR(120) NOT NULL COMMENT 'Name of the product',
  `unit_price` DECIMAL(10, 2) NOT NULL COMMENT 'Price per unit',
  `item_details` VARCHAR(255) DEFAULT NULL COMMENT 'Detailed description of the item',
  `quantity_on_hand` INT(11) NOT NULL COMMENT 'Current stock level',
  `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Timestamp of item creation',
  `modified_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Timestamp of last modification',
  PRIMARY KEY (`item_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Table storing product and inventory information';

-- Sample data insertion
INSERT INTO `inventory_item` (`item_name`, `unit_price`, `item_details`, `quantity_on_hand`)
VALUES ('Pro Gaming Laptop', 1599.99, 'High-performance laptop for gaming enthusiasts', 75);

INSERT INTO `inventory_item` (`item_name`, `unit_price`, `item_details`, `quantity_on_hand`)
VALUES ('4K Monitor', 450.00, '27-inch 4K UHD monitor with vibrant colors', 120);

INSERT INTO `inventory_item` (`item_name`, `unit_price`, `item_details`, `quantity_on_hand`)
VALUES ('Ergonomic Mechanical Keyboard', 120.50, 'RGB backlit mechanical keyboard with tactile switches', 200);

This SQL defines an inventory\_item table with fields for item identification, pricing, description, stock levels, and timestamps for creation and modification. Sample data demonstrates how to populate this table.

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.