【超详细前后端项目搭建】前端vue3+ts项目(引入ElementPlus、Axios)、后端springboot搭建(创建接口操作mysql数据库)实现前后端联调

前端 0

目录

  • 前言
  • 一、前端项目
    • 1、使用vue脚手架创建项目
      • 1.1检查vue版本
      • 1.2 使用vue脚手架创建项目
    • 2、删除项目多余文件,修改配置项目
      • 2.1、删除以下文件
      • 2.1、在views下创建index文件
      • 2.2、修改router/index.ts路由文件:
      • 2.3、修改App.vue文件:
      • 2.4、初始化页面样式以及清除浮动
    • 3、引入ElementPlus 组件库
      • 3.1、导入依赖包
        • 第一种:全局挂载ElementPlus,在main.js中添加
        • 第一种:按需导入组件
      • 在页面中使用ElementPlus组件
    • 3、创建登录页面
    • 4、封装并使用 Axios
      • 4.1、安装Axios
      • 4.2、安装NProgress顶部进度条
      • 4.3、封装请求拦截
      • 4.4、前端设置跨域
      • 4.5、配置接口api
      • 4.6、将http请求全局封装
  • 二、后端项目
    • 1、检查JDK和maven的安装版本
    • 2、创建springboot项目
    • 3、创建springboot项目成功
    • 4、配置maven和maven库
    • 5、加载maven库
    • 6、创建application.yml
    • 7、运行项目
    • 8、新建WebConfig文件处理跨域
    • 9、使用idea连接mysql
    • 10、在pom文件添加lombok依赖
    • 11、创建bean文件夹,用于放置实体对象
    • 12、查看构造成功成功的实体对象
    • 13、创建controller接口
    • 14、创建dao接口
    • 15、创建mapper映射文件
  • 三、测试前后端功能
    • 1、前端页面接口请求
    • 2、后端控制台日志打印


前言

本项目为简易的全栈项目,其中前端项目使用到了vue3、ts、Element Plus、axios等技术栈;后端项目使用到了springboot、jdbc、mysql、maven等技术


一、前端项目

1、使用vue脚手架创建项目

1.1检查vue版本

输入命令vue -V(V要大写),版本需要在4.5.1之后

1

1.2 使用vue脚手架创建项目

1、使用命令vue create vue3-element-demo 创建Vue项目。
2、通过上下键选择,选择 Manually select features,按回车,手动进行配置。
在这里插入图片描述
3、通过上下键选择,通过空格键选中(使用Babel,TypeScript,Router、Vuex、CSS Pre-processors、Linter / Formatter),按回车
在这里插入图片描述

4、选择vue3按回车
在这里插入图片描述
5、是否使用 Class 风格装饰器,此处输入【y】,然后回车确认;
在这里插入图片描述
6、Babel 和 TS 是否一起使用,用于现代模式、自动检测的 polyfills 和转译 JSX,此处输入【y】,然后回车确认;
在这里插入图片描述
7、是否使用history路由模式,此处输入【n】,即使用默认的 hash 模式,然后回车确认;
在这里插入图片描述
8、选择 CSS 预处理器,按上下方向键来选择,笔者习惯了 Less,然后回车确认;
在这里插入图片描述
9、选择第一个ESLint with error prevention only(仅具有错误预防功能的ESLint)
在这里插入图片描述
在这里插入图片描述
10、Babel、ESLint 等插件的配置是单独的文件进行配置,还是都在 package.json 文件里面?此处输选择 package.json 咯,并不想太多零散的配置文件,然后回车确认;
在这里插入图片描述
11、是否保存当前创建 Vue3 项目的特性配置,下次再创建 Vue 项目的时候,可以选择该特性,然后回车确认即可创建完成。这个可以不用保存,输入【n】,然后回车确认;
在这里插入图片描述12、项目创建中;
在这里插入图片描述
项目创建成功:
在这里插入图片描述
在这里插入图片描述
运行项目
在这里插入图片描述
在这里插入图片描述

2、删除项目多余文件,修改配置项目

2.1、删除以下文件

在这里插入图片描述

2.1、在views下创建index文件

在这里插入图片描述

<template>    <div>我的首页</div></template>  <script lang="ts">  export default {    name: 'Index'  }</script><style scoped></style>

2.2、修改router/index.ts路由文件:

在这里插入图片描述
编译时会有报错:
vue eslint报错:Component name “index“ should always be multi-word.eslintvue/multi-word-component-names
在这里插入图片描述
原因:除了根组件(App.vue)外,自定义组件名称应该由多单词组成,防止和html标签冲突。
解决方法,关闭eslint校验,重新编译就正常了
lintOnSave: false

在这里插入图片描述

2.3、修改App.vue文件:

在这里插入图片描述

<template>  <div id="app">    <router-view/>  </div></template><style lang="less">html,body,#app {  width: 100%;  height: 100%;}</style>

运行效果:
在这里插入图片描述

2.4、初始化页面样式以及清除浮动

新建css/resset.css文件,并在index.html文件中引入,初始化样式
在这里插入图片描述

/** * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/) * http://cssreset.com */  html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed,  figure, figcaption, footer, header, hgroup,  menu, nav, output, ruby, section, summary, time, mark, audio, video{   margin: 0;   padding: 0;   border: 0;   font-size: 100%;   font: inherit;   font-weight: normal;   vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure,  footer, header, hgroup, menu, nav, section{   display: block; } ol, ul, li{   list-style: none; } blockquote, q{   quotes: none; } blockquote:before, blockquote:after, q:before, q:after{   content: '';   content: none; } table{   border-collapse: collapse;   border-spacing: 0; }   /* custom */ a{   color: #7e8c8d;   text-decoration: none;   -webkit-backface-visibility: hidden; } ::-webkit-scrollbar{   width: 5px;   height: 5px; } ::-webkit-scrollbar-track-piece{   background-color: rgba(0, 0, 0, 0.2);   -webkit-border-radius: 6px; } ::-webkit-scrollbar-thumb:vertical{   height: 5px;   background-color: rgba(125, 125, 125, 0.7);   -webkit-border-radius: 6px; } ::-webkit-scrollbar-thumb:horizontal{   width: 5px;   background-color: rgba(125, 125, 125, 0.7);   -webkit-border-radius: 6px; } html, body{   width: 100%;   font-family: "Arial", "Microsoft YaHei", "黑体", "宋体", "微软雅黑", sans-serif; } body{   line-height: 1;   -webkit-text-size-adjust: none;   -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } html{   overflow-y: scroll; }   /*清除浮动*/ .clearfix:before, .clearfix:after{   content: " ";   display: inline-block;   height: 0;   clear: both;   visibility: hidden; } .clearfix{   *zoom: 1; }   /*隐藏*/ .dn{   display: none; }

index.html中引用:
在这里插入图片描述

3、引入ElementPlus 组件库

3.1、导入依赖包

npm i element-plus -D
在这里插入图片描述

第一种:全局挂载ElementPlus,在main.js中添加

在这里插入图片描述

第一种:按需导入组件

vue.config.js中引入(按需导入方式),添加如下配置
在这里插入图片描述

const { defineConfig } = require('@vue/cli-service');const AutoImport = require('unplugin-auto-import/webpack');const Components = require('unplugin-vue-components/webpack');const { ElementPlusResolver } = require('unplugin-vue-components/resolvers');module.exports = defineConfig({  transpileDependencies: true,  //关闭eslint校验  lintOnSave: false,  configureWebpack: {    plugins: [      AutoImport({        resolvers: [ElementPlusResolver()],      }),      Components({        resolvers: [ElementPlusResolver()],      }),    ],  }})

在页面中使用ElementPlus组件

在这里插入图片描述
效果:
在这里插入图片描述

3、创建登录页面

在view下新建Login.vue文件

在这里插入图片描述

<template>    <div class="container" :class="{ 'sign-up-mode': signUpMode }">      <!-- form表单容器 -->      <div class="form-container">        <div class="signin-signup">          <!-- 登录 -->            <el-form            ref="ruleFormRef"            :model="loginUser"            :rules="rules"            label-width="100px"            class="login-form sign-in-form"            >            <el-form-item label="邮箱" prop="email">                <el-input v-model="loginUser.email" placeholder="Enter Email..." />            </el-form-item>            <el-form-item label="密码" prop="password">                <el-input                v-model="loginUser.password"                type="password"                placeholder="Enter Password..."                />            </el-form-item>            <el-form-item>                <el-button type="primary" class="submit-btn" @click="submitForm(ruleFormRef)">提交</el-button>            </el-form-item>            <!-- 找回密码 -->            <el-form-item>                <p class="tiparea">忘记密码<a>立即找回</a></p>            </el-form-item>            </el-form>        </div>      </div>      <!-- 左右切换动画 -->      <div class="panels-container">        <div class="panel left-panel">          <div class="content">            <h3>Row,row,row your boat</h3>            <p>Gentlely down the stream</p>            <button @click="signUpMode = !signUpMode" class="btn transparent">              注册            </button>          </div>        </div>        <div class="panel right-panel">          <div class="content">            <h3>Merrily,merrily,merrily,merrily,</h3>            <p>Life is but a dream</p>            <button @click="signUpMode = !signUpMode" class="btn transparent">              登录            </button>          </div>        </div>      </div>    </div>  </template>  <script lang="ts" setup>  import { ref, reactive, toRefs, getCurrentInstance } from 'vue'  import type { FormInstance, FormRules } from 'element-plus'  // Vue3语法糖  // 通过解构getCurrentInstance,获取this,这里的this就是ctx  // const { ctx } = getCurrentInstance()  const { proxy } = getCurrentInstance()  // 登录/注册模式  const signUpMode = ref(false)  const ruleFormRef = ref<FormInstance>()  // 登录表单  const loginUser = reactive({    email: '',    password: ''  })  // 校验规则  const rules = reactive({    email: [          {            required: true,            type: 'email',            message: 'email格式错误',            trigger: 'blur'          }        ],        password: [          { required: true, message: '密码不得为空', trigger: 'blur' },          { min: 6, max: 30, message: '密码长度必须在6到30之间', trigger: 'blur' }        ]      })      // 触发登录方法      const submitForm  = (formEl: FormInstance | undefined) => {        if(!formEl!) return        formEl.validate((valid) => {          if (valid) {            console.log('submit!')            const data = proxy.$http.getUserPassword(loginUser)            console.log('data', data)          } else {            console.log('error submit!')            return false          }        })      }  </script>  <style scoped>  .container {    position: relative;    width: 100%;    min-height: 100vh;    background-color: #fff;    overflow: hidden;  }  .form-container {    position: absolute;    left: 0;    top: 0;    width: 100%;    height: 100%;  }  .signin-signup {    position: relative;    top: 50%;    left: 75%;    transform: translate(-50%, -50%);    width: 44%;    transition: 1s 0.7s ease-in-out;    display: grid;    grid-template-columns: 1fr;    z-index: 5;  }  /* 左右切换动画 */  .social-text {    padding: 0.7rem 0;    font-size: 1rem;  }  .social-media {    display: flex;    justify-content: center;  }  .social-icon {    height: 46px;    width: 46px;    display: flex;    justify-content: center;    align-items: center;    margin: 0 0.45rem;    color: #333;    border-radius: 50%;    border: 1px solid #333;    text-decoration: none;    font-size: 1.1rem;    transition: 0.3s;  }  .social-icon:hover {    color: #4481eb;    border-color: #4481eb;  }  .btn {    width: 150px;    background-color: #5995fd;    border: none;    outline: none;    height: 49px;    border-radius: 49px;    color: #fff;    text-transform: uppercase;    font-weight: 600;    margin: 10px 0;    cursor: pointer;    transition: 0.5s;  }  .btn:hover {    background-color: #4d84e2;  }  .panels-container {    position: absolute;    height: 100%;    width: 100%;    top: 0;    left: 0;    display: grid;    grid-template-columns: repeat(2, 1fr);  }  .container:before {    content: '';    position: absolute;    height: 2000px;    width: 2000px;    top: -10%;    right: 48%;    transform: translateY(-50%);    background-image: linear-gradient(-45deg, #4481eb 0%, #04befe 100%);    transition: 1.8s ease-in-out;    border-radius: 50%;    z-index: 6;  }  .image {    width: 100%;    transition: transform 1.1s ease-in-out;    transition-delay: 0.4s;  }  .panel {    display: flex;    flex-direction: column;    align-items: flex-end;    justify-content: space-around;    text-align: center;    z-index: 6;  }  .left-panel {    pointer-events: all;    padding: 3rem 17% 2rem 12%;  }  .right-panel {    pointer-events: none;    padding: 3rem 12% 2rem 17%;  }  .panel .content {    color: #fff;    transition: transform 0.9s ease-in-out;    transition-delay: 0.6s;  }  .panel h3 {    font-weight: 600;    line-height: 1;    font-size: 1.5rem;  }  .panel p {    font-size: 0.95rem;    padding: 0.7rem 0;  }  .btn.transparent {    margin: 0;    background: none;    border: 2px solid #fff;    width: 130px;    height: 41px;    font-weight: 600;    font-size: 0.8rem;  }  .right-panel .image,  .right-panel .content {    transform: translateX(800px);  }  /* ANIMATION */  .container.sign-up-mode:before {    transform: translate(100%, -50%);    right: 52%;  }  .container.sign-up-mode .left-panel .image,  .container.sign-up-mode .left-panel .content {    transform: translateX(-800px);  }  .container.sign-up-mode .signin-signup {    left: 25%;  }  .container.sign-up-mode form.sign-up-form {    opacity: 1;    z-index: 2;  }  .container.sign-up-mode form.sign-in-form {    opacity: 0;    z-index: 1;  }  .container.sign-up-mode .right-panel .image,  .container.sign-up-mode .right-panel .content {    transform: translateX(0%);  }  .container.sign-up-mode .left-panel {    pointer-events: none;  }  .container.sign-up-mode .right-panel {    pointer-events: all;  }  @media (max-width: 870px) {    .container {      min-height: 800px;      height: 100vh;    }    .signin-signup {      width: 100%;      top: 95%;      transform: translate(-50%, -100%);      transition: 1s 0.8s ease-in-out;    }    .signin-signup,    .container.sign-up-mode .signin-signup {      left: 50%;    }    .panels-container {      grid-template-columns: 1fr;      grid-template-rows: 1fr 2fr 1fr;    }    .panel {      flex-direction: row;      justify-content: space-around;      align-items: center;      padding: 2.5rem 8%;      grid-column: 1 / 2;    }    .right-panel {      grid-row: 3 / 4;    }    .left-panel {      grid-row: 1 / 2;    }    .image {      width: 200px;      transition: transform 0.9s ease-in-out;      transition-delay: 0.6s;    }    .panel .content {      padding-right: 15%;      transition: transform 0.9s ease-in-out;      transition-delay: 0.8s;    }    .panel h3 {      font-size: 1.2rem;    }    .panel p {      font-size: 0.7rem;      padding: 0.5rem 0;    }    .btn.transparent {      width: 110px;      height: 35px;      font-size: 0.7rem;    }    .container:before {      width: 1500px;      height: 1500px;      transform: translateX(-50%);      left: 30%;      bottom: 68%;      right: initial;      top: initial;      transition: 2s ease-in-out;    }    .container.sign-up-mode:before {      transform: translate(-50%, 100%);      bottom: 32%;      right: initial;    }    .container.sign-up-mode .left-panel .image,    .container.sign-up-mode .left-panel .content {      transform: translateY(-300px);    }    .container.sign-up-mode .right-panel .image,    .container.sign-up-mode .right-panel .content {      transform: translateY(0px);    }    .right-panel .image,    .right-panel .content {      transform: translateY(300px);    }    .container.sign-up-mode .signin-signup {      top: 5%;      transform: translate(-50%, 0);    }  }  @media (max-width: 570px) {    form {      padding: 0 1.5rem;    }    .image {      display: none;    }    .panel .content {      padding: 0.5rem 1rem;    }    .container {      padding: 1.5rem;    }    .container:before {      bottom: 72%;      left: 50%;    }    .container.sign-up-mode:before {      bottom: 28%;      left: 50%;    }  }  /* 控制login & register显示 */  form {    padding: 0rem 5rem;    transition: all 0.2s 0.7s;    overflow: hidden;  }  form.sign-in-form {    z-index: 2;  }  form.sign-up-form {    opacity: 0;    z-index: 1;  }  /* register */  .loginForm,  .registerForm {    margin-top: 20px;    background-color: #fff;    padding: 20px 40px 20px 20px;    border-radius: 5px;    box-shadow: 0px 5px 10px #cccc;  }  .submit-btn {    width: 100%;  }  .tiparea {    text-align: right;    font-size: 12px;    color: #333;    width: 100%;  }  .tiparea a {    color: #409eff;  }  </style>

在这里插入图片描述
在这里插入图片描述

4、封装并使用 Axios

4.1、安装Axios

npm i axios
在这里插入图片描述

4.2、安装NProgress顶部进度条

npm i --save-dev @types/nprogress
在这里插入图片描述

4.3、封装请求拦截

在 src 目录新建 utils 文件夹,再新建 requestUtil.ts 文件,写上以下代码
在这里插入图片描述

import axios from 'axios'import Nprogress from 'nprogress'import 'nprogress/nprogress.css'import { ElMessage } from 'element-plus'const http = axios.create({  baseURL: 'http://localhost:9000',  timeout: 300 * 1000, // 请求超时时间设置为300秒})const NETWORK_ERROR = '网络错误,请联系开发人员'/** * 请求拦截器 */http.interceptors.request.use((req) => {  console.log('请求拦截器 =>', req)  Nprogress.start()  return req;}, (error) => {  Nprogress.done()  return Promise.reject(error);});/** * 响应拦截器 */http.interceptors.response.use(function (res) {  console.log('响应拦截器 =>', res)  Nprogress.done()  if (res.status == 200) {    return res.data  } else {    ElMessage.error((NETWORK_ERROR))    return Promise.reject(NETWORK_ERROR)  }});export default http

4.4、前端设置跨域

在vue.config.js中配置如下代码:
在这里插入图片描述

const { defineConfig } = require('@vue/cli-service');// const AutoImport = require('unplugin-auto-import/webpack');// const Components = require('unplugin-vue-components/webpack');// const { ElementPlusResolver } = require('unplugin-vue-components/resolvers');module.exports = defineConfig({  transpileDependencies: true,  //关闭eslint校验  lintOnSave: false,  // ElementPlus按需导入方式  // configureWebpack: {  //   plugins: [  //     AutoImport({  //       resolvers: [ElementPlusResolver()],  //     }),  //     Components({  //       resolvers: [ElementPlusResolver()],  //     }),  //   ],  // }  devServer: {    open: true,    host: 'localhost',    port: 8080,    https: false,    // 设置跨域    proxy: {      '/api': {        target: 'http://localhost:9000',        ws: true,        changeOrigin: true,        pathRewrite: {          '^api': ''        }      }    }  }})

4.5、配置接口api

在src目录下创建api文件夹,里面创建index.ts
在这里插入图片描述

import http from '@/utils/requestUtils' export default {  /**   * 根据用户邮箱、密码查询用户信息   */  getUserPassword(data: any) {    return http.post(      '/api/getUserPassword',      data,      {        headers: {          'Content-Type': 'application/json'        },      }    )  },   /**   * 保存用户信息   */  saveUser(data: any) {    return http.post(      '/api/saveUser',      data,      {        headers: {          'Content-Type': 'application/json'        },      }    )  },}

4.6、将http请求全局封装

在 main.ts 文件引入HTTP请求工具并配置为全局方法
在这里插入图片描述

import { createApp } from 'vue'import App from './App.vue'import router from './router'import store from './store'import ElementPlus from 'element-plus'import 'element-plus/dist/index.css'import axios from 'axios'import apiServe from '@/api'const app = createApp(App)app.use(store)app.use(router)app.use(ElementPlus)app.mount('#app')app.config.globalProperties.$http = apiServeapp.config.globalProperties.$axios = axios

二、后端项目

1、检查JDK和maven的安装版本

在cmd输入 java -version
和mvn -v检查对应的安装情况
在这里插入图片描述

2、创建springboot项目

通过idea的spring initializr创建工程,不选择maven而是选择spring initializr快捷创建。然后去勾选相关依赖。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3、创建springboot项目成功

项目创建成功

在这里插入图片描述

4、配置maven和maven库

配置本地maven库
在这里插入图片描述

5、加载maven库

在这里插入图片描述

6、创建application.yml

在resources下面新建application.yml,并配置数据库名,密码,以及端口,端口尽量不要使用8080,避免和前端端口相同了

在这里插入图片描述
注释掉另外一个配置
在这里插入图片描述

# mysqlspring:  datasource:    #MySQL配置    driverClassName:  com.mysql.cj.jdbc.Driver    url: jdbc:mysql://localhost:3306/easyproject?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC    #数据库名和密码    username: root    password: 920724mybatis:  mapper-locations: classpath:mapper/*.xml  type-aliases-package: com.example.demo.modelserver:  port: 9000

7、运行项目

在这里插入图片描述
项目运行成功,端口9000
在这里插入图片描述
在这里插入图片描述

8、新建WebConfig文件处理跨域

创建utils文件夹,在utils文件夹下创建WebConfig,并添加以下配置
在这里插入图片描述

package com.springboot.userlogin.springbootdemo.utils;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.CorsRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;// 使用注解说明是全局配置类@Configurationpublic class WebConfig extends WebMvcConfigurerAdapter { // 继承跨域请求的类    @Override    public void addCorsMappings(CorsRegistry registry) { // 跨域处理的方法        registry.addMapping("/**") // 任意访问都允许跨域                .allowedOrigins("http://localhost:8080", "null") // 跨域来源                .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") // 跨域请求类型                .maxAge(3600) // 超时时间                .allowCredentials(true); // 允许携带信息    }}

alt+insert快捷键可以弹出
在这里插入图片描述

9、使用idea连接mysql

mysql安装配置方法可以参照我写的另外一个文档:
https://blog.csdn.net/m0_47791238/article/details/134811414?spm=1001.2014.3001.5501

在这里插入图片描述
在这里插入图片描述
输入mysql用户名和密码:
在这里插入图片描述
在这里插入图片描述

10、在pom文件添加lombok依赖

目的:为了使用@Data注解
在这里插入图片描述

<dependency>      <groupId>org.projectlombok</groupId>      <artifactId>lombok</artifactId>      <version>1.18.24</version> </dependency>

11、创建bean文件夹,用于放置实体对象

在项目中创建bean文件夹,新建user实体类,使用Data注解,创建构造方法和get/set方法
在这里插入图片描述

package com.springboot.userlogin.springbootdemo.bean;import lombok.Data;@Datapublic class User {    private int id;    private String username;    private String password;    private String email;    private String role;    private boolean state;//    public User() {//    }//    public User(String username, String password, String email, String role, boolean state) {//        this.username = username;//        this.password = password;//        this.email = email;//        this.role = role;//        this.state = state;//    }////    public int getId() {//        return id;//    }////    public String getUsername() {//        return username;//    }////    public String getPassword() {//        return password;//    }////    public String getEmail() {//        return email;//    }////    public String getRole() {//        return role;//    }////    public boolean getState() {//        return state;//    }////    public void setId(int id) {//        this.id = id;//    }////    public void setUsername(String username) {//        this.username = username;//    }////    public void setPassword(String password) {//        this.password = password;//    }////    public void setEmail(String email) {//        this.email = email;//    }////    public void setRole(String role) {//        this.role = role;//    }////    public void setState(boolean state) {//        this.state = state;//    }}

12、查看构造成功成功的实体对象

快捷键 alt + 7
在这里插入图片描述

13、创建controller接口

在这里插入图片描述

import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RestController;@RestControllerpublic class LoginController {    @Autowired    UserDao userDao;    @PostMapping("/api/getUserPassword") // @RequestMapping注解创建接口    public String userLogin(@RequestBody User user) { // @RequestBody注解方便找到user实体        System.out.println("User : " + user);        String str = "error";        int count = userDao.getUserByMassage(user.getEmail(), user.getPassword());        if (count > 0) {            str = "ok";        }        return str;    }}

14、创建dao接口

在这里插入图片描述

package com.springboot.userlogin.springbootdemo.dao;import org.apache.ibatis.annotations.Mapper;import org.apache.ibatis.annotations.Param;import org.springframework.stereotype.Repository;@Repository@Mapperpublic interface UserDao {    int getUserByMassage(@Param("email") String email, @Param("password") String password);}

15、创建mapper映射文件

在resources下面创建mapper文件夹,用于存放数据库的映射文件
在mapper文件夹下新建UserMapper.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"><!--对应dao层接口文件的目录--><mapper namespace="com.springboot.userlogin.springbootdemo.dao.UserDao">    <!--  id值为UserDao接口方法名; -->    <select id="getUserByMassage" resultType="java.lang.Integer">       	SELECT count(id) FROM easyUser       	WHERE email=#{email} AND password=#{password}    </select></mapper>

三、测试前后端功能

1、前端页面接口请求

在这里插入图片描述

2、后端控制台日志打印

在这里插入图片描述

也许您对下面的内容还感兴趣: