Building a Fire Safety Education Site with SSM, JSP, and Vue
Application Startup and Configuration
The entry point leverages Spring Boot’s auto-configuraton and MyBatis mapper scanning. The main class extends SpringBootServletInitializer to support traditional WAR deployment:
package com.platform;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
@SpringBootApplication
@MapperScan(basePackages = {"com.platform.mapper"})
public class SafetyEducationApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(SafetyEducationApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SafetyEducationApplication.class);
}
}
Account Management Endpoints
The controller exposes REST endpoints for registration, login, profile retrieval, password reset, and CRUD operations. User creation uses a timestamp combined with a random factor to generate identifiers.
package com.platform.controller;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.platform.entity.AccountEntity;
import com.platform.service.AccountService;
import com.platform.service.TokenService;
import com.platform.utils.*;
@RestController
@RequestMapping("/accounts")
public class AccountController {
@Autowired
private AccountService accountService;
@Autowired
private TokenService tokenService;
@PostMapping("/signin")
@IgnoreAuth
public ApiResult signin(@RequestParam String loginName,
@RequestParam String secret,
HttpServletRequest request) {
AccountEntity entity = accountService.lookupByLoginName(loginName);
if (entity == null || !entity.getAccessKey().equals(secret)) {
return ApiResult.fail("Invalid login name or access key");
}
String token = tokenService.issueToken(entity.getId(), loginName, "member", "member");
return ApiResult.success().append("token", token);
}
@PostMapping("/signup")
@IgnoreAuth
public ApiResult signup(@RequestBody AccountEntity account) {
if (accountService.existsByLoginName(account.getLoginAlias())) {
return ApiResult.fail("Login name already registered");
}
long generatedId = new Date().getTime() + (long) (Math.random() * 10000);
account.setId(generatedId);
accountService.createAccount(account);
return ApiResult.success();
}
@PostMapping("/signout")
public ApiResult signout(HttpServletRequest request) {
request.getSession().invalidate();
return ApiResult.success("Signed out");
}
@GetMapping("/current")
public ApiResult currentMember(HttpServletRequest request) {
Long memberId = (Long) request.getSession().getAttribute("userId");
AccountEntity entity = accountService.fetchById(memberId);
return ApiResult.success().append("data", entity);
}
@PostMapping(value = "/reset-key")
@IgnoreAuth
public ApiResult resetKey(@RequestParam String loginName) {
AccountEntity entity = accountService.lookupByLoginName(loginName);
if (entity == null) {
return ApiResult.fail("Login name does not exist");
}
entity.setAccessKey("safety123");
accountService.modifyAccount(entity);
return ApiResult.success("Access key reset to safety123");
}
@GetMapping("/list")
@IgnoreAuth
public ApiResult listPublic(@RequestParam Map<String, Object> filters,
AccountEntity query) {
PageData page = accountService.fetchPage(filters, QueryHelper.buildPublicFilter(query, filters));
return ApiResult.success().append("data", page);
}
@GetMapping("/admin-list")
public ApiResult adminList(@RequestParam Map<String, Object> filters,
AccountEntity query) {
PageData page = accountService.fetchPage(filters, QueryHelper.buildAdminFilter(query, filters));
return ApiResult.success().append("data", page);
}
@GetMapping("/{entryId}")
@IgnoreAuth
public ApiResult detail(@PathVariable Long entryId) {
AccountEntity entity = accountService.fetchById(entryId);
return ApiResult.success().append("data", entity);
}
@PostMapping
public ApiResult save(@RequestBody AccountEntity account) {
if (accountService.countByLoginName(account.getLoginAlias()) > 0) {
return ApiResult.fail("Login name already in use");
}
account.setId(new Date().getTime());
accountService.createAccount(account);
return ApiResult.success();
}
@Transactional
@PutMapping
public ApiResult modify(@RequestBody AccountEntity account) {
if (accountService.countByLoginNameExceptSelf(account.getId(), account.getLoginAlias()) > 0) {
return ApiResult.fail("Login name conflict");
}
accountService.modifyAccount(account);
return ApiResult.success();
}
@DeleteMapping
public ApiResult remove(@RequestBody Long[] ids) {
accountService.removeBatch(Arrays.asList(ids));
return ApiResult.success();
}
}
Technology Stack Overview
Backend with Spring Boot
Spring Boot is the backbone for crafting standalone, production-grade applications on top of the Spring ecosystem. Its opinionated defaults and auto-configuration drastically cut boilerplate code. With embedded servlet containers like Tomcat, deployment turns into a simple java -jar command. Actuator endpoints enable runtime health checks and metrics. The starter dependencies and @SpringBootApplication annotation make it trivial to assemble a cohesive backend with persistence, security, and tarnsaction support.
Frontend with Vue
Vue.js offers a reactive data-binding core that simplifies dynamic enterface development. Its component architecture encourages breaking UIs into isolated, reusable pieces, which improves maintainability and testability. A vibrant plugin ecosystem and clear documentation accelerate both learning and feature delivery. Vue's progressive nature allows adopting it incrementally, making it suitable for anything from enhancing static pages to building complex single-page applications.
Testing Methodology
System validation aims to uncover discrepancies between actual behavior and specifications. Functional testing relies on black‑box techniques: boundary value analysis, mandatory field checks, and role-based authorization paths. For example, login scenarios include mismatched credentials, missing inputs, and cross‑role access attempts. Each test case is documented with expected outcomes, and failures trigger immediate investigation. This process ensures logical flow correctness and guards against regressions. Post‑test reviews confirm that the platform meets defined requirements without comfort‑impeding complexity, delivering a stable and intuitive experience for end users interacting with fire safety educational content.