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

smileAgain-lg 2024-06-27 08:03:02 阅读 85

目录

前言一、前端项目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、封装并使用 Axios4.1、安装Axios4.2、安装NProgress顶部进度条4.3、封装请求拦截4.4、前端设置跨域4.5、配置接口api4.6、将http请求全局封装

二、后端项目1、检查JDK和maven的安装版本2、创建springboot项目3、创建springboot项目成功4、配置maven和maven库5、加载maven库6、创建application.yml7、运行项目8、新建WebConfig文件处理跨域9、使用idea连接mysql10、在pom文件添加lombok依赖11、创建bean文件夹,用于放置实体对象12、查看构造成功成功的实体对象13、创建controller接口14、创建dao接口15、创建mapper映射文件

三、测试前后端功能1、前端页面接口请求2、后端控制台日志打印


前言

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


附上开源代码gitee地址:

前端代码:https://gitee.com/smileagain-lg/vue3-element-demo.git

后端代码:https://gitee.com/smileagain-lg/spring-boot-demo.git

一、前端项目

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 = apiServe

app.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,避免和前端端口相同了

在这里插入图片描述

注释掉另外一个配置

在这里插入图片描述

# mysql

spring:

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: 920724

mybatis:

mapper-locations: classpath:mapper/*.xml

type-aliases-package: com.example.demo.model

server:

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;

// 使用注解说明是全局配置类

@Configuration

public 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;

@Data

public 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;

@RestController

public 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

@Mapper

public 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、后端控制台日志打印

在这里插入图片描述



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。