配置git环境与项目创建
概览
使用前后端分离的方式 完成本项目
前端使用vue3完成 后端使用springboot完成
- 项目框架(按页面)
- 项目框架(按架构)
拓展知识点:
关于前后端分离的更多内容:<a href="/vault/2-Learning/05-%E9%A1%B9%E7%9B%AE/04-SpringBoot%E6%A1%86%E6%9E%B6%E8%AF%BE/02-%E9%85%8D%E7%BD%AEgit%E7%8E%AF%E5%A2%83%E4%B8%8E%E9%A1%B9%E7%9B%AE%E5%88%9B%E5%BB%BA/02-%E5%89%8D%E5%90%8E%E7%AB%AF%E5%88%86%E7%A6%BBor%E4%B8%8D%E5%88%86%E7%A6%BB%EF%BC%9F">前后端分离or不分离?</a>
架构知识点扫盲:<a href="/vault/2-Learning/05-%E9%A1%B9%E7%9B%AE/04-SpringBoot%E6%A1%86%E6%9E%B6%E8%AF%BE/02-%E9%85%8D%E7%BD%AEgit%E7%8E%AF%E5%A2%83%E4%B8%8E%E9%A1%B9%E7%9B%AE%E5%88%9B%E5%BB%BA/01-%E5%85%B3%E4%BA%8E%E6%9E%B6%E6%9E%84">关于架构</a>
- 技术栈:
| 技术 | 说明 |
| SpringBoot | 容器+MVC框架 |
| mysql | 关系型数据库 |
| JWT | 登录支持 |
| SpringSecurity | 验证和授权框架 |
| Redis | 缓存数据库 |
| Lombok | 简化对象封装工具 |
| MyBatisPlus | ORM框架 |
| MicroService(SpringCloud) | 微服务 |
- 项目(游戏)设计逻辑:
环境配置与项目创建
主文件夹与仓库连接
创建项目文件夹 /kob
创建仓库 git init
创建readme文件 vim readme.md
git.acwing中创建远程仓库
本地仓库添加用户配置 (不用全局)
C:\code\java\kob>git config user.name "wei zhou"
C:\code\java\kob>git config user.email "zv041118@163.com"
编辑User目录下.ssh/config
Host git.acwing.com
User git
HostName git.acwing.com
IdentityFile C:/Users/zv041/.ssh/wei_01.pem
IdentitiesOnly yes
配置.gitignore 忽略无关项目的中间文件再推送 C:\code\java\kob.gitignore
# 编译输出文件
*.class
*.jar
*.war
*.ear
# Maven 和 Gradle 的构建目录
/build/
/target/
# 忽略 IntelliJ IDEA 文件
/.idea/
/*.iml
# 忽略 VS Code 工作区文件
.vscode/
# 忽略 Eclipse 的项目文件
.project
.classpath
.settings/
# 忽略 MacOS 系统生成的文件
.DS_Store
# 忽略 Windows 系统生成的文件
Thumbs.db
ehthumbs.db
desktop.ini
# 忽略日志文件
*.log
# 忽略临时文件
*.tmp
*.swp
# 忽略 Java 的缓存目录
*.class
*.jar
# 忽略环境配置文件
*.env
# 忽略 Gradle 的缓存文件
.gradle/
/build/
# 忽略 Maven 的输出文件
/target/
# 忽略 IntelliJ IDEA 文件
.idea/
*.iws
*.iml
# 忽略 NetBeans 文件
/nbproject/private/
/build/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
# 忽略 JRebel 重载缓存
.rebel/
# 忽略 JetBrains IDE 编译生成文件
/out/
# 忽略构建脚本生成的二进制文件
*.exe
*.dll
*.so
*.out
# 忽略其他不需要提交的临时文件
*.pid
*.pid.lock
连接远程仓库并推送
git remote add origin git@git.acwing.com:Zwww/kob.git
git status
git add .
git status
git commit -m "readme commit"
git push -u origin master
创建后端项目
环境
nmd 创建的时候用的22 结果换个电脑22说版本过高 傻逼环境
显示在8080端口运行了 (文件标红是因为未被git收录 没关系)
浏览器打开localhost:8080 出现以下界面即为成功
backend创建
前面提到 在springboot的后端主要是用来实现一个函数的 一个链接对应一个函数 负责给用户返回一个页面
那么这个函数应该写在哪 ——新开软件包controller 用于存放所有的后端函数
我们的页面设计有四大类 pk、对局记录、排行榜、用户中心
一个板块对应一个软件包 每个板块的页面应该在对应的包里面
以pk模块为例
示例:
前后端不分离写法
要想将函数变成链接函数的话 加上注解:@Controller
指定页面的父级目录:@RequestMapping("/pk/")
创建测试html
指定返回的页面
让pk/index/返回 刚刚建立的 templates/pk/index.html 页面
编辑 com/zwnsyw/backend/controller/pk/IndexController.java
package com.zwnsyw.backend.controller.pk;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/pk/")
public class IndexController {
@RequestMapping("index/")
public String index(){
return "pk/inedx.html";
}
}
访问http://localhost:8080/pk/index/ 即可查看
另外关于图片的索引: 直接放在resources下 static下新建image文件夹 然后用/image/ 进行索引
所以其实就是 pk模块 就访问http://localhost:8080/pk 之后pk模块下的所有页面 什么主页 对战信息 就一一对应在http://localhost:8080/pk/index/、http://localhost:8080/pk/message/
然后其他模块也以此类推
如果是前后端不分离的话 以这种逻辑就可以直接编写代码了
前后端分离写法
前后端分离的话 返回的就不是一个页面 而是一些信息 注解也由@Controller变为@RestController
package com.zwnsyw.backend.controller.pk;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class BotinfoController {
}
就这样成功返回一个字符串
同理也可以返回链表、字典等等数据信息
package com.zwnsyw.backend.controller.pk;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/pk/")
public class BotinfoController {
@RequestMapping("getbotinfo/")
public List<Map<String, String>> getBotInfo(){
List<Map<String,String>> list=new LinkedList<>();
Map<String,String> bot1=new HashMap<>();
bot1.put("name","tiger");
bot1.put("rating","1500");
Map<String,String> bot2=new HashMap<>();
bot2.put("name","apple");
bot2.put("rating","1200");
list.add(bot1);
list.add(bot2);
return list;
}
}
修改端口
在application.properties加上server.port=3000
创建前端项目
环境
设置镜像地址,安装vue (前提先下好node,js)
node,js直接官网安装 Win+R输入cmd, 输入node -v确认安装上了
设置镜像地址,安装vue
npm config set registry https://registry.npmmirror.com #设置镜像地址
npm install -g cnpm
cnpm install -g @vue/cli
vue -V #检查vue版本,确认安装上了注意是大写V
vue ui #如果上面显示版本号了就可以启动了
web创建
点击创建 找到之前创建的kob项目文件夹 在此新建项目
添加插件
安装依赖 jquery、bootstrap
配置完如下:
运行
得到一个地址: http://localhost:8080/
得到以下界面即成功
acapp创建
左上角 项目管理器 同理再创建一个项目 acapp
这里插件只要装 vue-x 路由不用装
依赖也不需要装
直接serve 运行
至此项目文件夹构建完成
搭建项目骨架
web
开启web服务
进入web服务给出的http://localhost:8080/#/
发现报错 打开vscode
修改本行
删除不必要的代码
web\src\router\index.js 修改为 (删除两个hash)
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
这样以来浏览器中的网址就可以删除/#了
删除
web\src\views\AboutView.vue
web\src\views\HomeView.vue
web\src\components\HelloWorld.vue
修改web\src\App.vue 为 (删除css和
<template>
<div>
Hello World
</div>
<router-view></router-view>
</template>
修改web\src\router\index.js为
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
现在就变得非常干净了
测试前后端通信
后端
开启后端backend服务
前面BotinfoController实现了返回一个列表(数据) 现在测试能否在前端接收到这个信息 实现前后端的交互
修改backend/src/main/java/com/zwnsyw/backend/controller/pk/BotinfoController.java为 (列表嵌套map过于复杂 测试通信没必要)
package com.zwnsyw.backend.controller.pk;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/pk/")
public class BotinfoController {
@RequestMapping("getbotinfo/")
public Map<String, String> getBotInfo(){
Map<String,String> bot1=new HashMap<>();
bot1.put("name","tiger");
bot1.put("rating","1500");
return bot1;
}
}
前端
修改App.vue
<template>
<div>
<div>Bot昵称:{{ bot_name }}</div>
<div>Bot战力:{{ bot_rating }}</div>
</div>
<router-view></router-view>
</template>
import $ from 'jquery';
import { ref } from 'vue';
export default{
name:"App",
setup:() => {
// 定义响应式变量 bot_name 和 bot_rating,用于存储从 API 获取的数据
let bot_name=ref("");
let bot_rating=ref("");
// 使用 jQuery 的 ajax 方法发起 GET 请求,获取机器人信息
$.ajax({
url: "http://localhost:3000/pk/getbotinfo/",// 请求的 URL(本地服务器的一个 API 端点)
type: "get",// 请求类型为 GET
success: resp=>{
// 成功获取响应后,在控制台输出响应数据
console.log(resp);
}
});
// 返回变量,使得模板中可以使用 bot_name 和 bot_rating
return {
bot_name,
bot_rating
}
}
}
发生跨域问题 (CORS policy)
因为前后端所在端口不同 发送请求时会被浏览器阻止
前端(在 localhost:8080 上运行)向服务器(localhost:3000)发起请求时,服务器没有返回 Access-Control-Allow-Origin 头信息,导致浏览器基于
CORS 策略阻止了该请求。CORS 是一种浏览器安全机制,用来防止不安全的跨域请求。
解决:
在根包下创建config包
在该包下创建 CorsConfig类
粘贴以下代码
package com.zwnsyw.backend.config;
import org.springframework.context.annotation.Configuration;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
@Configuration
public class CorsConfig implements Filter {
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
String origin = request.getHeader("Origin");
if (origin!= null) {
response.setHeader("Access-Control-Allow-Origin", origin);
}
String headers = request.getHeader("Access-Control-Request-Headers");
if (headers!= null) {
response.setHeader("Access-Control-Allow-Headers", headers);
response.setHeader("Access-Control-Expose-Headers", headers);
}
response.setHeader("Access-Control-Allow-Methods", "*");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
chain.doFilter(request, response);
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
重启服务
刷新页面
成功获取
让获取到的数据在前端页面显示
修改App.vue
<template>
<div>
<div>Bot昵称:{{ bot_name }}</div>
<div>Bot战力:{{ bot_rating }}</div>
</div>
<router-view></router-view>
</template>
import $ from 'jquery';
import { ref } from 'vue';
export default{
name:"App",
setup:() => {
// 定义响应式变量 bot_name 和 bot_rating,用于存储从 API 获取的数据
let bot_name=ref("");
let bot_rating=ref("");
// 使用 jQuery 的 ajax 方法发起 GET 请求,获取机器人信息
$.ajax({
url: "http://localhost:3000/pk/getbotinfo/",// 请求的 URL(本地服务器的一个 API 端点)
type: "get",// 请求类型为 GET
success: resp=>{
bot_name.value=resp.name;
bot_rating.value=resp.rating;
}
});
// 返回变量,使得模板中可以使用 bot_name 和 bot_rating
return {
bot_name,
bot_rating
}
}
}
刷新页面
成功显示:
成功通信
分析
我们在vue里写的所有的代码 都是在用户浏览器里执行的(用户在打开网页时 先会把vue里敲的代码全部下载下来 然后一一往下执行 执行到我们的js 去向服务器发送请求
后端服务器接收到请求后 看那个url要访问的是哪个函数 (看@Controller下的路径 跟着@RequestMapping一直找到我们写的那个函数 执行完后 将函数的执行结果返回给前端(用户浏览器) 用户拿到这些执行结果(数据)后 会将前端的留白值 换成我们得到的那个值
整个流程概述:
- 前端代码下载并执行:
- 当用户在浏览器中访问一个页面(例如输入一个 URL),浏览器会向服务器请求这个页面的 HTML 文件。这时,Vue.js 相关的代码(包括 Vue 的组件、脚本、样式等)也会被打包并下载到浏览器。
- 一旦浏览器加载了这些文件,它会解析 HTML 文件,解析并执行下载下来的 JavaScript 代码。这时候,Vue.js 的框架代码就会运行并开始初始化组件、绑定数据和事件监听。
- 向后端发送请求:
- 当需要从服务器获取数据(例如通过用户点击按钮或页面加载时),Vue.js 会通过 JavaScript 代码(通常是
axios、fetch或jQuery.ajax)向服务器发送一个请求。 - 这个请求包含 URL、请求方法(如 GET、POST)、请求头和请求体等信息。
- 当需要从服务器获取数据(例如通过用户点击按钮或页面加载时),Vue.js 会通过 JavaScript 代码(通常是
- 后端服务器处理请求:
- 服务器接收到这个请求后,会根据请求的 URL 和请求方法,找到对应的处理函数(例如在 Spring Boot 中,通过
@Controller和@RequestMapping注解)。 - 服务器中的函数(控制器)处理这个请求,执行必要的业务逻辑(如查询数据库、计算数据、验证用户等)。
- 当业务逻辑处理完成后,服务器会将结果(通常是 JSON 格式的数据)打包在 HTTP 响应中,并返回给前端。
- 服务器接收到这个请求后,会根据请求的 URL 和请求方法,找到对应的处理函数(例如在 Spring Boot 中,通过
- 前端接收响应并更新页面:
- 前端接收到后端的响应后,会执行与之相关的回调函数。通常在回调函数中,会使用 Vue.js 的响应式变量将返回的数据赋值给绑定的数据属性。
- Vue.js 会自动根据这些响应式数据的变化更新页面(Vue 的响应式原理)。这时,页面上原本的留白(或者占位符)就会被新的数据替换,从而展现在用户眼前。
具体的例子(步骤解释):
- 用户访问
http://localhost:8080/页面,浏览器向服务器请求页面,并下载了 Vue.js 打包后的前端代码(例如.js文件)。 - 浏览器解析并执行这些 Vue.js 代码,页面上展示初始的内容和组件,但由于数据尚未获取,可能显示一些占位符或“加载中”。
- 在 Vue.js 的生命周期钩子(如
mounted)中,前端代码向后端服务器(例如http://localhost:3000/api/getdata)发送请求。 - 服务器的控制器(如
@Controller和@RequestMapping("/api")配置的路径)找到处理该请求的函数,处理并返回数据。 - Vue.js 接收到服务器返回的数据后,将这些数据赋值给响应式变量,Vue.js 自动更新页面中相关的内容,使用户看到新的数据。
几个关键点:
- Vue.js 的代码在浏览器中执行:Vue.js 的代码在用户的浏览器中运行,浏览器会先下载前端代码再执行。
- 发送请求到服务器:通过 JavaScript 代码发送 HTTP 请求,通常会在特定的事件触发后或者页面加载时自动发送。
- 后端路由处理请求:服务器接收到请求后,根据 URL 找到对应的处理函数进行逻辑处理。
- 前后端数据交互:后端将处理结果返回给前端,前端用返回的数据更新页面。
通过这些步骤,前后端共同协作,动态生成和更新页面内容。这样的模式使得 Vue.js 与现代的前后端分离架构配合得非常流畅。
关于注解(了解)?只做了解即可
vue图片目录
美化一下 顺便了解vue框架的图片存放目录 assets 用@/ 引用
\kob\web\src\assets
App.vue中添加style
body{
background-image: url("@/assets/bg.jpg");
background-size: cover;
}
完美
项目分区导航: 在O(1)时间删除链表结点 ⬅️ | 00-配置git环境与项目创建 | ➡️ 关于架构
💬 评论