Campus Online Food Ordering System Built with Java and Vue
The backend of the system is built using Spring Boot, which simplifies configuration through convention-over-configuration principles and auto-configuration based on project dependencies. This allows developers to focus primarily on business logic rather than boilerplate setup. The frontend leverages Vue.js for its intuitive API and reactive data binding, enabling efficient development of dynamic user interfaces with minimal direct DOM manipulasion.
Functional Testing
Key functionalities such as user authentication and user management were validated through black-box testing. Test cases covered valid and invalid inputs, boundary conditions, and mandatory field validations.
Login Functionality Test Cases:
| Input Data | Expected Result | Actual Result | Analysis |
|---|---|---|---|
| Valid username, password, and CAPTCHA | Successful login | Login succeeded | Matches expectation |
| Incorrect password | Error message | "Incorrect password" shown | Matches expectation |
| Invalid CAPTCHA | CAPTCHA error | "Invalid CAPTCHA" shown | Matches expectation |
| Empty username | Prompt for username | "Usernamee required" shown | Matches expectation |
| Empty password | Password error | "Incorrect password" shown | Matches expectation |
User Management Test Cases:
| Input Data | Expected Result | Actual Result | Analysis |
|---|---|---|---|
| Complete user info | User added successfully | Appears in list | Matches expectation |
| Modify existing user | Info updated | Changes reflected | Matches expectation |
| Delete user | Confirmation prompt, then removal | User no longer found | Matches expectation |
| Missing username | Validation error | "Username required" shown | Matches expectation |
| Duplicate username | Add failure | "Username already exists" shown | Matches expectation |
Database Schema
Core tables include yonghu (users), messages (comments), and token (session tokens):
CREATE TABLE `yonghu` (
`id` BIGINT NOT NULL AUTO_INCREMENT COMMENT 'Primary key',
`addtime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`yonghuming` VARCHAR(200) NOT NULL UNIQUE,
`mima` VARCHAR(200) NOT NULL,
`xingming` VARCHAR(200),
`xingbie` VARCHAR(200),
`touxiang` VARCHAR(200),
`shouji` VARCHAR(200),
`shenfenzheng` VARCHAR(200),
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
CREATE TABLE `messages` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`addtime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`userid` BIGINT NOT NULL,
`username` VARCHAR(200),
`content` LONGTEXT NOT NULL,
`reply` LONGTEXT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
CREATE TABLE `token` (
`id` BIGINT NOT NULL AUTO_INCREMENT,
`userid` BIGINT NOT NULL,
`username` VARCHAR(100) NOT NULL,
`tablename` VARCHAR(100),
`role` VARCHAR(100),
`token` VARCHAR(200) NOT NULL,
`addtime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`expiratedtime` TIMESTAMP NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
Sample Backend Code
A shared controller handles common utilities like geolocation and facial comparison:
@RestController
public class SharedController {
@Autowired
private SharedService sharedService;
@Autowired
private SettingsService settingsService;
private static AipFace faceClient = null;
private static String BAIDU_MAP_KEY = null;
@GetMapping("/geolocate")
public ApiResponse geolocate(String longitude, String latitude) {
if (BAIDU_MAP_KEY == null) {
BAIDU_MAP_KEY = settingsService.getSettingValue("baidu_map_ak");
if (BAIDU_MAP_KEY == null) {
return ApiResponse.error("Baidu Map AK not configured");
}
}
Map<String, String> location = BaiduMapUtil.getCity(longitude, latitude, BAIDU_MAP_KEY);
return ApiResponse.success(location);
}
@PostMapping("/compareFaces")
public ApiResponse compareFaces(String imageA, String imageB) {
if (faceClient == null) {
String apiKey = settingsService.getSettingValue("face_api_key");
String secretKey = settingsService.getSettingValue("face_secret_key");
if (apiKey == null || secretKey == null) {
return ApiResponse.error("Face API credentials missing");
}
faceClient = new AipFace(null, apiKey, secretKey);
faceClient.setConnectionTimeoutInMillis(2000);
faceClient.setSocketTimeoutInMillis(60000);
}
try {
Path uploadDir = Paths.get(ResourceUtils.getFile("classpath:static/upload").getAbsolutePath());
byte[] img1Bytes = Files.readAllBytes(uploadDir.resolve(imageA));
byte[] img2Bytes = Files.readAllBytes(uploadDir.resolve(imageB));
String encoded1 = Base64.getEncoder().encodeToString(img1Bytes);
String encoded2 = Base64.getEncoder().encodeToString(img2Bytes);
List<MatchRequest> requests = Arrays.asList(
new MatchRequest(encoded1, "BASE64"),
new MatchRequest(encoded2, "BASE64")
);
JSONObject result = faceClient.match(requests);
return ApiResponse.success(JSON.parseObject(result.getJSONObject("result").toString()));
} catch (IOException e) {
return ApiResponse.error("Image file not found or unreadable");
}
}
}