Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Design and Implementation of a Personal Finance System Using Java, Spring Boot, and Vue

Tech 3

The increasing demand for personal financial management has led to the development of personal finance systems. These systems provide a convenient and effective way for individuals to manage income, expenses, investments, and savings. The rapid growth of financial technology (Fintech) supports these systems with internet, mobile devices, data analysis, and artificial intelligence technologies. They offer features like account management, budget planning, investment advice, and financial analysis, delivering intelligent and personalized services. Many people lack sufficient knowledge and experience in financial management, leading to risks and waste. Personal finance systems help improve financial literacy through education, budgeting tools, and account analysis. Traditional banking services often fail to meet diverse and personalized needs, but these systems provide customized solutions with personalized account settings and intelligent data analysis. The openness of financial markets and the popularity of internet and mobile payments accelerate their development, offering more choices and better experiences from both traditional institutions and new Fintech platforms.

Backend Framework: Spring Boot

Spring Boot includes built-in servers like Tomcat, Jetty, and Undertow, allowing direct use without additional installation and configuration. A key advantage is its auto-configuration capability, which automatically sets up applications based on project dependencies, simplifying configuration. It also provides many out-of-the-box features and plugins, such as Spring Data, Spring Security, and Spring Cloud, enabling faster development and easier integration with other technologies. As a popular framework, its auto-configuration, built-in servers, and plugins help developers build high-quality applications quickly and efficiently.

Frontend Framework: Vue

Vue.js utilizes virtual DOM technology, a memory data structure that enables efficient DOM operations. It employs reactive data binding, virtual DOM, and componentization, offering a flexible, efficient, and maintainable development model. When data changes, the UI updates automatically, allowing developers to focus on data processing rather than manual UI updates, making Vue concise, flexible, and efficient.

Database: MySQL

MySQL is an open-source relational database management system (RDBMS) widely used in backend development, data storage, and retrieval. Its open-source nature allows free use, modification, and distribusion of source code, making it a preferred choice for many developers and organizations. MySQL supports multiple platforms, including Windows, Linux, and macOS, providing flexibility for various development and deployment environments. A large community offers extensive documentation, forums, and tools, enhancing its usability.

System Testing

System testing is essential in the development cycle to ensure quality and reliability. It serves as the final check before deployment, aiming to prevent user issues and enhance experience. Testing should consider multiple angles and scenarios to identify and resolve defects, ensuring the system meets requirements and functions correctly.

System Testing Objectives

Testing verifies that the system meets specification requirements and identifies any inconsistencies. It should focus on user perspectives, avoiding unrealistic scenarios to prevent wasted time and mismatched results.

System Functional Testing

Functional modules are tested through methods like clicking, inputting boundary values, and validating required fields using black-box testing. Test cases are written and executed to derive conclusions.

Login Function Testing Scheme: When logging in, the system validates credentials like username and password. Users must input data matching stored database entries; errors prompt corrections. The interface also validates role permissions, with erors for incorrect role selections. Login test cases are shown in the table below.

Input Data Expected Result Actual Result Result Analysis
Username: admin, Password: 123456, Captcha: correct Login successful Login successful Matches expected
Username: admin, Password: 111111, Captcha: correct Password error Password error, re-enter Matches expected
Username: admin, Password: 123456, Captcha: incorrect Captcha error Captcha information error Matches expected
Username: empty, Password: 123456, Captcha: correct Username required Please enter username Matches expected
Username: admin, Password: empty, Captcha: correct Password error Password error, re-enter Matches expected

User Management Function Testing Scheme: User management includes add, edit, delete, and search functions. When adding a user, required fields are validated for non-emptiness; adding existing user information checks for duplicate username prompts; deleting user information verifies system confirmation; editing user information ensures changes are displayed. User management test cases are shown in the table below.

Input Data Expected Result Actual Result Result Analysis
Fill in basic user information Add successful, displayed in list User appears in list Matches expected
Modify user information Edit successful, information updated User information modified Matches expected
Select delete user System asks for confirmation, user deleted after confirm System asks for confirmation, user not found after confirm Matches expected
Add user without username Prompt username cannot be empty Prompt username cannot be empty Matches expected
Fill in existing username Add failed, prompt duplicate username Add failed, prompt duplicate username Matches expected

System Testing Conclusion

This system primarily uses black-box testing, simulating user operations to write and execute test cases, ensuring corect system flow. Testing is crucial for system improvement and higher usability. It validates that functional modules meet initial design concepts and logic correctness. The system does not require complex logic processing for ease of use. The ultimate goal revolves around user experience, with all scenarios aligned to user needs. After testing, the system meets design requirements in functionality and performance.

Code Reference

@IgnoreAuth
@PostMapping("/authenticate")
public Response authenticateUser(String userIdentifier, String secretCode, String verificationCode, HttpServletRequest req) {
    UserAccount account = accountService.fetchUser(new EntityWrapper<UserAccount>().eq("userIdentifier", userIdentifier));
    if (account == null || !account.getSecretCode().equals(secretCode)) {
        return Response.error("Invalid credentials");
    }
    String authToken = authTokenService.createToken(account.getId(), userIdentifier, "userAccounts", account.getRole());
    return Response.ok().withData("authToken", authToken);
}

@Override
public String createToken(Long accountId, String userIdentifier, String tableName, String role) {
    AuthTokenEntity tokenEntry = this.fetchOne(new EntityWrapper<AuthTokenEntity>().eq("accountId", accountId).eq("role", role));
    String newToken = Utility.generateRandomString(32);
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(new Date());
    calendar.add(Calendar.HOUR_OF_DAY, 1);
    if (tokenEntry != null) {
        tokenEntry.setToken(newToken);
        tokenEntry.setExpirationTime(calendar.getTime());
        this.updateById(tokenEntry);
    } else {
        this.insert(new AuthTokenEntity(accountId, userIdentifier, tableName, role, newToken, calendar.getTime()));
    }
    return newToken;
}

@Component
public class AuthInterceptor implements HandlerInterceptor {
    public static final String AUTH_TOKEN_HEADER = "Auth-Token";
    @Autowired
    private AuthTokenService tokenService;
    
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse resp, Object handler) throws Exception {
        resp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        resp.setHeader("Access-Control-Max-Age", "3600");
        resp.setHeader("Access-Control-Allow-Credentials", "true");
        resp.setHeader("Access-Control-Allow-Headers", "x-requested-with,request-source,Auth-Token, Origin,imgType, Content-Type, cache-control,postman-token,Cookie, Accept,authorization");
        resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
        if (req.getMethod().equals(RequestMethod.OPTIONS.name())) {
            resp.setStatus(HttpStatus.OK.value());
            return false;
        }
        IgnoreAuth annotation;
        if (handler instanceof HandlerMethod) {
            annotation = ((HandlerMethod) handler).getMethodAnnotation(IgnoreAuth.class);
        } else {
            return true;
        }
        String token = req.getHeader(AUTH_TOKEN_HEADER);
        if (annotation != null) {
            return true;
        }
        AuthTokenEntity tokenEntry = null;
        if (StringUtils.isNotBlank(token)) {
            tokenEntry = tokenService.getTokenEntry(token);
        }
        if (tokenEntry != null) {
            req.getSession().setAttribute("accountId", tokenEntry.getAccountId());
            req.getSession().setAttribute("role", tokenEntry.getRole());
            req.getSession().setAttribute("tableName", tokenEntry.getTableName());
            req.getSession().setAttribute("userIdentifier", tokenEntry.getUserIdentifier());
            return true;
        }
        PrintWriter writer = null;
        resp.setCharacterEncoding("UTF-8");
        resp.setContentType("application/json; charset=utf-8");
        try {
            writer = resp.getWriter();
            writer.print(JSONObject.toJSONString(Response.error(401, "Authentication required")));
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
        return false;
    }
}

Database Reference

-- ----------------------------
-- Table structure for auth_token
-- ----------------------------
DROP TABLE IF EXISTS `auth_token`;
CREATE TABLE `auth_token` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Primary key',
  `account_id` bigint(20) NOT NULL COMMENT 'Account ID',
  `user_identifier` varchar(100) NOT NULL COMMENT 'User identifier',
  `table_name` varchar(100) DEFAULT NULL COMMENT 'Table name',
  `role` varchar(100) DEFAULT NULL COMMENT 'Role',
  `token` varchar(200) NOT NULL COMMENT 'Token',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation time',
  `expires_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Expiration time',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='Token table';

-- ----------------------------
-- Records of auth_token
-- ----------------------------
INSERT INTO `auth_token` VALUES ('9', '23', 'cd01', 'student', 'Student', 'al6svx5qkei1wljry5o1npswhdpqcpcg', '2023-02-23 21:46:45', '2023-03-15 14:01:36');
INSERT INTO `auth_token` VALUES ('10', '11', 'xh01', 'student', 'Student', 'fahmrd9bkhqy04sq0fzrl4h9m86cu6kx', '2023-02-27 18:33:52', '2023-03-17 18:27:42');
INSERT INTO `auth_token` VALUES ('11', '17', 'ch01', 'student', 'Student', 'u5km44scxvzuv5yumdah2lhva0gp4393', '2023-02-27 18:46:19', '2023-02-27 19:48:58');
INSERT INTO `auth_token` VALUES ('12', '1', 'admin', 'user_accounts', 'Administrator', 'h1pqzsb9bldh93m92j9m2sljy9bt1wdh', '2023-02-27 19:37:01', '2023-03-17 18:23:02');
INSERT INTO `auth_token` VALUES ('13', '21', 'xiaohao', 'club_leader', 'Club Leader', 'zdm7j8h1wnfe27pkxyiuzvxxy27ykl2a', '2023-02-27 19:38:07', '2023-03-17 18:25:20');
INSERT INTO `auth_token` VALUES ('14', '27', 'djy01', 'student', 'Student', 'g3teq4335pe21nwuwj2sqkrpqoabqomm', '2023-03-15 12:56:17', '2023-03-15 14:00:16');
INSERT INTO `auth_token` VALUES ('15', '29', 'dajiyue', 'club_leader', 'Club Leader', '0vb1x9xn7riewlp5ddma5ro7lp4u8m9j', '2023-03-15 12:58:08', '2023-03-15 14:03:48');

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.