【超详细前后端项目搭建】前端vue3+ts项目(引入ElementPlus、Axios)、后 ...

用户云卷云舒  论坛元老 | 2024-6-28 11:44:51 | 来自手机 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1031|帖子 1031|积分 3093


前言

本项目为简易的全栈项目,其中前端项目利用到了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.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文件


  1. <template>
  2.     <div>我的首页</div>
  3. </template>
  4.   
  5. <script lang="ts">
  6.   export default {
  7.     name: 'Index'
  8.   }
  9. </script>
  10. <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文件:


  1. <template>
  2.   <div id="app">
  3.     <router-view/>
  4.   </div>
  5. </template>
  6. <style lang="less">
  7. html,
  8. body,
  9. #app {
  10.   width: 100%;
  11.   height: 100%;
  12. }
  13. </style>
复制代码
运行结果:

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

新建css/resset.css文件,并在index.html文件中引入,初始化样式

  1. /**
  2. * Eric Meyer's Reset CSS v2.0 (http://meyerweb.com/eric/tools/css/reset/)
  3. * http://cssreset.com
  4. */
  5. html, body, div, span, applet, object, iframe,
  6. h1, h2, h3, h4, h5, h6, p, blockquote, pre,
  7. a, abbr, acronym, address, big, cite, code,
  8. del, dfn, em, img, ins, kbd, q, s, samp,
  9. small, strike, strong, sub, sup, tt, var,
  10. b, u, i, center,
  11. dl, dt, dd, ol, ul, li,
  12. fieldset, form, label, legend,
  13. table, caption, tbody, tfoot, thead, tr, th, td,
  14. article, aside, canvas, details, embed,
  15. figure, figcaption, footer, header, hgroup,
  16. menu, nav, output, ruby, section, summary,
  17. time, mark, audio, video{
  18.    margin: 0;
  19.    padding: 0;
  20.    border: 0;
  21.    font-size: 100%;
  22.    font: inherit;
  23.    font-weight: normal;
  24.    vertical-align: baseline;
  25. }
  26. /* HTML5 display-role reset for older browsers */
  27. article, aside, details, figcaption, figure,
  28. footer, header, hgroup, menu, nav, section{
  29.    display: block;
  30. }
  31. ol, ul, li{
  32.    list-style: none;
  33. }
  34. blockquote, q{
  35.    quotes: none;
  36. }
  37. blockquote:before, blockquote:after,
  38. q:before, q:after{
  39.    content: '';
  40.    content: none;
  41. }
  42. table{
  43.    border-collapse: collapse;
  44.    border-spacing: 0;
  45. }
  46.   
  47. /* custom */
  48. a{
  49.    color: #7e8c8d;
  50.    text-decoration: none;
  51.    -webkit-backface-visibility: hidden;
  52. }
  53. ::-webkit-scrollbar{
  54.    width: 5px;
  55.    height: 5px;
  56. }
  57. ::-webkit-scrollbar-track-piece{
  58.    background-color: rgba(0, 0, 0, 0.2);
  59.    -webkit-border-radius: 6px;
  60. }
  61. ::-webkit-scrollbar-thumb:vertical{
  62.    height: 5px;
  63.    background-color: rgba(125, 125, 125, 0.7);
  64.    -webkit-border-radius: 6px;
  65. }
  66. ::-webkit-scrollbar-thumb:horizontal{
  67.    width: 5px;
  68.    background-color: rgba(125, 125, 125, 0.7);
  69.    -webkit-border-radius: 6px;
  70. }
  71. html, body{
  72.    width: 100%;
  73.    font-family: "Arial", "Microsoft YaHei", "黑体", "宋体", "微软雅黑", sans-serif;
  74. }
  75. body{
  76.    line-height: 1;
  77.    -webkit-text-size-adjust: none;
  78.    -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
  79. }
  80. html{
  81.    overflow-y: scroll;
  82. }
  83.   
  84. /*清除浮动*/
  85. .clearfix:before,
  86. .clearfix:after{
  87.    content: " ";
  88.    display: inline-block;
  89.    height: 0;
  90.    clear: both;
  91.    visibility: hidden;
  92. }
  93. .clearfix{
  94.    *zoom: 1;
  95. }
  96.   
  97. /*隐藏*/
  98. .dn{
  99.    display: none;
  100. }
复制代码
index.html中引用:

3、引入ElementPlus 组件库

3.1、导入依赖包

npm i element-plus -D

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


第一种:按需导入组件

vue.config.js中引入(按需导入方式),添加如下配置

  1. const { defineConfig } = require('@vue/cli-service');
  2. const AutoImport = require('unplugin-auto-import/webpack');
  3. const Components = require('unplugin-vue-components/webpack');
  4. const { ElementPlusResolver } = require('unplugin-vue-components/resolvers');
  5. module.exports = defineConfig({
  6.   transpileDependencies: true,
  7.   //关闭eslint校验
  8.   lintOnSave: false,
  9.   configureWebpack: {
  10.     plugins: [
  11.       AutoImport({
  12.         resolvers: [ElementPlusResolver()],
  13.       }),
  14.       Components({
  15.         resolvers: [ElementPlusResolver()],
  16.       }),
  17.     ],
  18.   }
  19. })
复制代码
在页面中利用ElementPlus组件


结果:

3、创建登录页面

在view下新建Login.vue文件

  1. <template>
  2.     <div class="container" :class="{ 'sign-up-mode': signUpMode }">
  3.       <!-- form表单容器 -->
  4.       <div class="form-container">
  5.         <div class="signin-signup">
  6.           <!-- 登录 -->
  7.             <el-form
  8.             ref="ruleFormRef"
  9.             :model="loginUser"
  10.             :rules="rules"
  11.             label-width="100px"
  12.             class="login-form sign-in-form"
  13.             >
  14.             <el-form-item label="邮箱" prop="email">
  15.                 <el-input v-model="loginUser.email" placeholder="Enter Email..." />
  16.             </el-form-item>
  17.             <el-form-item label="密码" prop="password">
  18.                 <el-input
  19.                 v-model="loginUser.password"
  20.                 type="password"
  21.                 placeholder="Enter Password..."
  22.                 />
  23.             </el-form-item>
  24.             <el-form-item>
  25.                 <el-button type="primary" class="submit-btn" @click="submitForm(ruleFormRef)">提交</el-button>
  26.             </el-form-item>
  27.             <!-- 找回密码 -->
  28.             <el-form-item>
  29.                 <p class="tiparea">忘记密码<a>立即找回</a></p>
  30.             </el-form-item>
  31.             </el-form>
  32.         </div>
  33.       </div>
  34.       <!-- 左右切换动画 -->
  35.       <div class="panels-container">
  36.         <div class="panel left-panel">
  37.           <div class="content">
  38.             <h3>Row,row,row your boat</h3>
  39.             <p>Gentlely down the stream</p>
  40.             <button @click="signUpMode = !signUpMode" class="btn transparent">
  41.               注册
  42.             </button>
  43.           </div>
  44.         </div>
  45.         <div class="panel right-panel">
  46.           <div class="content">
  47.             <h3>Merrily,merrily,merrily,merrily,</h3>
  48.             <p>Life is but a dream</p>
  49.             <button @click="signUpMode = !signUpMode" class="btn transparent">
  50.               登录
  51.             </button>
  52.           </div>
  53.         </div>
  54.       </div>
  55.     </div>
  56.   </template>
  57.   <script lang="ts" setup>
  58.   import { ref, reactive, toRefs, getCurrentInstance } from 'vue'
  59.   import type { FormInstance, FormRules } from 'element-plus'
  60.   // Vue3语法糖
  61.   // 通过解构getCurrentInstance,获取this,这里的this就是ctx
  62.   // const { ctx } = getCurrentInstance()
  63.   const { proxy } = getCurrentInstance()
  64.   // 登录/注册模式
  65.   const signUpMode = ref(false)
  66.   const ruleFormRef = ref<FormInstance>()
  67.   // 登录表单
  68.   const loginUser = reactive({
  69.     email: '',
  70.     password: ''
  71.   })
  72.   // 校验规则
  73.   const rules = reactive({
  74.     email: [
  75.           {
  76.             required: true,
  77.             type: 'email',
  78.             message: 'email格式错误',
  79.             trigger: 'blur'
  80.           }
  81.         ],
  82.         password: [
  83.           { required: true, message: '密码不得为空', trigger: 'blur' },
  84.           { min: 6, max: 30, message: '密码长度必须在6到30之间', trigger: 'blur' }
  85.         ]
  86.       })
  87.       // 触发登录方法
  88.       const submitForm  = (formEl: FormInstance | undefined) => {
  89.         if(!formEl!) return
  90.         formEl.validate((valid) => {
  91.           if (valid) {
  92.             console.log('submit!')
  93.             const data = proxy.$http.getUserPassword(loginUser)
  94.             console.log('data', data)
  95.           } else {
  96.             console.log('error submit!')
  97.             return false
  98.           }
  99.         })
  100.       }
  101.   </script>
  102.   <style scoped>
  103.   .container {
  104.     position: relative;
  105.     width: 100%;
  106.     min-height: 100vh;
  107.     background-color: #fff;
  108.     overflow: hidden;
  109.   }
  110.   .form-container {
  111.     position: absolute;
  112.     left: 0;
  113.     top: 0;
  114.     width: 100%;
  115.     height: 100%;
  116.   }
  117.   .signin-signup {
  118.     position: relative;
  119.     top: 50%;
  120.     left: 75%;
  121.     transform: translate(-50%, -50%);
  122.     width: 44%;
  123.     transition: 1s 0.7s ease-in-out;
  124.     display: grid;
  125.     grid-template-columns: 1fr;
  126.     z-index: 5;
  127.   }
  128.   /* 左右切换动画 */
  129.   .social-text {
  130.     padding: 0.7rem 0;
  131.     font-size: 1rem;
  132.   }
  133.   .social-media {
  134.     display: flex;
  135.     justify-content: center;
  136.   }
  137.   .social-icon {
  138.     height: 46px;
  139.     width: 46px;
  140.     display: flex;
  141.     justify-content: center;
  142.     align-items: center;
  143.     margin: 0 0.45rem;
  144.     color: #333;
  145.     border-radius: 50%;
  146.     border: 1px solid #333;
  147.     text-decoration: none;
  148.     font-size: 1.1rem;
  149.     transition: 0.3s;
  150.   }
  151.   .social-icon:hover {
  152.     color: #4481eb;
  153.     border-color: #4481eb;
  154.   }
  155.   .btn {
  156.     width: 150px;
  157.     background-color: #5995fd;
  158.     border: none;
  159.     outline: none;
  160.     height: 49px;
  161.     border-radius: 49px;
  162.     color: #fff;
  163.     text-transform: uppercase;
  164.     font-weight: 600;
  165.     margin: 10px 0;
  166.     cursor: pointer;
  167.     transition: 0.5s;
  168.   }
  169.   .btn:hover {
  170.     background-color: #4d84e2;
  171.   }
  172.   .panels-container {
  173.     position: absolute;
  174.     height: 100%;
  175.     width: 100%;
  176.     top: 0;
  177.     left: 0;
  178.     display: grid;
  179.     grid-template-columns: repeat(2, 1fr);
  180.   }
  181.   .container:before {
  182.     content: '';
  183.     position: absolute;
  184.     height: 2000px;
  185.     width: 2000px;
  186.     top: -10%;
  187.     right: 48%;
  188.     transform: translateY(-50%);
  189.     background-image: linear-gradient(-45deg, #4481eb 0%, #04befe 100%);
  190.     transition: 1.8s ease-in-out;
  191.     border-radius: 50%;
  192.     z-index: 6;
  193.   }
  194.   .image {
  195.     width: 100%;
  196.     transition: transform 1.1s ease-in-out;
  197.     transition-delay: 0.4s;
  198.   }
  199.   .panel {
  200.     display: flex;
  201.     flex-direction: column;
  202.     align-items: flex-end;
  203.     justify-content: space-around;
  204.     text-align: center;
  205.     z-index: 6;
  206.   }
  207.   .left-panel {
  208.     pointer-events: all;
  209.     padding: 3rem 17% 2rem 12%;
  210.   }
  211.   .right-panel {
  212.     pointer-events: none;
  213.     padding: 3rem 12% 2rem 17%;
  214.   }
  215.   .panel .content {
  216.     color: #fff;
  217.     transition: transform 0.9s ease-in-out;
  218.     transition-delay: 0.6s;
  219.   }
  220.   .panel h3 {
  221.     font-weight: 600;
  222.     line-height: 1;
  223.     font-size: 1.5rem;
  224.   }
  225.   .panel p {
  226.     font-size: 0.95rem;
  227.     padding: 0.7rem 0;
  228.   }
  229.   .btn.transparent {
  230.     margin: 0;
  231.     background: none;
  232.     border: 2px solid #fff;
  233.     width: 130px;
  234.     height: 41px;
  235.     font-weight: 600;
  236.     font-size: 0.8rem;
  237.   }
  238.   .right-panel .image,
  239.   .right-panel .content {
  240.     transform: translateX(800px);
  241.   }
  242.   /* ANIMATION */
  243.   .container.sign-up-mode:before {
  244.     transform: translate(100%, -50%);
  245.     right: 52%;
  246.   }
  247.   .container.sign-up-mode .left-panel .image,
  248.   .container.sign-up-mode .left-panel .content {
  249.     transform: translateX(-800px);
  250.   }
  251.   .container.sign-up-mode .signin-signup {
  252.     left: 25%;
  253.   }
  254.   .container.sign-up-mode form.sign-up-form {
  255.     opacity: 1;
  256.     z-index: 2;
  257.   }
  258.   .container.sign-up-mode form.sign-in-form {
  259.     opacity: 0;
  260.     z-index: 1;
  261.   }
  262.   .container.sign-up-mode .right-panel .image,
  263.   .container.sign-up-mode .right-panel .content {
  264.     transform: translateX(0%);
  265.   }
  266.   .container.sign-up-mode .left-panel {
  267.     pointer-events: none;
  268.   }
  269.   .container.sign-up-mode .right-panel {
  270.     pointer-events: all;
  271.   }
  272.   @media (max-width: 870px) {
  273.     .container {
  274.       min-height: 800px;
  275.       height: 100vh;
  276.     }
  277.     .signin-signup {
  278.       width: 100%;
  279.       top: 95%;
  280.       transform: translate(-50%, -100%);
  281.       transition: 1s 0.8s ease-in-out;
  282.     }
  283.     .signin-signup,
  284.     .container.sign-up-mode .signin-signup {
  285.       left: 50%;
  286.     }
  287.     .panels-container {
  288.       grid-template-columns: 1fr;
  289.       grid-template-rows: 1fr 2fr 1fr;
  290.     }
  291.     .panel {
  292.       flex-direction: row;
  293.       justify-content: space-around;
  294.       align-items: center;
  295.       padding: 2.5rem 8%;
  296.       grid-column: 1 / 2;
  297.     }
  298.     .right-panel {
  299.       grid-row: 3 / 4;
  300.     }
  301.     .left-panel {
  302.       grid-row: 1 / 2;
  303.     }
  304.     .image {
  305.       width: 200px;
  306.       transition: transform 0.9s ease-in-out;
  307.       transition-delay: 0.6s;
  308.     }
  309.     .panel .content {
  310.       padding-right: 15%;
  311.       transition: transform 0.9s ease-in-out;
  312.       transition-delay: 0.8s;
  313.     }
  314.     .panel h3 {
  315.       font-size: 1.2rem;
  316.     }
  317.     .panel p {
  318.       font-size: 0.7rem;
  319.       padding: 0.5rem 0;
  320.     }
  321.     .btn.transparent {
  322.       width: 110px;
  323.       height: 35px;
  324.       font-size: 0.7rem;
  325.     }
  326.     .container:before {
  327.       width: 1500px;
  328.       height: 1500px;
  329.       transform: translateX(-50%);
  330.       left: 30%;
  331.       bottom: 68%;
  332.       right: initial;
  333.       top: initial;
  334.       transition: 2s ease-in-out;
  335.     }
  336.     .container.sign-up-mode:before {
  337.       transform: translate(-50%, 100%);
  338.       bottom: 32%;
  339.       right: initial;
  340.     }
  341.     .container.sign-up-mode .left-panel .image,
  342.     .container.sign-up-mode .left-panel .content {
  343.       transform: translateY(-300px);
  344.     }
  345.     .container.sign-up-mode .right-panel .image,
  346.     .container.sign-up-mode .right-panel .content {
  347.       transform: translateY(0px);
  348.     }
  349.     .right-panel .image,
  350.     .right-panel .content {
  351.       transform: translateY(300px);
  352.     }
  353.     .container.sign-up-mode .signin-signup {
  354.       top: 5%;
  355.       transform: translate(-50%, 0);
  356.     }
  357.   }
  358.   @media (max-width: 570px) {
  359.     form {
  360.       padding: 0 1.5rem;
  361.     }
  362.     .image {
  363.       display: none;
  364.     }
  365.     .panel .content {
  366.       padding: 0.5rem 1rem;
  367.     }
  368.     .container {
  369.       padding: 1.5rem;
  370.     }
  371.     .container:before {
  372.       bottom: 72%;
  373.       left: 50%;
  374.     }
  375.     .container.sign-up-mode:before {
  376.       bottom: 28%;
  377.       left: 50%;
  378.     }
  379.   }
  380.   /* 控制login & register显示 */
  381.   form {
  382.     padding: 0rem 5rem;
  383.     transition: all 0.2s 0.7s;
  384.     overflow: hidden;
  385.   }
  386.   form.sign-in-form {
  387.     z-index: 2;
  388.   }
  389.   form.sign-up-form {
  390.     opacity: 0;
  391.     z-index: 1;
  392.   }
  393.   /* register */
  394.   .loginForm,
  395.   .registerForm {
  396.     margin-top: 20px;
  397.     background-color: #fff;
  398.     padding: 20px 40px 20px 20px;
  399.     border-radius: 5px;
  400.     box-shadow: 0px 5px 10px #cccc;
  401.   }
  402.   .submit-btn {
  403.     width: 100%;
  404.   }
  405.   .tiparea {
  406.     text-align: right;
  407.     font-size: 12px;
  408.     color: #333;
  409.     width: 100%;
  410.   }
  411.   .tiparea a {
  412.     color: #409eff;
  413.   }
  414.   </style>
复制代码


4、封装并利用 Axios

4.1、安装Axios

npm i axios

4.2、安装NProgress顶部进度条

npm i --save-dev @types/nprogress

4.3、封装请求拦截

在 src 目录新建 utils 文件夹,再新建 requestUtil.ts 文件,写上以下代码

  1. import axios from 'axios'
  2. import Nprogress from 'nprogress'
  3. import 'nprogress/nprogress.css'
  4. import { ElMessage } from 'element-plus'
  5. const http = axios.create({
  6.   baseURL: 'http://localhost:9000',
  7.   timeout: 300 * 1000, // 请求超时时间设置为300秒
  8. })
  9. const NETWORK_ERROR = '网络错误,请联系开发人员'
  10. /**
  11. * 请求拦截器
  12. */
  13. http.interceptors.request.use((req) => {
  14.   console.log('请求拦截器 =>', req)
  15.   Nprogress.start()
  16.   return req;
  17. }, (error) => {
  18.   Nprogress.done()
  19.   return Promise.reject(error);
  20. });
  21. /**
  22. * 响应拦截器
  23. */
  24. http.interceptors.response.use(function (res) {
  25.   console.log('响应拦截器 =>', res)
  26.   Nprogress.done()
  27.   if (res.status == 200) {
  28.     return res.data
  29.   } else {
  30.     ElMessage.error((NETWORK_ERROR))
  31.     return Promise.reject(NETWORK_ERROR)
  32.   }
  33. });
  34. export default http
复制代码
4.4、前端设置跨域

在vue.config.js中配置如下代码:

  1. const { defineConfig } = require('@vue/cli-service');
  2. // const AutoImport = require('unplugin-auto-import/webpack');
  3. // const Components = require('unplugin-vue-components/webpack');
  4. // const { ElementPlusResolver } = require('unplugin-vue-components/resolvers');
  5. module.exports = defineConfig({
  6.   transpileDependencies: true,
  7.   //关闭eslint校验
  8.   lintOnSave: false,
  9.   // ElementPlus按需导入方式
  10.   // configureWebpack: {
  11.   //   plugins: [
  12.   //     AutoImport({
  13.   //       resolvers: [ElementPlusResolver()],
  14.   //     }),
  15.   //     Components({
  16.   //       resolvers: [ElementPlusResolver()],
  17.   //     }),
  18.   //   ],
  19.   // }
  20.   devServer: {
  21.     open: true,
  22.     host: 'localhost',
  23.     port: 8080,
  24.     https: false,
  25.     // 设置跨域
  26.     proxy: {
  27.       '/api': {
  28.         target: 'http://localhost:9000',
  29.         ws: true,
  30.         changeOrigin: true,
  31.         pathRewrite: {
  32.           '^api': ''
  33.         }
  34.       }
  35.     }
  36.   }
  37. })
复制代码
4.5、配置接口api

在src目录下创建api文件夹,里面创建index.ts

  1. import http from '@/utils/requestUtils'
  2. export default {
  3.   /**
  4.    * 根据用户邮箱、密码查询用户信息
  5.    */
  6.   getUserPassword(data: any) {
  7.     return http.post(
  8.       '/api/getUserPassword',
  9.       data,
  10.       {
  11.         headers: {
  12.           'Content-Type': 'application/json'
  13.         },
  14.       }
  15.     )
  16.   },
  17.   /**
  18.    * 保存用户信息
  19.    */
  20.   saveUser(data: any) {
  21.     return http.post(
  22.       '/api/saveUser',
  23.       data,
  24.       {
  25.         headers: {
  26.           'Content-Type': 'application/json'
  27.         },
  28.       }
  29.     )
  30.   },
  31. }
复制代码
4.6、将http请责备局封装

在 main.ts 文件引入HTTP请求工具并配置为全局方法

  1. import { createApp } from 'vue'
  2. import App from './App.vue'
  3. import router from './router'
  4. import store from './store'
  5. import ElementPlus from 'element-plus'
  6. import 'element-plus/dist/index.css'
  7. import axios from 'axios'
  8. import apiServe from '@/api'
  9. const app = createApp(App)
  10. app.use(store)
  11. app.use(router)
  12. app.use(ElementPlus)
  13. app.mount('#app')
  14. app.config.globalProperties.$http = apiServe
  15. 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,制止和前端端口雷同了

注释掉另外一个配置

  1. # mysql
  2. spring:
  3.   datasource:
  4.     #MySQL配置
  5.     driverClassName:  com.mysql.cj.jdbc.Driver
  6.     url: jdbc:mysql://localhost:3306/easyproject?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC
  7.     #数据库名和密码
  8.     username: root
  9.     password: 920724
  10. mybatis:
  11.   mapper-locations: classpath:mapper/*.xml
  12.   type-aliases-package: com.example.demo.model
  13. server:
  14.   port: 9000
复制代码
7、运行项目


项目运行成功,端口9000


8、新建WebConfig文件处理跨域

创建utils文件夹,在utils文件夹下创建WebConfig,并添加以下配置

  1. package com.springboot.userlogin.springbootdemo.utils;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.web.servlet.config.annotation.CorsRegistry;
  4. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  5. // 使用注解说明是全局配置类
  6. @Configuration
  7. public class WebConfig extends WebMvcConfigurerAdapter { // 继承跨域请求的类
  8.     @Override
  9.     public void addCorsMappings(CorsRegistry registry) { // 跨域处理的方法
  10.         registry.addMapping("/**") // 任意访问都允许跨域
  11.                 .allowedOrigins("http://localhost:8080", "null") // 跨域来源
  12.                 .allowedMethods("POST", "GET", "PUT", "OPTIONS", "DELETE") // 跨域请求类型
  13.                 .maxAge(3600) // 超时时间
  14.                 .allowCredentials(true); // 允许携带信息
  15.     }
  16. }
复制代码
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注解

  1. <dependency>
  2.       <groupId>org.projectlombok</groupId>
  3.       <artifactId>lombok</artifactId>
  4.       <version>1.18.24</version>
  5. </dependency>
复制代码
11、创建bean文件夹,用于放置实体对象

在项目中创建bean文件夹,新建user实体类,利用Data注解,创建构造方法和get\set方法

  1. package com.springboot.userlogin.springbootdemo.bean;
  2. import lombok.Data;
  3. @Data
  4. public class User {
  5.     private int id;
  6.     private String username;
  7.     private String password;
  8.     private String email;
  9.     private String role;
  10.     private boolean state;
  11. //    public User() {
  12. //    }
  13. //    public User(String username, String password, String email, String role, boolean state) {
  14. //        this.username = username;
  15. //        this.password = password;
  16. //        this.email = email;
  17. //        this.role = role;
  18. //        this.state = state;
  19. //    }
  20. //
  21. //    public int getId() {
  22. //        return id;
  23. //    }
  24. //
  25. //    public String getUsername() {
  26. //        return username;
  27. //    }
  28. //
  29. //    public String getPassword() {
  30. //        return password;
  31. //    }
  32. //
  33. //    public String getEmail() {
  34. //        return email;
  35. //    }
  36. //
  37. //    public String getRole() {
  38. //        return role;
  39. //    }
  40. //
  41. //    public boolean getState() {
  42. //        return state;
  43. //    }
  44. //
  45. //    public void setId(int id) {
  46. //        this.id = id;
  47. //    }
  48. //
  49. //    public void setUsername(String username) {
  50. //        this.username = username;
  51. //    }
  52. //
  53. //    public void setPassword(String password) {
  54. //        this.password = password;
  55. //    }
  56. //
  57. //    public void setEmail(String email) {
  58. //        this.email = email;
  59. //    }
  60. //
  61. //    public void setRole(String role) {
  62. //        this.role = role;
  63. //    }
  64. //
  65. //    public void setState(boolean state) {
  66. //        this.state = state;
  67. //    }
  68. }
复制代码
12、查看构造成功成功的实体对象

快捷键 alt + 7

13、创建controller接口


  1. import org.springframework.web.bind.annotation.PostMapping;
  2. import org.springframework.web.bind.annotation.RequestBody;
  3. import org.springframework.web.bind.annotation.RestController;
  4. @RestController
  5. public class LoginController {
  6.     @Autowired
  7.     UserDao userDao;
  8.     @PostMapping("/api/getUserPassword") // @RequestMapping注解创建接口
  9.     public String userLogin(@RequestBody User user) { // @RequestBody注解方便找到user实体
  10.         System.out.println("User : " + user);
  11.         String str = "error";
  12.         int count = userDao.getUserByMassage(user.getEmail(), user.getPassword());
  13.         if (count > 0) {
  14.             str = "ok";
  15.         }
  16.         return str;
  17.     }
  18. }
复制代码
14、创建dao接口


  1. package com.springboot.userlogin.springbootdemo.dao;
  2. import org.apache.ibatis.annotations.Mapper;
  3. import org.apache.ibatis.annotations.Param;
  4. import org.springframework.stereotype.Repository;
  5. @Repository
  6. @Mapper
  7. public interface UserDao {
  8.     int getUserByMassage(@Param("email") String email, @Param("password") String password);
  9. }
复制代码
15、创建mapper映射文件

在resources下面创建mapper文件夹,用于存放数据库的映射文件
在mapper文件夹下新建UserMapper.xml

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <!DOCTYPE mapper  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  3.         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  4. <!--对应dao层接口文件的目录-->
  5. <mapper namespace="com.springboot.userlogin.springbootdemo.dao.UserDao">
  6.     <!--  id值为UserDao接口方法名; -->
  7.     <select id="getUserByMassage" resultType="java.lang.Integer">
  8.                SELECT count(id) FROM easyUser
  9.                WHERE email=#{email} AND password=#{password}
  10.     </select>
  11. </mapper>
复制代码
三、测试前后端功能

1、前端页面接口请求


2、后端控制台日记打印



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

用户云卷云舒

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表