Egg框架搭建后台服务【1】
需求
博客系统升级,本来是用 express 写的,最近发现 Egg 不错,正好学习升级一下。边学边写。
Ps:相同的功能,迭代的写法,由浅入深,做个记录。
开发
初始化
安装
node版本需要 >=14.20.0, LTS版本最低要求 8.x,npm版本 >=6.1.0
mkdir egg-blogs && cd egg-blogs
npm init egg --type=simple
npm install
npm run dev
默认启动的是 7001 端口。
创建目录结构
egg-blogs
├── package.json
├── app
| ├── router.js
│ ├── controller
│ | └── home.js
│ ├── service
│ | └── user.js
│ ├── middleware
│ └── extend
│ ├── helper.js
├── config
| ├── plugin.js
| ├── config.default.js
安装&配置插件
npm i --save egg-mysql
在 config/plugin.js 中配置
/** @type Egg.EggPlugin */
module.exports = {// had enabled by egg// static: {// enable: true,// }mysql: {enable: true,package: 'egg-mysql'}
};
在 config/config.default.js 中配置数据库信息
/* eslint valid-jsdoc: "off" *//*** @param {Egg.EggAppInfo} appInfo app info*/
module.exports = appInfo => {/*** built-in config* @type {Egg.EggAppConfig}**/const config = exports = {};// use for cookie sign key, should change to your own and keep securityconfig.keys = appInfo.name + '123';// add your middleware config hereconfig.middleware = [];// 关闭安全配置config.security = {xframe: {enable: false,},csrf: {enable: false,}};// 添加mysql配置config.mysql = {client: {host: '127.0.0.1',port: 3306,user: 'root',password: '12345678',database: 'blogs',charset: 'utf8'},app: true,agent: false,};// add your user config hereconst userConfig = {// myAppName: 'egg',};return {...config,...userConfig,};
};
开发逻辑
Controller
创建 app/controller/tags.js
const {Controller} = require('egg');class TagsController extends Controller {/** 获取标签列表 */async getTagList() {await this.ctx.service.tags.getTagList(this.ctx.request.query);}/** 新建标签 */async createTag() {await this.ctx.service.tags.createTag(this.ctx.request.body);}/** 更新标签 */async updateTag() {await this.ctx.service.tags.updateTag(this.ctx.request.body);}/** 删除标签 */async deleteTag() {await this.ctx.service.tags.deleteTag(this.ctx.request.query);}
}module.exports = TagsController;
Service
创建 app/service/tags.js
const {Service} = require('egg');class TagsService extends Service {async getTagList(params) {const {ctx, app} = this;const tagName = params?.tagName || '';const result = await app.mysql.query('SELECT * FROM tag WHERE tagName LIKE "%' + tagName + '%" ORDER BY create_time DESC')// 判断是否成功const isSuccess = result && Array.isArray(result);if (isSuccess) {ctx.state = 200;ctx.body = {code: 200,success: true,data: result,msg: '获取标签数据成功',show: false}} else {ctx.state = 200;ctx.body = {code: 500,success: false,msg: '获取标签数据失败',show: true}}}async createTag(params) {const {ctx, app} = this;const tagInfo = {id: ctx.helper.snowflakeId(),tagName: params.tagName,tagColor: params.tagColor,remark: params.remark,create_time: app.mysql.literals.now,update_time: app.mysql.literals.now}const result = await app.mysql.insert('tag', tagInfo);if (result.affectedRows === 1) {ctx.status = 200;ctx.body = {code: 200,success: true,data: tagInfo,msg: '创建标签成功',show: true}} else {ctx.status = 200;ctx.body = {code: 500,success: false,msg: '创建标签失败',show: true}}}async updateTag(params) {const {ctx, app} = this;const tagInfo = {id: params.id,tagName: params.tagName,tagColor: params.tagColor,remark: params.remark,update_time: app.mysql.literals.now}const result = await app.mysql.update('tag', tagInfo);const isSuccess = result && result.affectedRows === 1;if (isSuccess) {ctx.status = 200;ctx.body = {code: 200,success: true,data: tagInfo,msg: '修改标签成功',show: true}} else {ctx.status = 200;ctx.body = {code: 500,success: false,msg: '修改标签失败',show: true}}}async deleteTag(params) {const {ctx, app} = this;const ids = params.ids.split(',');const result = await app.mysql.beginDoomedTransactionScope(async (conn) => {for (let i = 0; i < ids.length; i++) {await app.mysql.delete('tag', {id: ids[i]});}return {success: true}}, ctx);if (result.success) {ctx.status = 200;ctx.body = {code: 200,success: true,msg: '删除标签成功',show: true}} else {ctx.status = 200;ctx.body = {code: 500,success: false,msg: '删除标签失败',show: true}}}
}module.exports = TagsService;
暴露路由
在 app/router.js 中暴露路由接口
/*** @param {Egg.Application} app - egg application*/
module.exports = app => {const {router, controller} = app;router.get('/', controller.home.index);// 操作标签router.get('/tags/getTagList', controller.tags.getTagList);router.post('/tags/createTag', controller.tags.createTag);router.put('/tags/updateTag', controller.tags.updateTag);router.delete('/tags/deleteTag', controller.tags.deleteTag);
};
总结
基础增删改查完成,但是当前状态最好不要部署在服务器上。
问题:
- 安全防护并未打开
- SQL防注入语法不对
- 直接操作数据库不规范、不标准
- 各类安全措施没有增加
- 各类数据校验没有增加
相关文章:
Egg框架搭建后台服务【1】
需求 博客系统升级,本来是用 express 写的,最近发现 Egg 不错,正好学习升级一下。边学边写。 Ps:相同的功能,迭代的写法,由浅入深,做个记录。 开发 初始化 安装 node版本需要 >14.20.0…...
Unity的Camera类——视觉掌控与深度解析(下)
前言 欢迎阅读本篇博客,这章我们将深入探讨 Unity 游戏引擎中 Camera 类的委托和枚举。摄像机在游戏开发中扮演着关键角色,它不仅定义了玩家视角的窗口,还影响着游戏的视觉表达和整体体验。理解和正确使用 Camera 类的枚举和委托,…...
【模型评估 06】超参数调优
对于很多算法工程师来说,超参数调优是一件非常头疼的事情。除了根据经验设定所谓的“合理值”之外,一般很难找到合理的方法去寻找超参数的最优取值。而与此同时,超参数对于模型效果的影响又至关重要。有没有一些可行的办法去进行超参数的调优…...

Matlab 字符识别OCR实验
Matlab 字符识别实验 图像来源于屏幕截图,要求黑底白字。数据来源是任意二进制文件,内容以16进制打印输出,0-9a-f’字符被16个可打印字符替代,这些替代字符经过挑选,使其相对容易被识别。 第一步进行线分割和字符分割…...
Docker Compose 部署 jenkins
Docker Compose 部署 jenkins jenkins 部署 Docker-Compose 部署 version: 3.1 services:jenkins:image: jenkinsci/blueoceanvolumes:- /data/jenkins/:/var/jenkins_home- /var/run/docker.sock:/var/run/docker.sock- /usr/bin/docker:/usr/bin/docker- /usr/lib/x86_64-…...
QT:使用QStyle实现QMenu的滚动效果
项目中,使用QMenu,多个QAction时 超出页面范围,需要菜单栏可以上下滚动。 实际QMenu是带滚动的,但是要知道怎么使用 还是需要查看QT源码,现在简单记录下我的使用方法。 QT源码中:q->style()->style…...

双指针问题——求只包含两个元素的最长连续子序列(子数组)
一,题目描述 你正在探访一家农场,农场从左到右种植了一排果树。这些树用一个整数数组 fruits 表示,其中 fruits[i] 是第 i 棵树上的水果 种类 。 你想要尽可能多地收集水果。然而,农场的主人设定了一些严格的规矩,你必…...

Unity组件开发--短连接HTTP
1.网络请求管理器 using LitJson; using Cysharp.Threading.Tasks; using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking; using UnityEngine.Events;using System.Web; using System.Text; using Sy…...
真正的强大,原来是不动声色的
当一个人走过了绝境,他就会发现,真正的强大,原来是不动声色的。 他会停止一切自证,不再解释,话越来越少,眼神越来越坚定。 他不再模棱两可,唯唯诺诺,而是敢于断然拒绝,…...
git 查看tag和创建tag以及上传tag命令
文章目录 git 查看tag和创建tag以及上传tag命令git tagtag操作常用命令 git 查看tag和创建tag以及上传tag命令 git tag 如果你达到一个重要的阶段,并希望永远记住那个特别的提交快照,你可以使用 git tag 给它打上标签。 Git 的 tag 功能是一个非常有用…...

代码随想录二刷 |二叉树 | 二叉搜索树的最小绝对差
代码随想录二刷 |二叉树 | 二叉搜索树的最小绝对差 题目描述解题思路 & 代码实现递归法迭代法 题目描述 530.二叉搜索树的最小绝对差 给你一棵所有节点为非负值的二叉搜索树,请你计算树中任意两节点的差的绝对值的最小值。 示例&#…...

【Linux】Linux 系统编程——tree 命令
文章目录 1. 命令概述2. 命令格式3. 常用选项4. 相关描述4.1 tree 命令安装 5. 参考示例5.1 创建树形目录5.2 使用 tree 命令查看树形目录 1. 命令概述 tree 命令用于在命令行界面以树状图形式显示目录及其子目录的内容。这个命令递归地列出所有子目录,并可选择显示…...
Android简单控件
1.文本显示 设置文本内容的两种方式: 在XML文件中通过属性 android:text 设置文本 <resources><string name"app_name">chapter03</string><string name"hello">你好,世界</string> </resources&…...

【Java 干货教程】Java实现分页的几种方式详解
一、前言 无论是自我学习中,还是在工作中,固然会遇到与前端搭配实现分页的功能,发现有几种方式,特此记录一下。 二、实现方式 2.1、分页功能直接交给前端实现 这种情况也是有的,(根据业务场景且仅仅只能用于数据量…...

关于Python里xlwings库对Excel表格的操作(三十一)
这篇小笔记主要记录如何【如何使用“Chart类”、“Api类"和“Axes函数”设置绘图区外框线型、颜色、粗细及填充颜色】。前面的小笔记已整理成目录,可点链接去目录寻找所需更方便。 【目录部分内容如下】【点击此处可进入目录】 (1)如何安…...
QML使用QCustomPlot笔记
这里在QML中使用QCustomPlot是定义一个继承自QQuickPaintedItem的类,它包含一个QCustomPlot对象,在paint函数中将这个对象转化为pixmap绘制到布局中显示。 在QML中使用QT的Widget控件也可以借鉴这个思路实现 顺便记录一下QCustomPlot的简单设置与使用。…...

【REST2SQL】06 GO 跨包接口重构代码
【REST2SQL】01RDB关系型数据库REST初设计 【REST2SQL】02 GO连接Oracle数据库 【REST2SQL】03 GO读取JSON文件 【REST2SQL】04 REST2SQL第一版Oracle版实现 【REST2SQL】05 GO 操作 达梦 数据库 对所有关系数据的操作都只有CRUD,采用Go 的接口interface{}重构代码…...

《NLP入门到精通》栏目导读
一、说明 栏目《NLP入门到精通》本着从简到难得台阶式学习过度。将自然语言处理得知识贯穿过来。本栏目得前导栏目是《深度学习》、《pytorch实践》,因此,读者需要一定得深度学习基础,才能过度到此栏目内容。 二、博客建设理念 本博客基地&am…...

C++学习笔记——类继承
目录 一、一个简单的基类 1.1封装性 1.2继承性 1.3虚函数 1.4多态性 二、基类 2.1一个简单的C基类的示例 2.2 Animal是一个基类。 三、继承 3.1概念 3.2is-a关系 3.3多态公有继承 3.4静态联编和动态联编 3.5访问控制 3.6ABC理念 一、一个简单的基类 C中的基类是一…...

ARCGIS PRO SDK 使用条件管理 Pro UI
ARCGIS PRO UI简单介绍以下: 第一步:在Config.daml中在</AddInfo>标签下加上条件<conditions>标签(必须添加的) <conditions><!-- 定义条件 ,此处定义了两个--Tab 另一个为 group><insert…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...

Psychopy音频的使用
Psychopy音频的使用 本文主要解决以下问题: 指定音频引擎与设备;播放音频文件 本文所使用的环境: Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)
宇树机器人多姿态起立控制强化学习框架论文解析 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一) 论文解读:交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用
前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...
6️⃣Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙
Go 语言中的哈希、加密与序列化:通往区块链世界的钥匙 一、前言:离区块链还有多远? 区块链听起来可能遥不可及,似乎是只有密码学专家和资深工程师才能涉足的领域。但事实上,构建一个区块链的核心并不复杂,尤其当你已经掌握了一门系统编程语言,比如 Go。 要真正理解区…...