SparkMovie Novel Website Built with SpringBoot Vue and UniApp Full Source Code Available

This project presents a complete movie and novel information website designed using SpringBoot, Vue (frontend), and UniApp (mobile). It includes full source code, deployment documentation, and an explanatory guide. The system supports user registration, content browsing, and admin management. It is suitable for learning full-stack development or as a graduation project reference.

Technical Stack

Backend Framework: SpringBoot

SpringBoot provides embedded servers like Tomcat, Jetty, and Undertow, enabling zero-configuration deployment. Its auto-configuration feature reduces manual setup by detecting dependencies in the classpath. The framework offers integrations with Spring Data, Spring Security, and Spring Cloud, speeding up development for scalable web applications. In this project, SpringBoot handles REST API creation, data persistence, and security.

Frontend Framework: Vue.js

Vue.js leverages a virtual DOM to optimize rendering performance. It supports reactive data binding, component-based architecture, and direct DOM manipulation when needed. This approach simplifies UI updates: when data changes, the view automatically refreshes without manual DOM handling. The result is a clean, maintainable frontend that separates logic from presentation.

Persistence Layer: MyBatis-Plus

MyBatis-Plus extends MyBatis with enhanced features such as automatic SQL generation, pagination, dynamic queries, optimistic locking, and performance analysis. It reduces boilerplate code by providing pre-built CRUD operations. The included code generator creates entity classes, Mapper interfaces, and XML mapping files from database tables. This speeds up development and ensures consistency across the data access layer.

System Testing

Testing Objectives

The primary goal of testing is to verify that the system meets functional requirements and operates without defects. Black-box testing is used to simulate user interactions across different modules. Test cases are designed to cover valid inputs, boundary values, and error handling. The process ensures that all features work correctly under expected usage patterns.

Functional Test Scenarios

Login Functionality: The login page validates credentials against the database. Test cases include correct credentials, wrong password, invalid captcha, and missing fields. The system displays appropriate error messages for each failure.

Input Data Expected Result Actual Result Outcome
Username: admin, Password: 123456, Captcha: correct Successful login Enters system Pass
Username: admin, Password: 111111, Captcha: correct Login fails, password error message Shows "Password incorrect, please re-enter" Pass
Username: admin, Password: 123456, Captcha: wrong Login fails, captcha error message Shows "Captcha error" Pass
Username: (empty), Password: 123456, Captcha: correct Mandatory field check Shows "Please enter username" Pass
Username: admin, Password: (empty), Captcha: corrrect Mandatory field check Shows "Please enter password" Pass

User Management: Tests cover adding, editing, deleting, and searching users. Key checks include empty required fields, duplicate usernames, and deletion confirmations.

Input Action Expected Result Actual Result Outcome
Fill all user details and submit User added and visible in list User appears in list Pass
Modify existing user details User updated with new information Changes reflected in list Pass
Delete an existing user Confirmation dialog, then user removed Confirmation shown, user removed Pass
Add user with empty username Username required error Shows "Username cannot be empty" Pass
Add user with duplicate username Duplicate username error Shows "Username already exists" Pass

Testing Conclusion

All functional tests passed. The system handles authentication, data validation, and user enteraction correctly. No critical defects were found. The application meets its design specifications and provides a stable user experience.

Code Sample

@IgnoreAuth
@PostMapping(value = "/login")
public R login(String username, String password, String captcha, HttpServletRequest request) {
   UsersEntity user = userService.selectOne(new EntityWrapper<UsersEntity>().eq("username", username));
   if(user==null || !user.getPassword().equals(password)) {
      return R.error("Account or password incorrect");
   }
   String token = tokenService.generateToken(user.getId(), username, "users", user.getRole());
   return R.ok().put("token", token);
}

@Override
public String generateToken(Long userid, String username, String tableName, String role) {
   TokenEntity tokenEntity = this.selectOne(new EntityWrapper<TokenEntity>().eq("userid", userid).eq("role", role));
   String token = CommonUtil.getRandomString(32);
   Calendar cal = Calendar.getInstance();   
   cal.setTime(new Date());   
   cal.add(Calendar.HOUR_OF_DAY, 1);
   if(tokenEntity != null) {
      tokenEntity.setToken(token);
      tokenEntity.setExpiratedtime(cal.getTime());
      this.updateById(tokenEntity);
   } else {
      this.insert(new TokenEntity(userid, username, tableName, role, token, cal.getTime()));
   }
   return token;
}

/**
 * Token-based authorization interceptor
 */
@Component
public class AuthorizationInterceptor implements HandlerInterceptor {

    public static final String LOGIN_TOKEN_KEY = "Token";

    @Autowired
    private TokenService tokenService;
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // Handle 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,Token, Origin,imgType, Content-Type, cache-control,postman-token,Cookie, Accept,authorization");
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        if (request.getMethod().equals(RequestMethod.OPTIONS.name())) {
            response.setStatus(HttpStatus.OK.value());
            return false;
        }
        
        IgnoreAuth annotation;
        if (handler instanceof HandlerMethod) {
            annotation = ((HandlerMethod) handler).getMethodAnnotation(IgnoreAuth.class);
        } else {
            return true;
        }

        String token = request.getHeader(LOGIN_TOKEN_KEY);
        
        if (annotation != null) {
            return true;
        }
        
        TokenEntity tokenEntity = null;
        if (StringUtils.isNotBlank(token)) {
            tokenEntity = tokenService.getTokenEntity(token);
        }
        
        if (tokenEntity != null) {
            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;
        }
        
        PrintWriter writer = null;
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8");
        try {
            writer = response.getWriter();
            writer.print(JSONObject.toJSONString(R.error(401, "Please login first")));
        } finally {
            if (writer != null) {
                writer.close();
            }
        }
        return false;
    }
}

Database Schema

-- Token table
DROP TABLE IF EXISTS `token`;
CREATE TABLE `token` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Primary key',
  `userid` bigint(20) NOT NULL COMMENT 'User ID',
  `username` varchar(100) NOT NULL COMMENT 'Username',
  `tablename` varchar(100) DEFAULT NULL COMMENT 'Table name',
  `role` varchar(100) DEFAULT NULL COMMENT 'Role',
  `token` varchar(200) NOT NULL COMMENT 'Token string',
  `addtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Creation time',
  `expiratedtime` 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';

-- Sample token data
INSERT INTO `token` VALUES ('9', '23', 'cd01', 'xuesheng', 'Student', 'al6svx5qkei1wljry5o1npswhdpqcpcg', '2023-02-23 21:46:45', '2023-03-15 14:01:36');
INSERT INTO `token` VALUES ('10', '11', 'xh01', 'xuesheng', 'Student', 'fahmrd9bkhqy04sq0fzrl4h9m86cu6kx', '2023-02-27 18:33:52', '2023-03-17 18:27:42');
INSERT INTO `token` VALUES ('11', '17', 'ch01', 'xuesheng', 'Student', 'u5km44scxvzuv5yumdah2lhva0gp4393', '2023-02-27 18:46:19', '2023-02-27 19:48:58');
INSERT INTO `token` VALUES ('12', '1', 'admin', 'users', 'Admin', 'h1pqzsb9bldh93m92j9m2sljy9bt1wdh', '2023-02-27 19:37:01', '2023-03-17 18:23:02');
INSERT INTO `token` VALUES ('13', '21', 'xiaohao', 'shezhang', 'President', 'zdm7j8h1wnfe27pkxyiuzvxxy27ykl2a', '2023-02-27 19:38:07', '2023-03-17 18:25:20');
INSERT INTO `token` VALUES ('14', '27', 'djy01', 'xuesheng', 'Student', 'g3teq4335pe21nwuwj2sqkrpqoabqomm', '2023-03-15 12:56:17', '2023-03-15 14:00:16');
INSERT INTO `token` VALUES ('15', '29', 'dajiyue', 'shezhang', 'President', '0vb1x9xn7riewlp5ddma5ro7lp4u8m9j', '2023-03-15 12:58:08', '2023-03-15 14:03:48');

For the complete project, including database scripts, source code, and deployement instructions, please contact the author.

Tags: SpringBoot vue mybatis-plus UniApp Token Authentication

Posted on Mon, 31 Aug 2026 16:31:39 +0000 by RickChase