Detailed Video Demonstration
Contact the author for access to more detailed demonstration videos.
Specific Implementation Screenshots
Included in the documentation.
Technology Stack
Backend Framework: SpringBoot
Spring Boot, built on the Spring Framework, offers several advantages. It includes embedded servers like Tomcat, Jetty, and Undertow, which can be used without requiring separate installation or complex configuration. A key feature is its powerful auto-configuration capability, which automatically configures the application based on project dependencies, significantly simplifying development. Spring Boot also provides a rich set of out-of-the-box features and plugins, such as Spring Data, Spring Security, and Spring Cloud, enabling developers to build applications faster and integrate other technologies with ease. Additional benefits include flexible configuration management, rapid development and deployment cycles, excellent community support, monitoring and diagnostic tools, and robust testing support. These advantages make Spring Boot a popular framework for building high-quality applications efficiently, with good configurability, scalability, and maintainability.
Example core code:
package com.example.demo;
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 DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@GetMapping("/greeting")
public String getGreeting() {
return "Welcome to the platform!";
}
}
This code defines a Spring Boot application entry class DemoApplication, marked with the @SpringBootApplication annotation. The @RestController annotation designates the class as a RESTful controller.
The controller contains a getGreeting method, mapped to the "/greeting" path via @GetMapping. When this endpoint is accessed, it returns the string "Welcome to the platform!".
Executing SpringApplication.run starts the application. Spring Boot auto-configures and launches the embedded server. Accessing http://localhost:8080/greeting invokes the getGreeting method and returns the response.
This example illustrates a basic Spring Boot application, which can be extended and customized based on specific requirements.
Frontend Framework: Vue.js
Vue.js is a progressive JavaScript framework. One of its core strengths is the Virtual DOM, an in-memory data structure that enables efficient DOM manipulation.
Vue.js employs modern techniques like reactive data binding, the Virtual DOM, and component-based architecture, offering developers a flexible, efficient, and maintainable development model. When data changes, Vue.js automatically updates the UI, freeing developers from manual DOM updates and allowing greater focus on business logic.
Example code demonstrating Vue.js core functionality:
<!DOCTYPE html>
<html>
<head>
<title>Vue Demo</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h2>{{ greeting }}</h2>
<button @click="updateGreeting">Update Text</button>
</div>
<script>
new Vue({
el: '#app',
data: {
greeting: 'Hello, Vue!'
},
methods: {
updateGreeting: function() {
this.greeting = 'Vue.js is powerful!';
}
}
});
</script>
</body>
</html>
This example creates a Vue instance bound to the #app element. The data option defines a greeting property initialized to 'Hello, Vue!'. The double curly brace syntax {{ greeting }} renders this value in the HTML. The methods option defines an updateGreeting function that changes the greeting value when the button is clicked. Due to Vue's reactivity, the displayed text updates automatically when the data property changes.
This demonstrates Vue.js's simplicity, flexibility, and efficiency, facilitating a clear relationship between data and the UI, which improves developer productivity. Vue.js is a strong choice for building applications of any scale.
Persistence Layer: MyBatis
MyBatis is an open-source persistence framework that simplifies database interaction. Its core concept is the separation of SQL statements from Java code, describing database operations via XML or annotations, thereby decoupling the data access layer and increasing flexibility.
Key advantages of MyBatis include:
- Simplified Database Operations: MyBatis provides robust SQL mapping, allowing Java objects to be mapped to database tables. Developers avoid writing verbose SQL manually, simplifying code creation and maintenance.
- Flexible SQL Control: MyBatis supports dynamic SQL, enabling the generation of SQL statements based on varying conditions and logic, making queries and updates more adaptable.
- Caching Support: MyBatis offers first-level and second-level cache support, effectively reducing database hits and improving system performance.
- High Extensibility: MyBatis uses a plugin mechanism, making it easy to extend and customize functionality to meet diverse business needs.
System Testing
Comprehensive testing was conducted to ensure the system meets high-quality standards. The goal was to identify potential issues from multiple perspectives and make timely improvements, ensuring system integrity and reliability.
Functional testing helped uncover latent defects for correction, ensuring the system operates flawlessly and meets client requirements. We proactively sought problems and shortcomings, taking measures to address them.
Testing focused not only on functionality but also on whether the system satisfies user needs. Through these tests, we accurately evaluated system performance and drew conclusions. The objective was to guarantee system quality and stability, delivering an optimal user experience.
Continuous optimization efforts are made to meet user expectations and demands. Testing and refinement are ongoing to keep the system in its best state.
Purpose of System Testing
System testing is a critical phase in the management system development lifecycle. It serves as the final checkpoint for system quality and reliability, representing the last verification step in the development process.
The primary aim is to prevent user-facing issues and enhance the user experience. This involves considering potential problems from various angles and simulating different scenarios to discover defects and resolve them. Testing also assesses system quality, checks for functional completeness, and ensures logical coherence. Successful system testing significantly elevates system quality and user satisfaction.
The goal is to verify that the system conforms to the requirements specification and to identify any discrepancies. Throughout testing, we consistently adopt the user's perspective, avoiding time spent on unrealistic scenarios, to ensure expected outcomes match actual results.
This system is committed to safeguarding quality and stability, optimizing the user experience. System testing allows for timely issue identification and resolution, ensuring the system aligns with user needs and delivers excellent service. We strive continuously to improve system reliability and user satisfaction.
Functional System Testing
Functional system testing evaluates the system's functional modules. Methods include clicking, inputting boundary values, and validating required/optional fields—essentially black-box testing. Test cases are written, executed, and conclusions drawn.
For example, login functionality was tested. When a user logs in, the system validates credentials against the database. Incorrect input triggers an error message. The interface also validates role permissions; logging in with an admin role, for instance, results in an error. Below is a sample test case table for login:
| Input Data | Expected Result | Actual Result | Analysis |
|---|---|---|---|
| Username: admin Password: 123456 Code: correct | Login successful | Login successful | Consistent |
| Username: admin Password: 111111 Code: correct | Password error | Password error, please re-enter | Consistent |
| Username: admin Password: 123456 Code: incorrect | Code error | Verification code error | Consistent |
| Username: (empty) Password: 123456 Code: correct | Username required | Please enter username | Consistent |
| Username: admin Password: (empty) Code: correct | Password error | Password error, please re-enter | Consistent |
User management functions (add, edit, delete, search) were also tested. Sample test cases include:
Add User:
| Input Data | Expected Result | Actual Result | Analysis |
|---|---|---|---|
| Username: user1 Password: 123456 Role: User | Add success, appears in list | User1 appears in list | Consistent |
| Username: user2 Password: 111111 Role: User | Add success, appears in list | User2 appears in list | Consistent |
| Username: user1 Password: 123456 Role: User | Add fail, username exists | Add failed, username exists | Consistent |
| Username: (empty) Password: 123456 Role: User | Add fail, username required | Add failed, username cannot be empty | Consistent |
Edit User:
| Input Data | Expected Result | Actual Result | Analysis |
|---|---|---|---|
| Select User1, change password to 654321 | Edit success, password updated | User1 password changed to 654321 | Consistent |
| Select User2, change role to Admin | Edit success, role updated | User2 role changed to Admin | Consistent |
| Select User1, clear username | Edit fail, username required | Edit failed, username cannot be empty | Consistent |
Delete User:
| Input Data | Expected Result | Actual Result | Analysis |
|---|---|---|---|
| Select User1, delete | System prompts for confirmation, user deleted after confirm | User1 successfully deleted | Consistent |
| Select User2, delete, cancel | System prompts, deletion cancelled | User2 not deleted | Consistent |
Through functional testing, we ensure the system's functional completeness and that it operates according to the requirements specification. Testing continues to uncover and fix latent issues, providing users with a fully-featured system.
System Testing Conclusion
This system primarily employed black-box testing, simulating user interactions to test all functionalities via test cases. This ensures the correctness of system workflows. System testing is essential for refining the system and improving its usability. Testing validated that the functional modules meet the initial design philosophy and that the logic of each module is correct. The system avoids overly complex logic for ease of use. The ultimate testing goal revolves around the user experience. All test scenarios should align with user requirements, not deviating from the target. When issues arise, consider them from the user's perspective. The final test results indicate that the implemented system meets design requirements in terms of both functionality and performance.
Code Reference
// Annotation to ignore permission verification
@IgnoreAuth
@PostMapping(value = "/authenticate")
public ResponseResult login(String username, String password, String captcha, HttpServletRequest request) {
// Query user
UserEntity user = userService.selectOne(new QueryWrapper<UserEntity>().eq("username", username));
// Validate user existence and password
if(user == null || !user.getPassword().equals(password)) {
return ResponseResult.error("Incorrect username or password");
}
// Generate token
String token = tokenService.createToken(user.getId(), username, "users", user.getRole());
return ResponseResult.ok().put("token", token);
}
// Token generation method
@Override
public String createToken(Long userId, String username, String tableName, String role) {
// Check for existing token
TokenEntity tokenEntity = this.selectOne(new QueryWrapper<TokenEntity>().eq("userid", userId).eq("role", role));
// Generate random token string
String token = RandomStringUtils.randomAlphanumeric(32);
// Set token expiry to 1 hour from now
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.HOUR_OF_DAY, 1);
if(tokenEntity != null) {
// Update existing token
tokenEntity.setToken(token);
tokenEntity.setExpiryTime(cal.getTime());
this.updateById(tokenEntity);
} else {
// Insert new token record
this.insert(new TokenEntity(userId, username, tableName, role, token, cal.getTime()));
}
return token;
}
/**
* Permission (Token) Verification Interceptor
*/
@Component
public class AuthInterceptor implements HandlerInterceptor {
public static final String TOKEN_HEADER = "Authorization";
@Autowired
private TokenService tokenService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// Support CORS
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", "x-requested-with,request-source,Authorization, Origin, Content-Type, Cookie, Accept");
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
// Handle preflight OPTIONS request
if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
response.setStatus(HttpStatus.OK.value());
return false;
}
// Check for @IgnoreAuth annotation on the handler method
IgnoreAuth annotation;
if (handler instanceof HandlerMethod) {
annotation = ((HandlerMethod) handler).getMethodAnnotation(IgnoreAuth.class);
} else {
return true;
}
// Get token from header
String token = request.getHeader(TOKEN_HEADER);
// Bypass authentication for methods marked with @IgnoreAuth
if(annotation != null) {
return true;
}
// Retrieve token entity based on token
TokenEntity tokenEntity = null;
if(StringUtils.isNotBlank(token)) {
tokenEntity = tokenService.getTokenEntity(token);
}
if(tokenEntity != null) {
// Store user info in session
request.getSession().setAttribute("userId", tokenEntity.getUserid());
request.getSession().setAttribute("role", tokenEntity.getRole());
request.getSession().setAttribute("tableName", tokenEntity.getTablename());
request.getSession().setAttribute("username", tokenEntity.getUsername());
return true;
}
// Authentication failed, return 401 error
PrintWriter writer = null;
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
try {
writer = response.getWriter();
writer.print(JSONObject.toJSONString(ResponseResult.error(401, "Please login first")));
} finally {
if(writer != null){
writer.close();
}
}
return false;
}
}
This Java code implements login functionality with token generation and a permission verification interceptor.
@IgnoreAuth: A custom annotation marking methods that bypass permission checks.@PostMapping(value = "/authenticate"): A POST endpoint for login.loginmethod: Accepts username, passowrd, and captcha. It queries the user, validates credentials, and returns a response containing a generated token upon success.createTokenmethod: Generates a token. It checks for an existing token, creates a random string, sets an expiry time (1 hour), and either updates or inserts a token record.AuthInterceptorclass: An interceptor implementingHandlerInterceptor. ItspreHandlemethod handles CORS headers, preflight OPTIONS requests, and checks for the@IgnoreAuthannotation. It validates the token from the request header. If valid, user information is stored in the session. If invalid, a 401 error response is returned.
This setup provides a basic login system with token-based authentication, ensuring only users with valid tokens can access protected resources.
Database Reference
Example SQL for creating a product table:
-- ----------------------------
-- Table structure for product
-- ----------------------------
DROP TABLE IF EXISTS `product`;
CREATE TABLE `product` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
`name` varchar(100) NOT NULL COMMENT 'Product Name',
`price` decimal(10, 2) NOT NULL COMMENT 'Product Price',
`description` varchar(200) DEFAULT NULL COMMENT 'Product Description',
`stock` int(11) NOT NULL COMMENT 'Product Stock',
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation Time',
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Update Time',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='Product Table';
This product table includes the following fields:
id: Primary key, auto-increment.name: Product name, cannot be null.price: Product price, stored with 10 total digits and 2 decimal places.description: Product description, up to 200 characters.stock: Inventory quantity.create_time: Timestamp of record creation.update_time: Timestamp of the last update, automatically updated on modification.
Example insert statements:
INSERT INTO `product` (`name`, `price`, `description`, `stock`)
VALUES ('iPhone 13', 999.99, 'A powerful and advanced smartphone', 100);
INSERT INTO `product` (`name`, `price`, `description`, `stock`)
VALUES ('Samsung Galaxy S21', 899.99, 'A flagship Android smartphone', 150);
INSERT INTO `product` (`name`, `price`, `description`, `stock`)
VALUES ('Sony PlayStation 5', 499.99, 'Next-gen gaming console', 50);