Overview
This article presents a comprehensive management system designed for seafood processing and sales operations. The system leverages modern web technologies to provide an integrated solution for tracking products, managing inventory, and handling sales workflows.
Technology Stack
Backend: Spring Boot
Spring Boot serves as the foundation for the server-side implementation. This framework provides embedded server capabilities through Tomcat, Jetty, or Undertow, eliminating the need for separate application server installation. The auto-configuration mechanism dramatically reduces boilerplate setup by automatically configuring components based on project dependencies.
Key advantages include rapid development capabilities, comprehensive security integration through Spring Security, data access abstraction via Spring Data, and cloud-native support through Spring Cloud. The framework also offers robust monitoring tools and testing utilities that simplify the development lifecycle.
A minimal Spring Boot application structure appears as follows:
package com.seafood.management;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.*;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpStatus;
@SpringBootApplication
@RestController
@RequestMapping("/api")
public class ApplicationEntry {
public static void main(String[] args) {
SpringApplication.run(ApplicationEntry.class, args);
}
@GetMapping("/health")
public ResponseEntity<String> healthCheck() {
return ResponseEntity.status(HttpStatus.OK).body("Service is running");
}
}
This example demonstrates the startup class annotated with @SpringBootApplication, which triggers the auto-configuration scanning mechanism. The @RestController annotation indicates this class handles REST API requests, while @GetMapping defines the endpoint mapping for health verification operations.
Frontend: Vue.js
Vue.js provides the reactive frontend framework, utilizing a virtual DOM implementation for efficient DOM manipulation and updates. The framework implements two-way data binding, allowing automatic synchronization between the view layer and underlying data models. Component-based architecture facilitates code reuse and maintainability.
The following demonstrates fundamental Vue.js functionality:
<html>
<head>
<meta charset="UTF-8">
<title>Product Management</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="productApp">
<h1>{{ productTitle }}</h1>
<input v-model="newProduct" placeholder="Enter product name">
<button @click="addProduct">Add Product</button>
<ul>
<li v-for="item in productList" :key="item.id">
{{ item.name }}
</li>
</ul>
</div>
<script>
new Vue({
el: '#productApp',
data: {
productTitle: 'Product Catalog',
newProduct: '',
productList: [
{ id: 1, name: 'Shrimp' },
{ id: 2, name: 'Crab' }
]
},
methods: {
addProduct: function() {
if (this.newProduct.trim()) {
this.productList.push({
id: Date.now(),
name: this.newProduct
});
this.newProduct = '';
}
}
}
});
</script>
</body>
</html>
This example creates a Vue instance bound to the product management interface, demonstrating reactive data binding through the v-model directive and list rendering via v-for.
Persistence Layer: MyBatis
MyBatis handles database operations by separating SQL statements from application logic through XML mapping or annotations. This approach provides fine-grained control over SQL execution while maintaining clean separation of concerns.
The framework offers automatic SQL result mapping, dynamic SQL generation capabilities, built-in caching mechanisms, and plugin extensibility for custom functionality. These features significantly reduce the amount of boilerplate code required for data access operations.
System Testing
Comprehensive testing ensures system quality and reliability. The testing strategy employs multiple approaches to validate functionality and identify potential defects.
Testing Objectives
System testing validates that the implementation matches specified requirements and identifies any discrepancies between expected and actual behavior. Testing activities focus on user-centric scenarios to insure the system meets practical usage requirements.
Functional Testing
Functional testing validates individual system components through black-box testing techniques. Test cases cover various input scenarios including boundary conditions, required field validation, and optional field handling.
The following table presents test results for the authentication module:
User management functionality undergoes extensive testing, covering creation, modification, deletion, and search operations. Test cases verify proper database synchronization and user interface updates.
Testing Outcomes
Black-box testing validates system behavior from the user's perspective without examining internal implementation details. All tested functional modules demonstrate correct operation and meet the original design specifications. The testing process confirms that both functional and performance requirements have been satisfied.
Database Schema
The product catalog utilizes the following table structure:
DROP TABLE IF EXISTS `seafood_product`;
CREATE TABLE `seafood_product` (
`product_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
`product_name` varchar(100) NOT NULL COMMENT 'Product Name',
`unit_price` decimal(10, 2) NOT NULL COMMENT 'Unit Price',
`product_description` varchar(200) DEFAULT NULL COMMENT 'Product Description',
`inventory_count` int(11) NOT NULL COMMENT 'Inventory Quantity',
`creation_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Created At',
`modification_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Updated At',
PRIMARY KEY (`product_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='Seafood Product Table';
This schema captures essential product information including pricing, inventory levels, and audit timestamps for tracking record modifications.
Backend Implementation
Authentication and authorization components handle user identity verification and access control.
// Authentication endpoint accessible without token
@IgnoreAuth
@PostMapping(value = "/authenticate")
public ResponseResult authenticate(String accountName, String passWord, String verifyCode, HttpServletRequest req) {
// Retrieve user entity from database
UserEntity userRecord = userService.findOne(
new EntityWrapper<UserEntity>().eq("accountName", accountName)
);
// Validate credentials
if(userRecord == null || !userRecord.getPassWord().equals(passWord)) {
return ResponseResult.error("Invalid account or password");
}
// Create authentication token
String sessionToken = tokenService.generateToken(
userRecord.getId(),
accountName,
"users",
userRecord.getRole()
);
return ResponseResult.success().put("token", sessionToken);
}
@Override
public String generateToken(Long userId, String accountName, String tableName, String roleName) {
// Check for existing token
TokenEntity existingToken = this.findOne(
new EntityWrapper<TokenEntity>()
.eq("userId", userId)
.eq("roleName", roleName)
);
// Generate random token identifier
String tokenValue = CommonUtil.generateRandomString(32);
// Set expiration to one hour from current time
Calendar expiration = Calendar.getInstance();
expiration.add(Calendar.HOUR_OF_DAY, 1);
if(existingToken != null) {
// Update existing token record
existingToken.setTokenValue(tokenValue);
existingToken.setExpirationTime(expiration.getTime());
this.updateById(existingToken);
} else {
// Create new token record
TokenEntity newToken = new TokenEntity(
userId, accountName, tableName, roleName, tokenValue, expiration.getTime()
);
this.insert(newToken);
}
return tokenValue;
}
The token generation service creates time-limited authentication tokens, supporting both token creation and renewal operations.
Authorization Interceptor
The permission validation interceptor examines incoming requests and enforces access control policies.
@Component
public class SecurityInterceptor implements HandlerInterceptor {
public static final String TOKEN_HEADER = "Authorization-Token";
@Autowired
private TokenValidationService tokenService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// Configure CORS headers for cross-origin requests
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers",
"Content-Type, Authorization-Token, X-Requested-With");
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
// Handle preflight requests immediately
if (HttpMethod.OPTIONS.matches(request.getMethod())) {
response.setStatus(HttpStatus.OK.value());
return false;
}
// Extract permission exemption annotation
IgnoreAuth skipAuth;
if (handler instanceof HandlerMethod) {
skipAuth = ((HandlerMethod) handler).getMethodAnnotation(IgnoreAuth.class);
} else {
return true;
}
// Extract token from request headers
String token = request.getHeader(TOKEN_HEADER);
// Bypass validation for exempt endpoints
if(skipAuth != null) {
return true;
}
// Validate token and retrieve associated session data
TokenEntity tokenRecord = null;
if(StringUtils.isNotBlank(token)) {
tokenRecord = tokenService.retrieveSession(token);
}
if(tokenRecord != null) {
// Populate session attributes for downstream processing
HttpSession session = request.getSession();
session.setAttribute("userId", tokenRecord.getUserId());
session.setAttribute("role", tokenRecord.getRoleName());
session.setAttribute("entityTable", tokenRecord.getTableName());
session.setAttribute("accountName", tokenRecord.getUsername());
return true;
}
// Return unauthorized status for invalid or missing tokens
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter output = response.getWriter();
output.write(JSONObject.toJSONString(ResponseResult.error(401, "Authentication required")));
output.close();
return false;
}
}
This interceptor handles cross-origin requests, evaluates permission exemptions, validates authentication tokens, and manages session state for authenticated users.
Data Sample
INSERT INTO `seafood_product` (`product_name`, `unit_price`, `product_description`, `inventory_count`)
VALUES ('Fresh Shrimp Pack', 49.99, 'Premium quality wild-caught shrimp', 500);
INSERT INTO `seafood_product` (`product_name`, `unit_price`, `product_description`, `inventory_count`)
VALUES ('Blue Crab Bundle', 79.99, 'Live blue crabs from local waters', 200);
INSERT INTO `seafood_product` (`product_name`, `unit_price`, `product_description`, `inventory_count`)
VALUES ('Processed Fish Fillets', 35.99, 'Pre-cleaned and ready to cook', 350);