熬夜写的 你们两个给我好好看
如遇图片无法正常加载 请代理访问
介绍
若依:你若不离不弃,我必生死相依
国内比较流行的前后端管理框架
环境要求
- JDK >= 1.8
- MySQL >= 5.7
- Maven >= 3.0
若依文档
安装
克隆或解压后的目录是这样的
其中service 为 RuoYi-service 即 springboot
sql 是 数据库文件(此处是mysql)
管理前端和用户前端 为 RuoYi-ui 即 Vue3
然后分别用vscode 和 IDEA 打开项目
[{"url":"/data/img/2024/10/02.png","alt":"vscode"},{"url":"/data/img/2024/10/03.png","alt":"idea"}]
后端部分
配置mysql数据库
导入部分就不多说了
我们讲配置数据库的部分
找到Neuedu-admin 部分
修改主机地址、数据库库名、用户名和密码
(根据你的数据库信息来修改)
然后稍微往上回滚 找到redis部分 修改数据库地址、端口号、密码
为了减少你们的工作量,这个redis的配置信息写我的
Redis配置
- IP:不便公开,会贴在群里
- Port: 6379
- Pwd: 不便公开,会贴在群里
同样 除了 dev 配置外,还有 prod 配置 也一样
[{"url":"/data/img/2024/10/07.png","alt":"配置mysql数据库 "},{"url":"/data/img/2024/10/08.png","alt":"配置redis数据库 "}]
配置swagger文档
不知道还记不记得 swagger是接口文档 提供了在线的接口调用及测试
配置文件在 Neuedu-admin/src/main/java/com/neuedu/web/core/config
下的SwaggerConfig.java
人家框架已经全部写好了
我们只要在入口文件的主函数上 加 @EnableSwagger2
的注解 就可以开启了
同时根据官网的参考
他加上了
1 2 3 4 5 6 7 8 9 10 11 12
| System.out.println("(♥◠‿◠)ノ゙ Swagger启动成功 ლ(´ڡ`ლ)゙ \n" + " .-------. ____ __ \n" + " | _ _ \\ \\ \\ / / \n" + " | ( ' ) | \\ _. / ' \n" + " |(_ o _) / _( )_ .' \n" + " | (_,_).' __ ___(_ o _)' \n" + " | |\\ \\ | || |(_,_)' \n" + " | | \\ `' /| `-' / \n" + " | | \\ / \\ / \n" + " ''-' `'-' `-..-' ");
|
然后就可以右上角点击运行了
当控制台输出 JVM running for 6.931
(♥◠‿◠)ノ゙ Swagger启动成功 ლ(´ڡ
ლ)゙` 字样时 就说明后端的服务跑起来了
我们可以打开 http://localhost:9090/swagger-ui/index.html 访问 用最简单的方式验证服务是否正常
或者你直接访问 http://localhost:9090/ 也可
[{"url":"/data/img/2024/10/09.png","alt":"配置swagger"},{"url":"/data/img/2024/10/10.png","alt":"配置swagger"},{"url":"/data/img/2024/10/11.png","alt":"运行"},{"url":"/data/img/2024/10/12.png","alt":"swagger验证"},{"url":"/data/img/2024/10/13.png","alt":"ruoyi验证"}]
前端部分
下载依赖/运行
这里我用的是cnpm 包管理工具
npm也行 但是自六月以来我的npm 不论 怎么换源 都特别慢 所以换了cnpm
你可以执行以下命令 先全局安装cnpm
然后执行cnpm install
这样或许会快些 当然如果你本身没问题 就无需如此
可能过程会报一些红色的deprecate
但是无伤大雅 继续执行 npm run dev
当你分别在80 和 18183 端口 看到以下页面 说明 前端你也准备就绪了
如果你跟着到了这里 那么恭喜你 可以正式开始进行作业了
[{"url":"/data/img/2024/10/14.png","alt":"前端"},{"url":"/data/img/2024/10/15.png","alt":"前端"},{"url":"/data/img/2024/10/16.png","alt":"前端"},{"url":"/data/img/2024/10/17.png","alt":"前端"}]
开发
需求概要
都说不打无准备之仗
试题嘛 总是有那么一个文档
pdf 或者 word 十几二十页的 这将作为我们整个开发过程的指南、说明书
本篇文章主要针对试题的第二模块进行简单介绍
这部分模块55’
且试题篇幅大概五六页
我给这部分内容总结如下
不要在意下面的数字
没错 我只是想看看我需要多少时间 但事实我花了不止几个小时

代码生成
了解需求后 来看看若依提供的代码生成工具
没错 就是下一小节cv大法的前摇
虽然这个过程由框架替你完成了本该做的开发工作
但是还是得要来看一看 这个代码生成的整个过程
(本来想说原理的 但好像我表述出来还是跟过程一样 遂改过程)
首先 进入代码生成器界面(管理前端):系统工具
-> 代码生成
在这里可以看到数据库中所有表的列表
选择表生成代码:在表列表中 选择要生成代码的表 点击生成
按钮 弹出代码生成配置界面
配置生成选项:在代码生成配置界面 可以设置生成代码的包路径 模块名称 作者信息等 配置完成后 点击生成
按钮 即可生成对应的代码文件
查看生成代码:选择压缩包的形式 可以自动下载 压缩包 解压后可查看 生成的代码文件
模板定制:模板文件位于 neuedu-generator/src/main/resources/vm
目录下 包括实体类模板、Mapper接口模板、Service接口模板、Service实现类模板和Controller类模板
生成逻辑:代码生成器通过读取数据库元数据(表结构和字段信息) 自动生成标准化的代码模板 减少手工编码的工作量 它会查询 information_schema 数据库中的 TABLES 和 COLUMNS 表来获取表结构信息 然后使用 Velocity 模板引擎渲染生成 Java 代码和前端代码
应用生成的代码:将生成的代码应用到项目中后端代码直接拷贝到相应的模块下前端代码拷贝到 ruoyi-ui 模块的相应目录下执行生成的 SQL 脚本来创建菜单和按钮权限 但是在本篇中 我们不需要再次导入生成的数据库 因为已经有人给我们导好 我们只需要完成响应的部分就好了
如果你心细的话 可能会问 mybatis generator
不也是代码生成吗
没错 它也是代码生成 但是它更适合于 数据库脚本
生成代码
也就是仅面向后端的代码生成方案 也是使用 Velocity 来生成 MyBatis 的 Mapper XML 文件、Mapper 接口、Model 类以及 DAO 类等
在它的配置文件中定义需要生成的代码的样式和结构,通过 Velocity 模板来输出最终的代码文件
但是若依提供的代码生成更全面 囊括了前后端 还支持vue2 vue3
另外 刚刚提到的 mybatis
(不是 mybatis generator
) 相当于持久化框架,与 JPA
类似,面向对象操作数据库,将数据库中的表映射成对象,行映射成对象的属性,从而可以对这些对象进行操作,同时提供了一组工具用于简化数据库操作。
参考 https://ruoyi.csdn.net/657052ab9820e81a16d962b9.html
[{"url":"/data/img/2024/10/18.png","alt":"代码生成"},{"url":"/data/img/2024/10/19.png","alt":"代码生成"},{"url":"/data/img/2024/10/20.png","alt":"代码生成"},{"url":"/data/img/2024/10/21.png","alt":"代码生成"},{"url":"/data/img/2024/10/22.png","alt":"代码生成"},{"url":"/data/img/2024/10/23.png","alt":"代码生成"}]
cv大法
终于到 cv大法了
很好 我知道上面步骤没说清楚 但是图片演示的很到位了
我要故意说的高级 然后用简单操作做高端的应用
你们不明白上一小节仔细揣摩
接下来让我传授你们cv大法
不理解cv有什么好讲的
(代码量很多 我怕你们找不到对应的文件)
不过既然是cv我就不细赘了
cv完之后 后端记得重启
上图
[{"url":"/data/img/2024/10/24.png","alt":"cv"},{"url":"/data/img/2024/10/25.png","alt":"cv"},{"url":"/data/img/2024/10/26.png","alt":"cv"},{"url":"/data/img/2024/10/27.png","alt":"cv"},{"url":"/data/img/2024/10/28.png","alt":"cv"},{"url":"/data/img/2024/10/29.png","alt":"cv"}]
[{"url":"/data/img/2024/10/30.png","alt":"cv"},{"url":"/data/img/2024/10/31.png","alt":"cv"},{"url":"/data/img/2024/10/32.png","alt":"cv"},{"url":"/data/img/2024/10/33.png","alt":"cv"},{"url":"/data/img/2024/10/34.png","alt":"cv"},{"url":"/data/img/2024/10/35.png","alt":"cv"},{"url":"/data/img/2024/10/36.png","alt":"cv"},{"url":"/data/img/2024/10/37.png","alt":"cv"}]
不过 按照官方文档 最后两个功能还需要在用户前端内各写两个页面 代码贴下面了 样式不好看 你们可以自己改
[{"url":"/data/img/2024/10/38.png","alt":"user"},{"url":"/data/img/2024/10/39.png","alt":"user"},{"url":"/data/img/2024/10/40.png","alt":"user"}]
[{"url":"/data/img/2024/10/41.png","alt":"user"},{"url":"/data/img/2024/10/42.png","alt":"user"},{"url":"/data/img/2024/10/43.png","alt":"user"},{"url":"/data/img/2024/10/44.png","alt":"user"},{"url":"/data/img/2024/10/45.png","alt":"user"}]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| <!-- news --> <!-- list --> <template> <div class="main"> <el-image style="width: 100%" :src="newsBgUrl" fit="fill" /> <div class="breadcrumb-box" v-if="list.length"> <ul class="breadcrumb"> <li v-for="item in list" :key="item.id"> <span class="title">{{ item.title }}</span>
<br> <span class="createTime">发表于 {{ item.createTime }}</span> | <span class="createBy">{{ item.createBy }} </span> | <span class="views">浏览 {{ item.views }} 次</span>
<br>
<span class="content">{{ item.content }}</span>
<br>
<button @click="showNews(item)" class="showBtn">查看</button> <pre style="text-wrap: wrap;">{{ item }}</pre> </li> </ul> </div> <div v-else> <img style="width: 200px;margin-top: 100px;" src="@/assets/images/nodata.png" alt=""> <div style="font-size: 14px;color: #999999;margin-top: 10px;">暂无内容</div> </div> </div> </template>
<script setup> import newsBgUrl from "@/assets/images/news-bg.png"; import { getNewsList } from "@/api/news/news";
const list = ref([]);
const loading = ref(true); const total = ref(0);
const data = reactive({ form: {}, queryParams: { pageNum: 1, pageSize: 10, title: null, content: null, views: null, }, rules: { } });
const { queryParams } = toRefs(data);
/** 查询志愿者信息中心列表 */ function getList() { loading.value = true; getNewsList(queryParams.value).then(response => { list.value = response.rows; total.value = response.total; loading.value = false; }); }
function showNews(item) { // console.log(item.id);
window.open(`/news/detail?id=${item.id}`); }
getList(); </script>
<style lang="scss" scoped>
.breadcrumb-box { width: 60%; margin: 0 auto; .breadcrumb { list-style: none; text-align: left; margin: 0; padding: 0; li { .title { font-size: 20px; font-weight: 700; color: #1F2D3D; } .createBy, .createTime, .views { font-size: 12px; color: #858585; } .content { font-size: 14px; color: #333333; } .showBtn { width: 60px; height: 30px; line-height: calc(30px - 6px); padding: 0px 6px; margin-top: 6px; text-align: center; // background-color: #1F2D3D; // color: #FFFFFF; border-radius: 5px; } } } }
@media screen and (max-width: 768px) {
.breadcrumb-box { width: 90%; }
} </style>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| <!-- news --> <!-- detail --> <template> <div class="main"> <div class="article"> <span class="title">{{ newsDetail.title }}</span>
<br>
<span class="createTime">发表于 {{ newsDetail.createTime }}</span> | <span class="createTime">更新于 {{ newsDetail.updateTime }}</span> | <span class="views">浏览 {{ newsDetail.views }} 次</span>
<br>
<span class="content">{{ newsDetail.content }}</span>
<br> <div class="copyright"> <span class="createBy"><span class="label">发布者:</span> {{ newsDetail.createBy }}</span>
<br>
<span><span class="label">文章链接:</span> <a :href="url">{{ url }}</a></span>
<br>
<span><span class="label">版权声明:</span> 未经许可,不得转载</span> </div> <!-- <span>{{ newsDetail.data.createTime }}</span> <span>{{ newsDetail.data.createBy }}</span> -->
<pre style="text-wrap: wrap;">{{ newsDetail }}</pre>
</div> </div> </template> <script setup name="NewsDetail"> import { ref } from 'vue'; import { getNewsDetail } from "@/api/news/news"; import { useRoute } from "vue-router";
const newsDetail = ref([]); const loading = ref(true); const total = ref(0); const route = useRoute(); const url = computed(() => window.location.origin + route.fullPath);
/** 查询志愿者信息中心列表 */ function getDetail() { loading.value = true; getNewsDetail(route.query.id).then(response => { newsDetail.value = response.data; total.value = response.total; loading.value = false; });
}
getDetail(); </script>
<style lang="scss" scoped> .main { .article { text-align: left; width: 60%; margin: 0 auto; .title { font-size: 35px; font-weight: 700; color: #1F2D3D; border-bottom: 1px solid #eee; } .createTime, .views { font-size: 13px; color: #858585; } .content { display: block; margin-top: 12px; font-size: 14px; color: #333333; } .copyright { margin-top: 16px; font-size: 14px; font-size: 13px; color: #858585; .label { color: #49b1f5; font-weight: bold; } } } }
@media screen and (max-width: 768px) { .main { .article { width: 90%; } } } </style>
|
[{"url":"/data/img/2024/10/46.png","alt":"user"}]
调试
一个好的开发 不会断点也要会调试
已知后端服务端口在9090
那么我们可以使用postman 对接口进行测试
我们会遇到接口的身份校验问题
校验办法如下
[{"url":"/data/img/2024/10/47.png","alt":"user"},{"url":"/data/img/2024/10/48.png","alt":"user"},{"url":"/data/img/2024/10/49.png","alt":"user"},{"url":"/data/img/2024/10/50.png","alt":"user"}]
关于代理
成熟的项目中 并不会直接请求后端接口地址 而是通过代理
如本项目 前端配置了 dev 和 prod 环境
并在vite.config里配置了代理
那么同样的我们在部署的时候 也需要在web服务器里配置对应的代理规则
这样才能使得我们的项目正常发布
[{"url":"/data/img/2024/10/51.png","alt":"proxy"},{"url":"/data/img/2024/10/52.png","alt":"proxy"}]
打包部署
后端
后端项目 直接进入项目根目录下的 bin
目录 执行 package.bat
文件双击即可
打包后的jar 包 生成在Neuedu-admin/target
目录下
直接终端执行 java -jar neuedu-admin.jar
或者 直接双击 run.bat
即可
报错
如遇打包报错
需要确保本地的jre 和 jdk环境
[{"url":"/data/img/2024/10/04.png","alt":"java"}]
前端
vue 项目打包只需要输入 npm run build即可
但还是需要查看package.json文件 里对应的打包指令是否有参数 或者其他指令
打包完之后 会在项目根目录生成dist文件 这就是打包后的静态资源文件
我把打包出来的文件 统一复制到了一个站点目录 重命名为dist01 和 dist02 (名字无所谓)
然后使用小皮面板 分别创建 dist01 和 dist02 的两个站点 端口无所谓 不要被占用即可
然后 找到 小皮面板的 nginx 配置文件
在其安装目录的 Extensions\Nginx1.15.11\conf\vhosts
目录下
分别找到刚才创建的两个站点的配置文件
首先在 location /
下添加try_files 重定向 到index.html
这样刷新后 不会指向404
然后 新建一个 location /prod-api/
配置响应的代理规则
然后重启web服务器
完成后 即可在浏览器通过主机+端口像开发模式下 正常访问 项目了
1
| try_files $uri $uri/ /index.html;
|
1 2 3 4 5 6 7 8
| location /prod-api/ { proxy_pass http://127.0.0.1:9090/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_redirect off; }
|
[{"url":"/data/img/2024/10/60.png","alt":"build"},{"url":"/data/img/2024/10/61.png","alt":"build"},{"url":"/data/img/2024/10/62.png","alt":"build"}]
[{"url":"/data/img/2024/10/53.png","alt":"build"},{"url":"/data/img/2024/10/54.png","alt":"build"},{"url":"/data/img/2024/10/55.png","alt":"build"},{"url":"/data/img/2024/10/56.png","alt":"build"},{"url":"/data/img/2024/10/57.png","alt":"build"},{"url":"/data/img/2024/10/58.png","alt":"build"},{"url":"/data/img/2024/10/59.png","alt":"build"}]
完结撒花
ヾ(≧∇≦*)ゝ🎉🎉🎉🎉🎉🎉