基于 Vue 和 SSM 的前后端分离项目实战:登录与注册功能实现

文章目录

    • 前言
    • 项目概述
    • 前端部分(Vue)
      • [1. 项目初始化](#1. 项目初始化)
      • [2. 页面布局](#2. 页面布局)
      • [3. 路由配置](#3. 路由配置)
      • [4. 主组件](#4. 主组件)
    • 后端部分(SSM)
      • [1. 项目结构](#1. 项目结构)
      • [2. 数据库设计](#2. 数据库设计)
      • [3. MyBatis 配置](#3. MyBatis 配置)
      • [4. DAO 层](#4. DAO 层)
      • [5. Service 层](#5. Service 层)
      • [6. Controller 层](#6. Controller 层)
      • [7. 配置文件](#7. 配置文件)
      • [8. Spring 配置](#8. Spring 配置)
      • [9. Servlet 配置](#9. Servlet 配置)
      • [10. 部署到 Tomcat](#10. 部署到 Tomcat)
    • 总结

前言

在现代 Web 开发中,前后端分离架构已经成为主流。前端负责页面展示和交互,后端提供数据接口,二者通过 API 进行通信。本文将通过一个实战小项目,详细介绍如何使用 Vue.js 搭建前端界面,以及使用 SSM 框架(Spring、SpringMVC、MyBatis)构建基于 Tomcat 部署的后端服务,实现登录和注册功能。

项目概述

我们将构建一个简单的用户管理系统,包含用户注册和登录功能。前端使用 Vue.js 框架,后端使用 SSM 框架进行开发,并通过 Tomcat 部署后端服务。通过这个项目,可以深入理解前后端分离的开发模式以及各个框架的使用方法。

前端部分(Vue)

1. 项目初始化

首先,使用 Vue CLI 创建一个新的 Vue 项目:

bash 复制代码
vue create user-management

选择默认的配置或者根据自己的需求进行定制。创建完成后,进入项目目录:

bash 复制代码
cd user-management

然后安装所需的依赖:

bash 复制代码
npm install axios vue-router element-ui
  • axios 用于发送 HTTP 请求。
  • vue-router 用于实现页面路由。
  • element-ui 是一个基于 Vue 的 UI 组件库,用于快速构建页面。

2. 页面布局

src/views 目录下创建两个视图文件:Login.vueRegister.vue,分别用于登录和注册页面。

Login.vue
html 复制代码
<template>
  <div class="login-container">
    <el-form :model="loginForm" :rules="rules" ref="loginForm" label-width="80px">
      <el-form-item label="用户名" prop="username">
        <el-input v-model="loginForm.username"></el-input>
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input type="password" v-model="loginForm.password"></el-input>
      </el-form-item>
      <el-button type="primary" @click="submitLogin">登录</el-button>
    </el-form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      loginForm: {
        username: '',
        password: ''
      },
      rules: {
        username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
        password: [{ required: true, message: '请输入密码', trigger: 'blur' }]
      }
    };
  },
  methods: {
    submitLogin() {
      this.$refs.loginForm.validate((valid) => {
        if (valid) {
          // 调用后端接口
          axios.post('/api/login', this.loginForm)
            .then(response => {
              if (response.data.success) {
                this.$message.success('登录成功');
                // 保存 token
                localStorage.setItem('token', response.data.token);
                this.$router.push('/home');
              } else {
                this.$message.error(response.data.message);
              }
            });
        }
      });
    }
  }
};
</script>
Register.vue
html 复制代码
<template>
  <div class="register-container">
    <el-form :model="registerForm" :rules="rules" ref="registerForm" label-width="80px">
      <el-form-item label="用户名" prop="username">
        <el-input v-model="registerForm.username"></el-input>
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input type="password" v-model="registerForm.password"></el-input>
      </el-form-item>
      <el-form-item label="确认密码" prop="confirmPassword">
        <el-input type="password" v-model="registerForm.confirmPassword"></el-input>
      </el-form-item>
      <el-button type="primary" @click="submitRegister">注册</el-button>
    </el-form>
  </div>
</template>

<script>
export default {
  data() {
    return {
      registerForm: {
        username: '',
        password: '',
        confirmPassword: ''
      },
      rules: {
        username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
        password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
        confirmPassword: [{ required: true, message: '请确认密码', trigger: 'blur' }]
      }
    };
  },
  methods: {
    submitRegister() {
      this.$refs.registerForm.validate((valid) => {
        if (valid) {
          if (this.registerForm.password !== this.registerForm.confirmPassword) {
            this.$message.error('两次密码不一致');
            return;
          }
          // 调用后端接口
          axios.post('/api/register', this.registerForm)
            .then(response => {
              if (response.data.success) {
                this.$message.success('注册成功');
                this.$router.push('/login');
              } else {
                this.$message.error(response.data.message);
              }
            });
        }
      });
    }
  }
};
</script>

3. 路由配置

src/router/index.js 中配置路由:

javascript 复制代码
import Vue from 'vue';
import VueRouter from 'vue-router';
import Login from '../views/Login.vue';
import Register from '../views/Register.vue';
import Home from '../views/Home.vue';

Vue.use(VueRouter);

const routes = [
  {
    path: '/',
    redirect: '/login'
  },
  {
    path: '/login',
    component: Login
  },
  {
    path: '/register',
    component: Register
  },
  {
    path: '/home',
    component: Home
  }
];

const router = new VueRouter({
  mode: 'history',
  routes
});

export default router;

4. 主组件

src/App.vue 中设置主组件:

html 复制代码
<template>
  <div id="app">
    <router-view></router-view>
  </div>
</template>

后端部分(SSM)

1. 项目结构

后端项目采用 Maven 构建,主要模块包括:

  • src/main/java/com/example/usermanagement/controller:控制器层,处理前端请求。
  • src/main/java/com/example/usermanagement/service:服务层,处理业务逻辑。
  • src/main/java/com/example/usermanagement/dao:数据访问层,使用 MyBatis 操作数据库。
  • src/main/resources/mapper:MyBatis 的 XML 映射文件。
  • src/main/resources/application.properties:配置文件。

2. 数据库设计

创建一个名为 user_management 的数据库,包含一个 user 表:

sql 复制代码
CREATE TABLE user (
  id INT AUTO_INCREMENT PRIMARY KEY,
  username VARCHAR(50) NOT NULL UNIQUE,
  password VARCHAR(100) NOT NULL
);

3. MyBatis 配置

src/main/resources/mapper/UserMapper.xml 中配置 MyBatis 的 SQL 映射:

xml 复制代码
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.example.usermanagement.dao.UserDao">

  <insert id="registerUser" parameterType="com.example.usermanagement.model.User">
    INSERT INTO user (username, password) VALUES (#{username}, #{password})
  </insert>

  <select id="getUserByUsername" parameterType="String" resultType="com.example.usermanagement.model.User">
    SELECT * FROM user WHERE username = #{username}
  </select>

</mapper>

4. DAO 层

创建 UserDao 接口:

java 复制代码
package com.example.usermanagement.dao;

import com.example.usermanagement.model.User;

public interface UserDao {
    int registerUser(User user);
    User getUserByUsername(String username);
}

5. Service 层

创建 UserService 接口及其实现类 UserServiceImpl

java 复制代码
package com.example.usermanagement.service;

import com.example.usermanagement.model.User;

public interface UserService {
    boolean register(User user);
    boolean login(String username, String password);
}
java 复制代码
package com.example.usermanagement.service.impl;

import com.example.usermanagement.dao.UserDao;
import com.example.usermanagement.model.User;
import com.example.usermanagement.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public boolean register(User user) {
        return userDao.registerUser(user) > 0;
    }

    @Override
    public boolean login(String username, String password) {
        User user = userDao.getUserByUsername(username);
        return user != null && user.getPassword().equals(password);
    }
}

6. Controller 层

创建 UserController

java 复制代码
package com.example.usermanagement.controller;

import com.example.usermanagement.model.User;
import com.example.usermanagement.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api")
public class UserController {

    @Autowired
    private UserService userService;

    @PostMapping("/register")
    public Result register(@RequestBody User user) {
        if (userService.register(user)) {
            return new Result(true, "注册成功");
        } else {
            return new Result(false, "注册失败");
        }
    }

    @PostMapping("/login")
    public Result login(@RequestBody User user) {
        if (userService.login(user.getUsername(), user.getPassword())) {
            return new Result(true, "登录成功", "token");
        } else {
            return new Result(false, "用户名或密码错误");
        }
    }

    class Result {
        private boolean success;
        private String message;
        private Object data;

        public Result(boolean success, String message) {
            this.success = success;
            this.message = message;
        }

        public Result(boolean success, String message, Object data) {
            this.success = success;
            this.message = message;
            this.data = data;
        }

        // Getter 和 Setter 方法
    }
}

7. 配置文件

src/main/resources/application.properties 中配置数据库连接和 MyBatis:

properties 复制代码
spring.datasource.url=jdbc:mysql://localhost:3306/user_management
spring.datasource.username=root
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

mybatis.mapper-locations=classpath:mapper/*.xml

8. Spring 配置

创建 Spring 配置文件 spring-config.xml

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc
           http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="com.example.usermanagement"/>
    <mvc:annotation-driven/>

    <!-- 数据源配置 -->
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="url" value="${spring.datasource.url}"/>
        <property name="username" value="${spring.datasource.username}"/>
        <property name="password" value="${spring.datasource.password}"/>
        <property name="driverClassName" value="${spring.datasource.driver-class-name}"/>
    </bean>

    <!-- MyBatis SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath:mapper/*.xml"/>
    </bean>

    <!-- MyBatis Mapper 扫描 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.example.usermanagement.dao"/>
    </bean>
</beans>

9. Servlet 配置

web.xml 中配置 Servlet 和 Spring 上下文:

xml 复制代码
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" version="3.1">
    <display-name>User Management</display-name>

    <!-- Spring 上下文 -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring-config.xml</param-value>
    </context-param>

    <!-- Spring 监听器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

    <!-- Spring MVC DispatcherServlet -->
    <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring-config.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/api/*</url-pattern>
    </servlet-mapping>

    <!-- 跨域支持 -->
    <filter>
        <filter-name>corsFilter</filter-name>
        <filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
        <init-param>
            <param-name>cors.allowed.origins</param-name>
            <param-value>*</param-value>
        </init-param>
        <init-param>
            <param-name>cors.allowed.methods</param-name>
            <param-value>GET,POST,PUT,DELETE,OPTIONS</param-value>
        </init-param>
        <init-param>
            <param-name>cors.allowed.headers</param-name>
            <param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>corsFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

10. 部署到 Tomcat

  1. 将后端项目打包成 WAR 文件。
  2. 将 WAR 文件部署到 Tomcat 的 webapps 目录。
  3. 启动 Tomcat,访问项目。

总结

通过以上步骤,我们实现了一个基于 Vue 和 SSM 框架的前后端分离项目,完成了用户登录和注册功能。前端使用 Vue.js 构建了友好的用户界面,后端使用 SSM 框架提供了稳定的数据服务,并通过 Tomcat 进行部署。这种架构清晰、易于维护,适合现代 Web 开发的需求。

在实际开发中,还可以进一步优化,例如添加用户角色管理、密码加密、验证码等功能,以提高系统的安全性和用户体验。

相关推荐
asdfg12589631 小时前
JavaBean是什么?怎么理解?有什么用途?
java·开发语言
摇滚侠3 小时前
SpringMVC 入门到实战 文件上传 75-77
java·后端·spring·maven·intellij-idea
GIS数据转换器3 小时前
城市排水生命线安全运行监测平台深度解析
java·运维·人工智能·python·安全·数据挖掘·无人机
代码不加糖4 小时前
js中不会冒泡的事件有哪些?
前端·javascript·vue.js
华如锦4 小时前
面了很多 Java转AI Agent方向,一些面试题总结
java·开发语言·人工智能·python·ai
睡不醒男孩0308234 小时前
CLup 6.x 版本中针对StarRocks 存算一体集群的完整操作手册
java·服务器·网络·clup
懂懂tty4 小时前
Vue2与Vue3之间API差异
前端·javascript·vue.js
程序员黑豆4 小时前
Java中怎么实现字符串拼接呢【AI全栈开发】
java
老毛肚4 小时前
软件测试期末考试
vue.js