项目 谷粒学院Day04-06

Day04(07.02)

前端知识

axios

在浏览器中可以帮助我们完成 ajax请求的发送

在node.js中可以向远程接口发送请求

在这里插入图片描述

使用
  1. 创建 HTML 页面,引入 js 文件,包含两个 js 文件,vue 和 axios

    <script src="vue.min.js"></script>
    <script src="axios.min.js"></script>
    
  2. 编写 axios 代码

    1. 创建 json 文件,数据创建

      {
          "success":true,
          "code":20000,
          "message":"成功",
          "data":{
              "items":[
                  {"name":"luvy","age":20},
                  {"name":"mary","age":30},
                  {"name":"jack","age":40}
              ]
          }
      
      }
      
    2. 使用 axios 发送 ajax 请求,请求文件,得到数据,在页面显示

      <body>
          <div id="app">
              <!--把userList数组里面数据显示,使用v-for指令-->
              <div v-for="user in userList">
                  {{user.name}}--{{user.age}}
              </div>
          </div>
          <script src="vue.min.js"></script>
          <script src="axios.min.js"></script>
          <script>
              new Vue({
                  el: '#app',
                  //固定的结构
                  data: {//在data定义变量和初始值
                      //定义变量,值是空的数组
                      userList:[]
                  },
                  created(){//调用定义方法,在页面渲染之前执行
                      this.getUserList()
                  },
                  methods:{//编写具体方法
                      //创建方法,查询所有用户数据
                      getUserList(){
                          //使用 axios 发送 ajax 请求
                          //axios.提价方式("请求接口路径”).then(箭头函数).catch(箭头函数)
                          axios.get("data.json")
                              .then(response =>{
                                  //response就是请求之后返回数据
                                  //console.log(response)
                                  //通过response获取具体数据,赋值给定义的空数组
                                  this.userList=response.data.data.items
                                  console.log(this.userList)
                              })//请求成功,执行 then 方法
                              .catch(error =>{
      
                              })//请求失败,执行 catch 方法
                      }
                  }
              })
          </script>
      </body>
      

      在这里插入图片描述

element-ui

是饿了么前端出品的基于 Vue.js的 后台组件库,方便程序员进行页面快速布局和构建

可以直接找到喜欢的图样模式,查看源码并修改

node.js

  1. node.js 是什么

    1. 是 JavaScript 的运行环境,用于执行 JavaScript 代码,不需要浏览器,直接可以运行 JavaScript 代码,相当于 Java 中的 jdk 环境
    2. 模拟服务器效果,如Tomcat
  2. 使用 node.js 执行 JavaScript 代码

在这里插入图片描述

  1. 在 vscode 中打开 cmd 窗口,执行 JavaScript 代码

在这里插入图片描述

npm

  1. 在后端开发中,使用过 maven,maven 可以构建项目,管理 jar 依赖,联网下载依赖

  2. npm 类似于 maven,用在前端中,管理前端 js 依赖,联网下载 js 依赖,比如 jQuery

  3. 查看是否安装成功

在这里插入图片描述

  1. 演示 npm 具体操作

    1. nmp 项目初始化操作

      使用命令 npm init

    在这里插入图片描述

    在这里插入图片描述

    项目初始化后,生成文件 package.json,类似于后端的 pom.xml

    1. npm 下载 js 依赖

      命令 npm install 依赖名

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

  其中 lock 文件锁定依赖版本,将项目发给别人时,只发 package.json 让其他人自行下载依赖,此时lock文件会锁定依赖的版本,而不是下载最新版本。
  1. 根据 package.json 文件下载依赖

    使用命令 npm install

babel

是一个转码器,可以将ES6代码转为ES5代码

因为写的代码是 es6 代码,但是 es6 代码浏览器兼容性很差,如果用 es5 代码,浏览器兼容性更好

所以用 babel 把 es6 代码转成 es5 运行

  1. 安装 babel 工具,使用命令npm install --global babel-cli

  2. 创建 js 文件,编写 es6 代码
    在这里插入图片描述

    标志性箭头函数为 es6 代码

  3. 创建 babel 配置文件,Babel的配置文件是.babelrc(固定名字),存放在项目的根目录下

在这里插入图片描述

  1. 安装 es2015 转码器

    npm install --save-dev babel-preset-es2015
    
  2. 使用命令进行转码

    1. 根据文件转码

      babel es6/01.js -o dist/001.js

在这里插入图片描述

  1. 根据文件夹转码

    babel es6 -d dist
    在这里插入图片描述
    在这里插入图片描述

模块化

  1. 模块化是什么

    1. 开发后端接口时,开发controller service mapper,controller 注入 service,service 注入 mapper,在后端中,类与类之间的调用是后端模块化操作
    2. 前端是 js 与 js 之间调用为模块化操作
  2. 使用 es5 实现模块化操作

    1. 在 01.js 中定义 js 方法

      //创建js方法
      //定义成员
      const sum = function(a,b){
              return parseInt(a) + parseInt(b)
          }
          const subtract = function(a,b){
              return parseInt(a) - parseInt(b)
      }
      
      //设置哪些方法可以被其他js调用
      module.exports={
          sum,
          subtract
      }
      
    2. 在 02.js 中调用 01.js 中的方法

      //调用01.js中的方法
      //1 引入01.js文件
      const m=require('./01')
      //2 调用
      console.log(m.sum(1,0))
      console.log(m.subtract(10,2))
      
    3. 结果在这里插入图片描述

  3. es6模块化操作

    如果使用 es6 写法实现模块化操作,在 node.js 环境中不能直接运行,需要使用 babel 将 es6 转成 es5 才能在 node.js 中运行

    1. 第一种写法

      //01.js
      //创建js方法,设置哪些方法可以被其他js调用
      export function getList(){
          console.log('getList...')
      }
      export function save(){
          console.log('save...')
      }
      
      
      //02.js
      //调用01.js中的方法
      //1 引入01.js文件
      import {getList,save} from'./01.js'
      //2 调用
      getList()
      save()
      

      进行转换 babel modulees61 -o es611,输出结果

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

  1. 第二种写法

    //01.js
    //创建js方法,设置哪些方法可以被其他js调用
    export default {
        getList(){
        console.log('getList...')
        },
        update(){
        console.log('update...')
        }
    }
    
    //02.js
    //调用01.js中的方法
    //1 引入01.js文件
    import m from'./01.js'
    //2 调用
    m.getList()
    m.update()
    

    进行转化,输出结果

![在这里插入图片描述](https://img-blog.csdnimg.cn/20210706145934550.png)

在这里插入图片描述

webpack

Webpack 是一个前端资源加载/打包工具。把多个静态资源文件打包成一个文件,减少页面的请求次数,提高页面访问效率

打包 js
  1. 安装 webpack 工具

在这里插入图片描述

  1. 创建 js 文件用于打包操作

    //common.js
    exports.info = function (str) {
            document.write(str);//浏览器输出
    }
    //utils.js
    exports.add = function (a, b) {
            return a + b;
    }
    //main.js
    const common= require('./common.js')
    const utils= require('./util.js')
    
    common.info('hello common'+ utils.add(100,18))
    
  2. 创建 webpack 配置文件,配置打包信息,文件名固定为 webpack.config.js

    const path = require("path"); //Node.js内置模块
    module.exports = {
        entry: './src/main.js', //配置入口文件
        output: {
            path: path.resolve(__dirname, './dist'), //输出路径,__dirname:当前文件所在路径
            filename: 'bundle.js' //输出文件
        }
    }
    
  3. 使用命令执行打包操作 webpack

    webpack #有黄色警告
    webpack --mode=development #没有警告
    #执行后查看bundle.js 里面包含了上面两个js文件的内容并惊醒了代码压缩
    

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

    加上打包模式

在这里插入图片描述

在这里插入图片描述

  1. 测试

    创建 01.html 用于测试
    在这里插入图片描述

在这里插入图片描述

打包 css
  1. 安装 style-loader 和 css-loader

    npm install --save-dev style-loader css-loader 
    
  2. 创建 css 文件,写样式内容

    body{
        background-color: aquamarine;
    }
    
  3. 在 main.js 中引入 css 文件

    //css 文件引入
    require('./style.css')
    
  4. 修改 webpack 配置文件

    const path = require("path"); //Node.js内置模块
    module.exports = {
        entry: './src/main.js', //配置入口文件
        output: {
            path: path.resolve(__dirname, './dist'), //输出路径,__dirname:当前文件所在路径
            filename: 'bundle.js' //输出文件
        },
        module: {
                    rules: [  
                        {  
                            test: /\.css$/,    //打包规则应用到以css结尾的文件上
                            use: ['style-loader', 'css-loader']
                        }  
                    ]  
                }
    }
    
  5. 重新打包,看结果

    在这里插入图片描述

搭建前端页面

选取模板(框架)进行环境搭建,使用 vue-admin-template

在这里插入图片描述

项目基本结构

  1. 前端框架入口

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

  1. 前端页面环境使用框架(模板),主要基于两种技术实现出来 vue + element-ui

  2. 框架的 build 目录

    放项目构建的脚本文件

  3. 框架的 config 目录

    可以改端口号等信息,修改在这里插入图片描述
    中的在这里插入图片描述
    改为false
    在这里插入图片描述
    可以修改访问后端接口地址

  4. src 目录

    在这里插入图片描述

    api :定义一些调用方法

    assets:定义静态资源

    components:组件,可以放一些额外的插件

    icons:图标

    router:路由

    store:脚本文件

    styles:样式文件

    utils:工具类

    views:项目中具体的页面

遇到问题

  1. 安装 node.js 失败

    使用.msi 显示失败,使用zip安装,并配置环境变量

  2. vscode 无法在终端直接使用 node命令

    重新打开,用管理员身份运行

  3. vscode 执行babel --version 无法查看版本号

    最后找出是VSCode终端类型的问题,终端应该是cmd的格式但是自己的终端格式是powdershell,,通过更改相关的权限就也可以使得powershell类型的终端可以运行:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Dso19esk-1625554321365)(C:\Users\User\AppData\Roaming\Typora\typora-user-images\image-20210704163004215.png)]

  4. 安装依赖出现问题,下载失败

    node.js 中没有 python 环境
    在这里插入图片描述
    在这里插入图片描述

Day05(07.05)

讲师管理前端开发

首先把后台管理系统登录改成本地(临时),后续会把登录添加权限框架 spring security

把系统登录改成本地

  1. 修改配置文件请求地址

    在 config 文件中修改 dev.env.js

在这里插入图片描述

  1. 登录要调用两个方法,login 登录操作方法,info 登陆之后获取用户信息方法,所以,创建接口两个方法实现登录

    1. login 返回 token 值
    2. info 返回 roles name avatar
  2. 开发接口

在这里插入图片描述

@RestController
@RequestMapping("/eduservice/user")
public class EduLoginController {
    //login
    @PostMapping("login")
    public R login(){
        return R.ok().data("token","admin");
    }

    //info
    @GetMapping("info")
    public R info(){
        return R.ok().data("roles","[admin]").data("name","admin").data("avatar","https://i.loli.net/2021/07/05/WZpQEGaRtCmP2Hu.gif");
    }
}
  1. 修改 api 文件夹 login.js 修改本地接口的路径

    export function login(username, password) {
      return request({
        url: '/eduservice/user/login',
        method: 'post',
        data: {
          username,
          password
        }
      })
    }
    
    export function getInfo(token) {
      return request({
        url: '/eduservice/user/info',
        method: 'get',
        params: { token }
      })
    }
    
  2. 最终测试

    1. 问题
      在这里插入图片描述

    2. 跨域问题

      通过一个地址访问另外一个地址,这个过程中如果有三个地方(访问协议 IP地址 端口号)任何一个不一样

在这里插入图片描述

在这里插入图片描述

  端口号不一样,出现跨域问题
  1. 跨域解决方式

    1. 在后端接口 controller 添加注解

在这里插入图片描述

  1. 使用网关解决

  2. 结果

    在这里插入图片描述

框架使用过程

  1. 添加路由

    在这里插入图片描述

  2. 点击某个路由,显示路由页面内容,在 views 创建 vue 页面

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

  3. 在 api 文件夹创建 js 文件,定义接口地址和参数

    在这里插入图片描述

  4. 在创建的 vue 页面引入 js 文件,调用方法实现功能

    1. 引入 import user from‘…’

    2. data():{
      
      },
      created():{
      
      },
      methods():{
      
      }
      
    3. 最后使用 element-ui 显示数据内容

讲师列表(分页条件查询)

添加路由
  {
    path: '/teacher',
    component: Layout,
    redirect: '/teacher/table',
    name: '讲师管理',
    meta: { title: '讲师管理', icon: 'example' },
    children: [
      {
        path: 'table',
        name: '讲师列表',
        component: () => import('@/views/table/index'),
        meta: { title: '讲师列表', icon: 'table' }
      },
      {
        path: 'save',
        name: '添加讲师',
        component: () => import('@/views/tree/index'),
        meta: { title: '添加讲师', icon: 'tree' }
      }
    ]
  },

在这里插入图片描述

创建路由对应页面

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

在 api 文件夹创建 teacher.js 文件,定义访问的接口地址
import request from '@/utils/request'

export default{
    //1 讲师列表(条件分页查询)
    //current 当前页 limit每页记录数 teacherQuery条件对象
    getTeacherListPage(current,limit,teacherQuery){
        return request({
         url: `/eduservice/teacher/pageTeacherCondition/${current}/${limit}`,
         method: 'post',
         //teacherQuery条件对象,后端使用RequestBody获取诗句
         //data 表示把对象转换为json 传递到接口里面
         data: teacherQuery
        })
    }
}
在 list.vue 调用定义的接口方法,得到接口返回数据
<script>
//引入调用 teacher.js文件
import teacher from'@/api/edu/teacher'

export default {
  //核心代码
  data(){// 定义变量和初始值
    return{
      list:null,//查询之后接口返回集合
      page:1,//当前页
      limit:10,//每页记录数
      total:0,//总记录数
      teacherQuery:{}//条件封装对象
    }
  },
  created(){//页面渲染之前执行,一般调用methods定义的方法
      //调用
      this.getList()
  },
  methods:{//创建具体方法,调用teacher.js 定义的方法
      //讲师列表方法
      getList(){
        teacher.getTeacherListPage(this.page,this.limit,this.teacherQuery)
          .then(response => {
            //response接口返回的数据
            //console.log(response)
            this.list=response.data.rows
            this.total=response.data.total
            console.log(this.list)
            console.log(this.total)
          })//请求成功
          .catch(error => {
            console.log(error)
          })//请求失败
      }
  }
}
</script>
请求接口获取的数据在页面进行显示

使用 element-ui

JavaScript中两个判断值,三个=判断类型和值

在这里插入图片描述

分页

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

条件查询
    <!--查询表单-->
    <el-form :inline="true" class="demo-form-inline">
      <el-form-item>
        <el-input v-model="teacherQuery.name" placeholder="讲师名"/>
      </el-form-item>

      <el-form-item>
        <el-select v-model="teacherQuery.level" clearable placeholder="讲师头衔">
          <el-option :value="1" label="高级讲师"/>
          <el-option :value="2" label="首席讲师"/>
        </el-select>
      </el-form-item>

      <el-form-item label="添加时间">
        <el-date-picker
          v-model="teacherQuery.begin"
          type="datetime"
          placeholder="选择开始时间"
          value-format="yyyy-MM-dd HH:mm:ss"
          default-time="00:00:00"
        />
      </el-form-item>
      <el-form-item>
        <el-date-picker
          v-model="teacherQuery.end"
          type="datetime"
          placeholder="选择截止时间"
          value-format="yyyy-MM-dd HH:mm:ss"
          default-time="00:00:00"
        />
      </el-form-item>

      <el-button type="primary" icon="el-icon-search" @click="getList()">查询</el-button>
      <el-button type="default" @click="resetData()">清空</el-button>
    </el-form>

在这里插入图片描述

清空

清空表单输入条件数据并查询所有的数据

在methods中添加函数

resetData() {//清空方法
         this.teacherQuery = {}//表单输入项数据清空,因为双向绑定
         this.getList()//查询所有讲师数据
}

讲师删除

在每条记录后,添加删除按钮

在这里插入图片描述

添加按钮绑定事件

在这里插入图片描述

在绑定事件的方法传递删除讲师的 id 值

在这里插入图片描述

在 api 文件夹 teacher.js 定义删除接口的地址
//删除讲师
    deleteTeacherId(id){
        return request({
         url: `/eduservice/teacher/${id}`,
         method: 'delete',
        })
    }
}
页面调用
//删除讲师方法
       removeDataById(id){
            this.$confirm('此操作将永久删除该讲师记录, 是否继续?', '提示', {
               confirmButtonText: '确定',
               cancelButtonText: '取消',
               type: 'warning'
            }).then(() => {//点击确定,执行then方法

            //调用删除方法
            teacher.deleteTeacherId(id)
             .then(response =>{//删除成功

              //提示信息
              this.$message({
                 type: 'success',
                 message: '删除成功!'
              });

             //刷新回到列表页面
              this.getList()
             })
        })//点击取消,执行catch方法
      }

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

讲师添加

api 定义接口地址
//添加讲师
    addTeacher(teacher){
        return request({
            url: `/eduservice/teacher/addTeacher`,
            method: 'post',
            data:teacher
        })
    }
页面调用

save.vue中
在这里插入图片描述
在这里插入图片描述

讲师修改

每条记录后添加修改按钮

在这里插入图片描述

点击修改进入表单页面,进行数据回显

根据讲师 id 查询数据显示

通过路由跳转进入数据回显页面

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

表单页面实现数据回显
  1. 在 teacher.js 中定义根据 id 查询接口

  2. 在页面调用接口

     //根据讲师 id 查询的方法
        getInfo(id){
          teacherApi.getTeacherInfo(id)
          .then(response =>{
            this.teacher=response.data.teacher
          })
        },
    
  3. 调用根据 id 查询的方法

    因为添加和修改都用 save 页面,需要区别是添加还是修改,只有修改时查询数据回显

    判断路径里面是否有讲师 id 值,有就是修改,没有就是添加

     created(){
        //判断路径是否有 id 值
        if (this.$route.params && this.$route.params.id) {
          const id = this.$route.params.id
          this.getInfo(id)
        }
      },
    

在这里插入图片描述

最终修改
  1. 在 api 的 teacher.js 定义修改接口

     //修改讲师
        updateTeacher(teacher){
            return request({
                url: `/eduservice/teacher/updateTeacher`,
                method: 'post',
                data:teacher
            })
        }
    
  2. 在页面调用修改方法

    saveOrUpdate() {
          //判断修改还是添加,根据teacher是否有id
          if(!this.teacher.id){
            //添加
            this.saveTeacher()
          }else{
            //修改
            this.updateTeacher()
          }
        },
            //修改讲师的方法
        updateTeacher(){
          teacherApi.updateTeacherInfo(this.teacher)
            .then(response =>{
              //提示信息
               this.$message({
              type: 'success',
             message: '修改成功!'
             });
              //回到列表,路由跳转
               this.$router.push({path:'/teacher/table'})
          })
        },
    
  3. 在这里插入图片描述

遇到问题

  1. 头像不显示

    一开始直接把网上图像右键打开链接地址,然后复制,不能显示
    解决办法:需要去第三方网站转换
    地址:https://sm.ms/,选择图片后upload,然后选择所对应的URL地址

    在这里插入图片描述

  2. 第一次点击修改,数据回显,但是第二次点击添加,还会显示回显数据,正确应该没有回显

    想通过这种方式解决:做添加讲师时,把表单数据清空在这里插入图片描述

    原因:多次路由跳转到同一个页面,created只会执行第一次,后面再进行跳转不会执行

    最终解决:使用 vue 监听

      watch: {
        $route(to, from) {//路由变化方式,当路由发生变化,方法就会执行
          this.init()
        }
      },
    

Day06(07.05)

阿里云oss使用

  1. 创建操作阿里云oss许可证

添加讲师头像上传功能

在service创建子模块

在service_oss中引入依赖

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zewZpaiO-1625554321467)(C:\Users\User\AppData\Roaming\Typora\typora-user-images\image-20210705195922150.png)]

创建配置文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Kwuil0cn-1625554321469)(C:\Users\User\AppData\Roaming\Typora\typora-user-images\image-20210705200534338.png)]

在启动类添加属性

因为目前这个 maven 不会链接数据库,启动会报错

解决方式两种:添加数据库配置

​ 在启动类添加属性,不加载数据库

在这里插入图片描述

启动成功

在这里插入图片描述

上传头像具体代码

  1. 创建常量类,读取配置文件内容

    //当项目启动,spring接口,spring加载后,执行接口一个方法
    @Component
    public class ConstantPropertiesUtils implements InitializingBean {
        //读取配置文件内容
        @Value("${aliyun.oss.file.endpoint}")//将value注解中的值注入属性中
        private String endpoint;
    
        @Value("${aliyun.oss.file.keyid}")
        private String keyId;
    
        @Value("${aliyun.oss.file.keysecret}")
        private String keySecret;
    
        @Value("${aliyun.oss.file.bucketname}")
        private String bucketName;
    
    
        //定义公开静态常量
        public static String END_POINT;
        public static String ACCESS_KEY_ID;
        public static String ACCESS_KEY_SECRET;
        public static String BUCKET_NAME;
    
    
        @Override
        public void afterPropertiesSet() throws Exception {
            END_POINT=endpoint;
            ACCESS_KEY_ID = keyId;
            ACCESS_KEY_SECRET = keySecret;
            BUCKET_NAME = bucketName;
        }
    }
    
  2. 创建 controller ,service

    1. controller

      @RestController
      @RequestMapping("/eduoss/fileoss")
      public class OssController {
      
          @Autowired
          private OssService ossService;
          //上传头像方法
          @PostMapping
          public R uploadOssFile(MultipartFile file){
              //获取上传文件
              //返回上传到oss的路径
              String url= ossService.uploadFileAvatar(file);
              return R.ok().data("url",url);
          }
      }
      
    2. 在 service 实现上传文件到oss的过程

      @Service
      public class OssServiceImpl implements OssService {
          //上传头像到oss
          @Override
          public String uploadFileAvatar(MultipartFile file) {
              // 工具类获取值
              String endpoint = ConstantPropertiesUtils.END_POINT;
              String accessKeyId = ConstantPropertiesUtils.ACCESS_KEY_ID;
              String accessKeySecret = ConstantPropertiesUtils.ACCESS_KEY_SECRET;
              String bucketName = ConstantPropertiesUtils.BUCKET_NAME;
      
              try{
                  // 创建OSSClient实例。
                  OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
      
                  //获取上传文件输入流
                  InputStream inputStream=file.getInputStream();
      
                  //获取文件名称
                  String fileName = file.getOriginalFilename();
                  //调用oss方法上传
                  //第一个参数 Bucket名称
                  // 第二个参数 上传到oss文件路径和文件名称  aa/bb/1.jpg
                  // 第三个参数 上传文件输入流
                  ossClient.putObject(bucketName,fileName,inputStream);
      
                  //关闭对象
                  ossClient.shutdown();
      
                  //把上传之后文件路径返回
                  //需要把上传到阿里云oss路径手动拼接出来
                  //https://edu-20210705.oss-cn-beijing.aliyuncs.com/01.jpg
                  String url="https://"+bucketName+"."+endpoint+"/"+fileName;
                  return url;
              }catch (Exception e){
                  e.printStackTrace();
                  return null;
              }
          }
      }
      

      在这里插入图片描述

在这里插入图片描述

完善接口

  1. 多次上传相同名称文件,造成最后一次上传把之前上传文件覆盖

    在文件名称添加随机唯一值,让每个文件名称不同

在这里插入图片描述

  1. 把文件进行分类管理

    根据日期进行分类

    在这里插入图片描述

  2. swagger测试

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

添加讲师实现上传头像前端整合

  1. 添加上传组件

在这里插入图片描述

  1. 页面使用组件

    data()中定义变量和初始值在这里插入图片描述

  2. 引入组件声明组件

在这里插入图片描述

  1. 修改上传接口地址

    在这里插入图片描述

  2. 编写close方法和上传成功方法

  3. 测试结果

    数据库中加入在这里插入图片描述

    即使上传的是jpg格式,最后也会是png,是因为上传文件可能有中文,框架,组件统一改成了file.png

nginx(反向代理服务器)

请求转发

在这里插入图片描述

负载均衡

在这里插入图片描述

动静分离

把 java 代码和普通 HTML 这种页面请求分离,访问不同内容

应用场景

  1. 配置 nginx 实现转发功能

在这里插入图片描述

  1. 在 nginx.conf 进行配置

    1. 修改默认80端口为81

    2. 配置转发规则

      在这里插入图片描述

    3. 修改前端请求地址为 nginx 地址

      在这里插入图片描述

添加课程分类功能

二级分类

在这里插入图片描述

使用 EasyExcel 进行 写 操作

  1. 引入依赖

    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>easyexcel</artifactId>
            <version>2.1.1</version>
        </dependency>
    </dependencies>
    
  2. 创建实体类,与Excel对应

    @Data
    public class DemoData {
        //设置表头名称
        @ExcelProperty("学生编号")
        private  Integer sno;
        @ExcelProperty("学生姓名")
        private  String sname;
    }
    
  3. 在这里插入图片描述

  4. 在这里插入图片描述

使用 EasyExce 进行 读 操作

  1. 创建对应实体类

    @Data
    public class DemoData {
        //设置表头名称
        @ExcelProperty(value = "学生编号",index = 0)
        private  Integer sno;
        @ExcelProperty(value = "学生姓名",index = 1)
        private  String sname;
    }
    
  2. 创建 监听 进行读取

    public class ExcelListener extends AnalysisEventListener<DemoData> {
        //一行一行读取Excel内容
        @Override
        public void invoke(DemoData data, AnalysisContext analysisContext) {
            System.out.println("****"+data);
        }
        //读取表头内容
        @Override
        public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
            System.out.println("表头:"+headMap);
        }
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    
        }
    }
    
  3. 方法调用

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

课程分类添加功能

  1. 使用代码生成器把课程分类代码生成

  2. 创建实体类

    @Data
    public class SubjectData {
    
        @ExcelProperty(index = 0)
        private int oneSubjectName;
    
        @ExcelProperty(index = 1)
        private String twoSubjectName;
    }
    
  3. 创建监听

    public class SubjectExcelListener extends AnalysisEventListener<SubjectData> {
    
        //因为SubjectExcelListener不能交给Spring管理,需要自己new,不能注入其他对象,不能自动实现数据库操作
    
        public EduSubjectService subjectService;
        public SubjectExcelListener(){}
        public SubjectExcelListener(EduSubjectService subjectService) {
            this.subjectService = subjectService;
        }
    
        //读取内容,一行一行读
        @Override
        public void invoke(SubjectData subjectData, AnalysisContext analysisContext) {
            if (subjectData==null){
                throw new GuliException(20001,"文件数据为空");
            }
    
            //一行一行读取,每次读取两个值,第一个值一级分类,第二个值二级分类
            //判断一级分类是否重复
            EduSubject existOneSubject = this.existOneSubject(subjectService, subjectData.getOneSubjectName());
            if (existOneSubject==null){
                //没有相同的一级分类,进行添加
                existOneSubject=new EduSubject();
                existOneSubject.setParentId("0");
                existOneSubject.setTitle(subjectData.getOneSubjectName());//一级分类名称
                subjectService.save(existOneSubject);
            }
    
            //获取一级分类ID值
            String pid=existOneSubject.getId();
            //添加二级分类
            //判断二级分类是否重复
            EduSubject existTwoSubject = this.existTwoSubject(subjectService, subjectData.getTwoSubjectName(), pid);
            if (existTwoSubject==null){
                existTwoSubject=new EduSubject();
                existTwoSubject.setParentId(pid);
                existTwoSubject.setTitle(subjectData.getTwoSubjectName());//二级分类名称
                subjectService.save(existTwoSubject);
            }
        }
    
        //判断一级分类不能重复添加
        private EduSubject existOneSubject(EduSubjectService eduSubjectService,String name){
            QueryWrapper<EduSubject> wrapper=new QueryWrapper<>();
            wrapper.eq("title",name);
            wrapper.eq("parent_id","0");
            EduSubject oneSubject=subjectService.getOne(wrapper);
            return oneSubject;
        }
    
        //判断二级分类不能重复添加
        private EduSubject existTwoSubject(EduSubjectService eduSubjectService,String name,String pid){
            QueryWrapper<EduSubject> wrapper=new QueryWrapper<>();
            wrapper.eq("title",name);
            wrapper.eq("parent_id",pid);
            EduSubject twoSubject=subjectService.getOne(wrapper);
            return twoSubject;
        }
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    
        }
    }
    
  4. 结果

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TeETFrRU-1625554321498)(C:\Users\User\AppData\Roaming\Typora\typora-user-images\image-20210706144736342.png)][外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j2hBGDRD-1625554321499)(C:\Users\User\AppData\Roaming\Typora\typora-user-images\image-20210706144755635.png)]

注意问题

  1. 监听中要判断一级分类,二级分类是否重复

  2. nginx 要在cmd使用命令 nginx.exe -s stop关掉

  3. 配置nginx时不要把server写在http外面

            existTwoSubject=new EduSubject();
            existTwoSubject.setParentId(pid);
            existTwoSubject.setTitle(subjectData.getTwoSubjectName());//二级分类名称
            subjectService.save(existTwoSubject);
        }
    }
    
    //判断一级分类不能重复添加
    private EduSubject existOneSubject(EduSubjectService eduSubjectService,String name){
        QueryWrapper<EduSubject> wrapper=new QueryWrapper<>();
        wrapper.eq("title",name);
        wrapper.eq("parent_id","0");
        EduSubject oneSubject=subjectService.getOne(wrapper);
        return oneSubject;
    }
    
    //判断二级分类不能重复添加
    private EduSubject existTwoSubject(EduSubjectService eduSubjectService,String name,String pid){
        QueryWrapper<EduSubject> wrapper=new QueryWrapper<>();
        wrapper.eq("title",name);
        wrapper.eq("parent_id",pid);
        EduSubject twoSubject=subjectService.getOne(wrapper);
        return twoSubject;
    }
    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
    
    }
    

    }

    
    
  4. 结果

    swagger测试数据库结果

注意问题

  1. 监听中要判断一级分类,二级分类是否重复
  2. nginx 要在cmd使用命令 nginx.exe -s stop关掉
  3. 配置nginx时不要把server写在http外面
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值