Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Implementation of a Scenic Area Accommodation Management System Using Spring Boot and Vue.js

Tech 1

System Architecture Overview

Traditional manual data management methods often suffer from high error rates, inefficient retrieval processes, and difficulty in updating information. To address these inefficiencies, an automated reservation platform streamlines workflows, ensuring systematic data handling. The architecture leverages Java for backend robustness and Vue.js for responsive frontend interactions, facilitating rapid data entry, maintenance, and statistical analysis.

Development Environment Specifications

The system is built on the following technology stack:

  • Language: Java 8 (JDK 1.8)
  • Framework: Spring Boot
  • Web Server: Tomcat 7
  • Database: MySQL 5.7
  • Build Tool: Maven 3.3.9
  • IDE: Eclipse, IntelliJ IDEA, or MyEclipse
  • Admin Access: localhost:8080/[project_name]/admin/dist/index.html
  • Public Interface: localhost:8080/[project_name]/front/dist/index.html

Default credentials for initial configuration are admin / admin.

Backend Implementation Highlights

Asset Management Controller

This module handles file operations such as image uploads and downloads, storing resources in the classpath static directory. Security checks ensure files are not empty before transfer.

package com.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.util.UUID;

@RestController
@RequestMapping("/assets")
public class MediaManagerController {

    @Autowired
    private ConfigService configService;

    /**
     * Store a new file asset
     */
    @RequestMapping("/upload")
    public ResponseEntity<?> uploadFile(@RequestParam("file") MultipartFile file, String type) throws Exception {
        if (file.isEmpty()) {
            return ResponseEntity.badRequest().body("File cannot be empty");
        }

        String originalFilename = file.getOriginalFilename();
        String extension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
        
        // Define storage path safely
        File basePath = new File(ResourceUtils.getURL("classpath:static").getPath());
        if (!basePath.exists()) basePath = new File("");
        
        File storeDir = new File(basePath.getAbsolutePath(), "/uploads/");
        if (!storeDir.exists()) storeDir.mkdirs();

        // Generate unique filename
        String uniqueName = UUID.randomUUID().toString() + "." + extension;
        File destFile = new File(storeDir, uniqueName);
        file.transferTo(destFile);

        // Optional: Persist metadata in config table
        if ("1".equals(type)) {
            // Update specific system config flag
            updateSystemConfig(uniqueName, "avatarUrl");
        }

        return ResponseEntity.ok().body(Map.of("filename", uniqueName));
    }

    /**
     * Retrieve a stored file
     */
    @RequestMapping("/download/{fileName}")
    public ResponseEntity<byte[]> downloadAsset(@PathVariable String fileName) {
        try {
            File basePath = new File(ResourceUtils.getURL("classpath:static").getPath());
            if (!basePath.exists()) basePath = new File("");
            
            File file = new File(basePath.getAbsolutePath(), "/uploads/" + fileName);
            
            if (file.exists()) {
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
                headers.setContentDispositionFormData("attachment", fileName);
                byte[] data = FileUtils.readFileToByteArray(file);
                return new ResponseEntity<>(data, headers, HttpStatus.OK);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
    }

    private void updateSystemConfig(String value, String name) {
        // Logic to save config into DB
    }
}

Community Discussion Module

This controller manages forum-like discusions, supporting list views, details, creation, and pagination. Role-based access controls restrict certain operations to administrators.

package com.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;
import java.util.Arrays;
import java.util.Date;
import java.util.UUID;
import org.springframework.web.bind.annotation.RequestBody;

// Assuming custom entity and service wrappers exist
import com.entity.DiscussionItem;
import com.service.DiscussionService;
import com.utils.PageUtils;
import com.utils.R;

@RestController
@RequestMapping("/discussions")
public class DiscussionController {

    @Autowired
    private DiscussionService discussionService;

    /**
     * Paginated list retrieval with filtering
     */
    @RequestMapping("/list")
    public R getDiscussions(@RequestParam Map<String, Object> params, HttpServletRequest request) {
        DiscussionItem queryModel = new DiscussionItem();
        
        // Filter out user-specific visibility based on session role
        if (!"admin".equals(request.getSession().getAttribute("role"))) {
            Long currentUserId = (Long) request.getSession().getAttribute("userId");
            queryModel.setUserid(currentUserId);
        }

        PageUtils pageData = discussionService.queryPage(params, buildQueryWrapper(queryModel));
        return R.ok().put("data", pageData);
    }

    /**
     * Detailed view by ID
     */
    @RequestMapping("/detail/{id}")
    public R getDetail(@PathVariable("id") Long id) {
        DiscussionItem item = discussionService.selectById(id);
        populateChildren(item);
        return R.ok().put("data", item);
    }

    /**
     * Create new thread
     */
    @RequestMapping("/create")
    @Transactional
    public R createDiscussion(@RequestBody DiscussionItem newItem, HttpServletRequest request) {
        newItem.setId(new Date().getTime());
        newItem.setUId((Long) request.getSession().getAttribute("userId"));
        discussionService.insert(newItem);
        return R.ok();
    }

    /**
     * Modify existing thread
     */
    @RequestMapping("/modify")
    @Transactional
    public R modifyDiscussion(@RequestBody DiscussionItem updatedItem, HttpServletRequest request) {
        discussionService.updateById(updatedItem);
        return R.ok();
    }

    /**
     * Delete multiple entries
     */
    @RequestMapping("/remove")
    public R removeItems(@RequestBody Long[] ids) {
        discussionService.deleteBatchIds(Arrays.asList(ids));
        return R.ok();
    }

    /**
     * Recursive method to fetch nested replies
     */
    private void populateChildren(DiscussionItem parent) {
        List<DiscussionItem> children = discussionService.selectByParentId(parent.getId());
        parent.setReplies(children);
        if (children != null && !children.isEmpty()) {
            children.forEach(this::populateChildren);
        }
    }

    private Object buildQueryWrapper(DiscussionItem condition) {
        // Simplified wrapper construction logic
        return condition;
    }
}

Data Storage & Security

MySQL 5.7 serves as the relational database engine. Its transactional support ensures data consistency during concurrent booking requests. The schema design minimizes redundancy while allowing efficient scaling.

Security measures include input validation to prevent injection attacks and session-based authentication for sensitive endpoints. Configuration tables manage runtime settings, such as default file paths, without requiring code recompilation.

Quality Assurance Strategy

Comprehensive testing covers both functional requirements and structural integrity. Unit tests verify individual service methods, while integration tests validate API endpoints under simulated load. Regression testing is performed after updates to ensure no existing features are broken. Focus areas include data persistence correctness, permission enforcement, and response latency metrics.

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.