Tb0_图书管理系统保姆教程(一)

2023-12-21 11:56:10

基于Vue+SpringBoot+Mybatis的图书管理系统

图书管理系统保姆教程(一)

需求分析

  • 用户与角色权限管理

    普通用户
    • 查看图书
    • 借阅图书
    • 添加图书评论
    • 查看借阅图书的信息
    • 归还图书
    • 修改用户密码
    系统管理员
    • 增删改查图书信息
    • 增删改查用户信息
  • 图书管理

    图书管理

    • excel批量导入

技术架构

前端:使用Vue+axios+elemenet框架实现

后端:SpringBoot+Mybatis

背景知识介绍

环境准备

IDE

  • VSCode
  • IntelliJ IDEA

使用 CLI 搭建 Vue.js 项目

利用 Vue CLI(或写成 vue-cli,即 Vue 脚手架)搭建项目

  • 安装 NPM(Node Package Manager),是一个NodeJS包管理和分发工具 。所以直接安装 Node.js,访问官网 https://nodejs.org/en/下载。
  • 安装 Vue CLI
npm install -g vue-cli
或者
npm install -g @vue/cli
  • 测试验证(略)

使用IntelliJ IDEA 创建Spring Boot项目

  • IntelliJ IDEA 专业版自带Spring插件
  • IntelliJ IDEA 社区版本,下载Spring Boot Helper
  • 使用maven的方法配置项目
  • 使用spring网站配置

创建项目

后端项目创建

博主直接使用spring网站配置的spring工程,直接使用idea打开运行。

后端运行效果(这个是正常运行的标志,虽然还没有加前端)

在这里插入图片描述

后端开发

用户类

java/demo/src/main/java/com/example/demo/User.java

这个类是有问题的!!!解决方法在后面

package book;

public class User {
    int ID;
    String userame;
    String passWord;

    public int getId() {
        return ID;
    }

    public void setId(int id) {
        this.ID = id;
    }

    public String getuserName() {
        return userame;
    }

    public void setuserName(String userName) {
        this.userame = userName;
    }

    public String getPassword() {
        return passWord;
    }

    public void setPassword(String password) {
        this.passWord = password;
    }
}
相应控制类

java/demo/src/main/java/com/example/demo/LoginController.java

package com.example.demo;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.Objects;

@Controller
public class LoginController {

    @CrossOrigin(origins = "*", allowedHeaders = "*")
    @PostMapping(value = "/api/login")
    @ResponseBody
    public Result login(@RequestBody User requestUser) {

        String username = requestUser.getUsername();

        if (!Objects.equals("admin", username) || !Objects.equals("123123", requestUser.getPassword())) {
            String message = "账号密码错误";
            return new Result(400);
        } else {
            return new Result(200);
        }
    }

    @CrossOrigin
    @PostMapping(value = "/api/test")
    public int test() {

            return  400;
        }
}
后端配置

java/demo/src/main/resources/application.properties添加 内容(初始应该是空白的,后期还要配置数据库等)

server.port=8888

前端页面开发

后端创建完成,需开发一个前端显示界面。

登录页面:src\components\Login.vue

<template>
    <div>
        用户名:<input type="text" v-model="loginForm.username" placeholder="请输入用户名"/>
        <br><br>
        密码: <input type="password" v-model="loginForm.password" placeholder="请输入密码"/>
        <br><br>
        <button v-on:click="login">登录</button>
    </div>
</template>

<script>

export default {
  name: 'Login',
  data () {
    return {
      loginForm: {
        username: '',
        password: ''
      },
      responseResult: []
    }
  },
  methods: {
    login () {
      this.$axios
        .post('/login', {
          username: this.loginForm.username,
          password: this.loginForm.password
        })
        .then(successResponse => {
          if (successResponse.data.code === 200) {
            this.$router.replace({path: '/index'})
          }
        })
        .catch(failResponse => {
        })
    }
  }
}
</script>

跳转页面:src\components\AppIndex.vue

<template>
    <div>
      Hello World!
    </div>
</template>

<script>
export default {
  name: 'AppIndex'
}
</script>

<style scoped>

</style>

前端配置

设置反向代理

src\main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'

import axios from 'axios'

// 设置baseURL,8888是后端端口号,前端请求默认发送到baseURL的地址
// var axios = require('axios')
axios.defaults.baseURL = 'http://localhost:8888/api'
Vue.prototype.$axios = axios// 全局注册,其他组件中通过调用 this.$axios 发送数据
Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

这儿会报错:

ailed to compile with 1 errors                                                                         上午11:32:03

This dependency was not found:

* axios in ./src/main.js

To install it, you can run: npm install --save axios
Error from chokidar (D:\): Error: EBUSY: resource busy or locked, lstat 'D:\DumpStack.log.tmp'
Error from chokidar (D:\node_modules): Error: EBUSY: resource busy or locked, lstat 'D:\DumpStack.log.tmp'

这儿英文提示的很清楚,需安装axios。

配置页面路由

src\router\index.js

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'
import Login from '@/components/Login'
import AppIndex from '@/components/AppIndex'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    },
    {
      path: '/login',
      name: 'Login',
      component: Login
    },
    {
      path: '/AppIndex',
      name: 'AppIndex',
      component: AppIndex
    }
  ]
})

跨域支持

config\index.js修改proxyTable

    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
      '/api': {
        target: 'http://localhost:8888',
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
      }
    },

运行程序

同时运行前端和后端项目,访问 localhost:8080/#/login,输入用户名 admin,密码 123123

后端未启动的情况

在这里插入图片描述

后端启动报错

启动出错

Access to XMLHttpRequest at 'http://localhost:8888/api/login' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
xhr.js:264 
        
 POST http://localhost:8888/api/login net::ERR_FAILED

? 这是常见的跨域资源共享(CORS)问题 。

? 浏览器限制了跨域请求,只有在服务端设置了响应头 Access-Control-Allow-Origin 时,才允许跨域请求。 这个错误是由于浏览器的跨域安全策略导致的。

CORS原理

跨域资源共享(CORS)是一种机制,是W3C标准。它允许浏览器向跨源服务器,发出XMLHttpRequest或Fetch请求。整个CORS通信过程都是浏览器自动完成的,不需要用户参与。

CORS的工作原理是:

  1. 浏览器先根据同源策略对前端页面和后台交互地址做匹配,若同源,则直接发送数据请求;若不同源,则发送跨域请求。
  2. 当浏览器需要向跨源服务器发送请求时,会在请求头中添加一些额外的字段,这些字段告诉服务器请求来自哪个源(即来源域名、协议和端口)。
  3. 服务器接收到请求后,会检查请求头中的这些字段,确认是否接受来自该源的请求。如果接受,服务器会正常处理请求并返回数据;如果不接受,服务器可能会返回一个错误响应。

CORS的配置通常包括以下几个字段:

  • Access-Control-Allow-Origin:指定哪些来源的网页可以访问该资源。可以是具体的来源域名,也可以是通配符’*'表示任何来源都可以访问。
  • Access-Control-Allow-Methods:指定允许的前端发起请求的方法类型。
  • Access-Control-Allow-Headers:指定允许的前端请求头字段。
  • Access-Control-Allow-Credentials:指定是否允许携带凭据(如cookies、HTTP认证等)。
  • Access-Control-Max-Age:指定预检请求的有效期(以秒为单位),即在多长时间内无需发送预检请求。

需要注意的是,使用CORS的前提是浏览器必须支持这个功能,并且服务器端也必须同意这种"跨域"请求。因此实现CORS的关键是服务器。

解决方法

将这几个类直接改到DemoApplication包下。

如图:

出错解决

博主的问题是把LoginController类、Result类、User类都放到自己创建的book目录下了。途中的book目录已经删除。book目录需时demo的子目录。

遇到跨域问题的同学可以尝试检查一下自己的

control类所在的包需符合“controller类必须是Application的所在包的类或者子包的类” ,启动类Application是Controller文件的上一级,只有这样,项目启动时才能扫描加载到controller类。

登录后不跳转
问题描述

两个页面单独登录可以登录

http://localhost:8080/#/login
http://localhost:8080/#/index

输入用户密码,页面不跳转

问题分析

单独页面都可以登录说明页面没有问题;

输入用户名密码,在login函数中,修改返回结果都是200后。页面可以正常跳转。说明前端代码正常。

public Result login(@RequestBody User requestUser) {

        String username = requestUser.getUsername();

        if (!Objects.equals("admin", username) || !Objects.equals("123123", requestUser.getPassword())) {
            String message = "账号密码错误";
            return new Result(200);
        } else {
            return new Result(200);
        }
    }

在方法中打断点,查看变量,username获取为空,密码是正确的。

按照原来的逻辑,应该返回new Result(400),确实不会跳转。

检查发现

在这里插入图片描述

设置两个断点,一个是setUserName函数,一个是setPassword函数。结果只进入setPassword

解决方法

点击右上角警告提示

在这里插入图片描述

警告已经写了这两个函数未使用,那么直接修改名称。修改名称后,还是不跳转。修改函数setUserName

改成setUsername。此处犯了两个拼写错误,都是泪。

至此完成前后端正常登录跳转功能。

项目Github地址链接

演示结果:

为空,密码是正确的。

按照原来的逻辑,应该返回new Result(400),确实不会跳转。

检查发现

在这里插入图片描述

设置两个断点,一个是setUserName函数,一个是setPassword函数。结果只进入setPassword

解决方法

点击右上角警告提示

在这里插入图片描述

警告已经写了这两个函数未使用,那么直接修改名称。修改名称后,还是不跳转。修改函数setUserName

改成setUsername。此处犯了两个拼写错误,都是泪。

至此完成前后端正常登录跳转功能。

项目Github地址链接

演示结果:

在这里插入图片描述

文章来源:https://blog.csdn.net/xinqingwuji/article/details/135124287
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。