前后端系统开发之——文章管理

原文地址:前后端系统开发之——文章管理 - Pleasure的博客

下面是正文内容:

前言

主要使用的技术:前端使用的是Vue.js,后端使用的是SpringBoot。如不雷同可以直接跳过了。

文章管理是这个系统最主要的一个功能也是最常规的一个功能。之前的文章提到的是文章分类的管理,类似于我们所熟知的标签操作。而文章管理相较于文章分类的管理除了基础的增删改查之外,还增加了文章图片的托管,Markdown编辑器,自定义校验等稍微复杂一点的操作。整体上相差不大。

所以将分为两篇来进行阐述。最后还差一块用户模块的功能,然后文章管理系统的开发就告一段落了。

接下来关于Web全栈开发的学习将进入到新的境界,涉及到更实用的技巧以及更复杂的操作。比如验证码校验,支付等之类的操作。

正文

页面展示(挺单一的)

前端的代码由于只包括展示页面和实现函数已经基本展示完毕,后端仍存在一些细节上的操作,比如图片阿里云的托管(有点类似于图床),自定义校验等,以及一些补充的笔记就放到下一篇文章中来讲。

前端涉及到的函数

具体的代码思路和文章分类管理的大差不差,所以就罗列在过程中要用到的一些主要的函数以及变量(也就是script部分涉及到的,具体代码中有备注但是有点乱)

用于在template部分绑定按钮抽屉等以此来实现事件。

category文章分类模型,包括id,categoryName,categoryAlias,createTime,updateTime
articles文章列表模型,包括id,title,content,coverImg,state,categoryId,createTime,updateTime
分页条模型,包括pageNum,total,pageSize
formaDate用于格式化日期(更改时间)
onSizeChange//当每页条数发生了变化,调用此函数
onCurrentChange当前页码发生变化,调用此函数
showDrawer显示新建编辑文章的抽屉
articleList,articleCategoryList获取文章有关的数据数据
addArticle添加新的文章
updateArticle更新文章数据
deleteArticle删除文章
clearData清空新建文章时抽屉中的数据

后端涉及到的函数

具体的代码思路和文章分类管理的大差不差,主要涉及到下面五个功能。在数据访问层,请求层,数据管理层都有针对分别实现这五个功能的函数。

add新增文章
list获取文章列表
findById获取文章详情
update更新文章内容
deleteById删除文章

代码展示

计算机中很多项目和应用都会因为作者公布展示的代码不全而导致不能跑起来无法正常运行。不是缺少必要的配置项,就是缺少必要的文件

为了省时省力,这也就是需要作者公布源码的原因。

由于是在之前的基础上进行的功能的拓展,所以一些必要的文件在专栏之前的文章里已经展示过了,也就不再进行重复展示,主要展示必要的文件。

但是可能有些配置文件进行过小的添加和改动,就需要自己根据报错一点点修改了,或者等待我完整的项目上传吧。

前端

主要文件ArticleManage.vue,article.js

ArticleManage.vue是用于填补展示文件Layout.vue中空白的部分用以实现功能。

article.js主要用于服务接口的调用,即前后端的链接,用于解决跨域的问题。

ArticleManage.vue

<script setup>
import {Edit,Delete
} from '@element-plus/icons-vue'import { ref } from 'vue'
import {ElMessage } from 'element-plus'
//文章分类数据模型
const categorys = ref([{"id": 1,"categoryName": "学校事件","categoryAlias": "xuexiaoshijian","createTime": "2024-03-25 00:16:04","updateTime": "2024-04-01 20:47:37"},
])
import {articleCategoryListService,articleListService,addArticleService,articleUpdateService} from '@/api/article.js'
//用户搜索时选中的分类id
const categoryId=ref('')//用户搜索时选中的发布状态
const state=ref('')//文章列表数据模型
const articles = ref([{"id": 1,"title": "测试文章","content": "12345678","coverImg": "https://yiming1234.oss-cn-beijing.aliyuncs.com/afc398f5-0c03-425b-a649-880ced2fb568.jpg","state": "已发布","categoryId": 1,"createTime": "2024-04-17 20:20:41","updateTime": "2024-04-17 20:20:41"}
])//重置搜索
const resetSearch = () => {categoryId.value = '';state.value = '';articleList();
}
//分页条数据模型
const pageNum = ref(1)//当前页
const total = ref(20)//总条数
const pageSize = ref(3)//每页条数//当每页条数发生了变化,调用此函数
const onSizeChange = (size) => {pageSize.value = sizearticleList()
}
//当前页码发生变化,调用此函数
const onCurrentChange = (num) => {pageNum.value = numarticleList()
}
//格式化日期
const formatDate = (dateString) => {const date = new Date(dateString);return date.toLocaleString();
}const title = ref('')//显示抽屉
const showDrawer = (row) => {visibleDrawer.value = true;title.value = '编辑文章';articleModel.value.title = row.title; // 确保row对象有一个title属性articleModel.value.categoryId = row.categoryId; // 确保row对象有一个categoryId属性articleModel.value.coverImg = row.coverImg; // 确保row对象有一个coverImg属性articleModel.value.content = row.content; // 确保row对象有一个content属性articleModel.value.state = row.state; // 确保row对象有一个state属性articleModel.value.id = row.id // 确保row对象有一个id属性
}
//回显文章分类const articleCategoryList = async () => {let result = await articleCategoryListService();categorys.value = result.data;}//获取文章列表数据
const articleList = async () => {let params = {pageNum: pageNum.value,pageSize: pageSize.value,categoryId: categoryId.value ? categoryId.value : null,state: state.value ? state.value : null}let result = await articleListService(params);//渲染视图total.value = result.data.total;articles.value = result.data.items;//处理数据,给数据模型扩展一个属性categoryNamefor (let i = 0; i < articles.value.length; i++) {let article = articles.value[i];for (let j = 0; j < categorys.value.length; j++) {if (article.categoryId == categorys.value[j].id) {article.categoryName = categorys.value[j].categoryName;}}}
}articleCategoryList();
articleList();import { QuillEditor } from '@vueup/vue-quill'
import '@vueup/vue-quill/dist/vue-quill.snow.css'
import {Plus} from '@element-plus/icons-vue'
//控制抽屉是否显示
const visibleDrawer = ref(false)
//添加表单数据模型
const articleModel = ref({title: '',categoryId: '',coverImg: '',content:'',state:''
})import {useTokenStore} from "@/stores/token.js";
const tokenStore = useTokenStore();const uploadSuccess = (result) => {articleModel.value.coverImg = result.data;console.log(result.data);
}//添加文章
const addArticle = async (clickState) => {articleModel.value.state = clickState;let result = await addArticleService(articleModel.value);ElMessage.success(result.msg?result.msg:'添加成功');visibleDrawer.value = false;articleList();
}
//编辑文章
const updateArticle = async (clickState) => {articleModel.value.state = clickState;let result = await articleUpdateService(articleModel.value);ElMessage.success(result.msg ? result.msg : '编辑成功')//调用获取所有文章分类的函数articleList();visibleDrawer.value = false;
}
//删除文章
import { ElMessageBox } from 'element-plus'
const deleteArticle = (row) => {ElMessageBox.confirm('确认删除当前文章?','Warning',{confirmButtonText: 'OK',cancelButtonText: 'Cancel',type: 'warning',}).then(async () => {//调用接口let result = await articleDeleteService(row.id);ElMessage({type: 'success',message: 'Delete completed',})articleList();}).catch(() => {ElMessage({type: 'info',message: 'Delete canceled',})})
}
const clearData = () => {articleModel.value.title = '';articleModel.value.categoryId = '';articleModel.value.coverImg = '';articleModel.value.content = '';articleModel.value.state = '';
}
</script>
<template><el-card class="page-container"><template #header><div class="header"><span>文章管理</span><div class="extra"><el-button type="primary" @click="visibleDrawer=true; title = '新建文章'; clearData()">添加文章</el-button></div></div></template><!-- 搜索表单 --><el-form inline><el-form-item label="文章分类:"><el-select placeholder="请选择" v-model="categoryId" style="width: 200px"><el-option v-for="c in categorys" :key="c.id" :label="c.categoryName" :value="c.id"></el-option></el-select></el-form-item><el-form-item label="发布状态:"><el-select placeholder="请选择" v-model="state" style="width: 200px"><el-option label="已发布" value="已发布"></el-option><el-option label="草稿" value="草稿"></el-option></el-select></el-form-item><el-form-item><el-button type="primary" @click="articleList">搜索</el-button><el-button @click="resetSearch">重置</el-button></el-form-item></el-form><!-- 文章列表 --><el-table :data="articles" style="width: 100%"><el-table-column label="文章标题" width="400" prop="title"></el-table-column><el-table-column label="分类" prop="categoryName"></el-table-column><el-table-column label="发表时间"><template #default="{ row }">{{ formatDate(row.createTime) }}</template></el-table-column><el-table-column label="状态" prop="state"></el-table-column><el-table-column label="操作" width="100"><template #default="{ row }"><el-button :icon="Edit" circle plain type="primary" @click="showDrawer(row)"></el-button><el-button :icon="Delete" circle plain type="danger" @click="deleteArticle(row)"></el-button></template></el-table-column><template #empty><el-empty description="没有数据" /></template></el-table><!-- 分页条 --><el-pagination v-model:current-page="pageNum" v-model:page-size="pageSize" :page-sizes="[3, 5 ,10, 15]"layout="jumper, total, sizes, prev, pager, next" background :total="total" @size-change="onSizeChange"@current-change="onCurrentChange" style="margin-top: 20px; justify-content: flex-end" /></el-card><el-drawer v-model="visibleDrawer" :title="title" direction="rtl" size="50%"><!-- 添加文章表单 --><el-form :model="articleModel" label-width="100px" ><el-form-item label="文章标题" ><el-input v-model="articleModel.title" placeholder="请输入标题"></el-input></el-form-item><el-form-item label="文章分类"><el-select placeholder="请选择" v-model="articleModel.categoryId"><el-option v-for="c in categorys" :key="c.id" :label="c.categoryName" :value="c.id"></el-option></el-select></el-form-item><el-form-item label="文章封面"><el-upload class="avatar-uploader" :auto-upload="true" :show-file-list="false"action="/api/upload"name="file":headers="{'Authorization': tokenStore.token}":on-success="uploadSuccess"><img v-if="articleModel.coverImg" :src="articleModel.coverImg" class="avatar" /><el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon></el-upload></el-form-item><el-form-item label="文章内容"><div class="editor"><quill-editortheme="snow"v-model:content="articleModel.content"contentType="html"></quill-editor></div></el-form-item><el-form-item><el-button type="primary" @click="title == '新建文章' ? addArticle('已发布') : updateArticle('已发布')">发布</el-button><el-button type="info" @click="title == '新建文章' ?addArticle('草稿'): updateArticle('草稿')">草稿</el-button></el-form-item></el-form></el-drawer>
</template>
<style lang="scss" scoped>
.page-container {min-height: 100%;box-sizing: border-box;.header {display: flex;align-items: center;justify-content: space-between;}
}.avatar-uploader {:deep() {.avatar {width: 178px;height: 178px;display: block;}.el-upload {border: 1px dashed var(--el-border-color);border-radius: 6px;cursor: pointer;position: relative;overflow: hidden;transition: var(--el-transition-duration-fast);}.el-upload:hover {border-color: var(--el-color-primary);}.el-icon.avatar-uploader-icon {font-size: 28px;color: #8c939d;width: 178px;height: 178px;text-align: center;}}
}
.editor {width: 100%;:deep(.ql-editor) {min-height: 200px;}
}
</style>

article.js的内容

import request from '@/utils/request.js'export const articleCategoryListService = ()=>{return request.get('/category')
}
//文章分类添加
export const articleCategoryAddService = (categoryData)=>{return request.post('/category',categoryData)
}//文章分类修改
export const articleCategoryUpdateService = (categoryData)=>{return request.put('/category',categoryData)
}//文章分类删除
export const articleCategoryDeleteService = (id)=>{return request.delete('/category?id='+id)
}//文章列表查询
export const articleListService = (params)=>{return request.get('/article',{params:params})
}//文章添加
export const addArticleService = (articleData)=>{return request.post('/article',articleData)
}//文章修改
export const articleUpdateService = (articleData)=>{return request.put('/article',articleData)
}//文章删除
export const articleDeleteService = (id)=>{return request.delete('/article?id='+id)
}

后端

主要文件有实体类(Article.java以及PageBean.java)
请求层(ArticleController.java)
服务层(ArticleService.java以及ArticleServiceImpl.java)
数据访问层(ArticleMapper.java)

AliOssUtil.java用于图片的托管,来自官网提供的示例文件进行了修改

org.example.anno.State.java和org.example.validation.StateValidation.java用于Article.java实体类中state类的校验

Article.java的内容

package org.example.pojo;import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import org.example.anno.State;
import org.hibernate.validator.constraints.URL;import java.time.LocalDateTime;@Data
public class Article {private Integer id;//主键ID@NotEmpty@Pattern(regexp = "^\\S{1,10}$")private String title;//文章标题@NotEmptyprivate String content;//文章内容@NotEmpty@URLprivate String coverImg;//封面图像@Stateprivate String state;//发布状态 已发布|草稿@NotNullprivate Integer categoryId;//文章分类idprivate Integer createUser;//创建人IDprivate LocalDateTime createTime;//创建时间private LocalDateTime updateTime;//更新时间
}

PageBean.java的内容

package org.example.pojo;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;//分页返回结果对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean <T>{private Long total;//总条数private List<T> items;//当前页数据集合
}

ArticleController.java的内容

package org.example.controller;import jakarta.servlet.http.HttpServletResponse;
import org.example.pojo.Article;
import org.example.pojo.PageBean;
import org.example.pojo.Result;
import org.example.service.ArticleService;
import org.example.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;import java.util.Map;@RestController
@RequestMapping("/article")
public class ArticleController {@Autowiredprivate ArticleService articleService;//新增文章@PostMappingpublic Result add(@RequestBody @Validated Article article) {articleService.add(article);return Result.success();}//获取文章列表@GetMappingpublic Result<PageBean<Article>> list(Integer pageNum, Integer pageSize, @RequestParam(required = false) String categoryId, @RequestParam(required = false) String state) {PageBean<Article> pageBean = articleService.list(pageNum, pageSize, categoryId, state);return Result.success(pageBean);}//获取文章详情@GetMapping("/detail")public Result<Article> detail(@RequestParam Integer id) {Article article = articleService.findById(id);return Result.success(article);}//更新文章@PutMappingpublic Result update(@RequestBody Article article) {articleService.update(article);return Result.success();}//删除文章@PostMapping("/delete")public Result delete(@RequestParam Integer id) {articleService.deleteById(id);return Result.success();}
}

ArticleService.java的内容

package org.example.service;
import org.example.pojo.Article;
import org.example.pojo.PageBean;
public interface ArticleService {// 添加文章void add(Article article);//条件分页列表查询PageBean<Article> list(Integer pageNum, Integer pageSize, String categoryId, String state);Article findById(Integer id);void update(Article article);void deleteById(Integer id);
}

ArticleServiceImpl.java的内容

package org.example.service.impl;import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.example.mapper.ArticleMapper;
import org.example.pojo.Article;
import org.example.pojo.PageBean;
import org.example.service.ArticleService;
import org.example.utils.ThreadLocalUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;@Service
public class ArticleServiceImpl implements ArticleService {@Autowiredprivate ArticleMapper articleMapper;@Overridepublic void add(Article article) {//补充属性值article.setCreateTime(LocalDateTime.now());article.setUpdateTime(LocalDateTime.now());Map<String,Object> map = ThreadLocalUtil.get();article.setCreateUser((Integer) map.get("id"));articleMapper.add(article);}@Overridepublic PageBean<Article> list(Integer pageNum, Integer pageSize, String categoryId, String state) {//创建pagebean对象PageBean<Article> pb = new PageBean<>();//开启分页查询PageHelper.startPage(pageNum,pageSize);//调用MapperMap<String,Object> map = ThreadLocalUtil.get();Integer userId = (Integer) map.get("id");List<Article> as = articleMapper.list(userId,categoryId,state);//Page中提供了方法,可以获取PageHelper分页查询后 得到的总记录条数和当前页数据Page<Article> p = (Page<Article>) as;//把数据填充到PageBean对象中pb.setTotal(p.getTotal());pb.setItems(p.getResult());return pb;}@Overridepublic Article findById(Integer id) {Article article = articleMapper.findById(id);return article;}@Overridepublic void update(Article article) {article.setUpdateTime(LocalDateTime.now());articleMapper.update(article);}@Overridepublic void deleteById(Integer id) {articleMapper.deleteById(id);}
}

ArticleMapper.java的内容

package org.example.mapper;import org.apache.ibatis.annotations.*;
import org.example.pojo.Article;
import org.example.pojo.Category;
import java.util.List;@Mapper
public interface ArticleMapper {// 添加文章@Insert("insert into article(title,content,cover_img,state,category_id,create_user,create_time,update_time) values(#{title},#{content},#{coverImg},#{state},#{categoryId},#{createUser},#{createTime},#{updateTime})")void add(Article article);List<Article> list(Integer userId, String categoryId, String state);@Select("select * from article where create_user = #{userId}")Article findById(Integer userId);@Update("update article set title=#{title},content=#{content},cover_img=#{coverImg},state=#{state},category_id=#{categoryId},update_time=now() where id=#{id}")void update(Article article);@Delete("delete from article where id=#{id}")void deleteById(Integer id);
}

AliOss.java的内容

package org.example.utils;import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;import java.io.FileInputStream;
import java.io.InputStream;public class AliOssUtil {// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。private static final String ENDPOINT = "https://oss-cn-beijing.aliyuncs.com";// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。//EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();// 填写Bucket名称,例如examplebucket。private static final String ACCESS_KEY_ID = "LTAI5tS2iFbkK1VLdeYdr4p2";private static final String ACCESS_KEY_SECRET = "Mob9G1cqSRCxZKOllAkbqoJ7jT6mH9";private static final String BUCKET_NAME = "yiming1234";// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。public static String uploadFile(String objectName, InputStream in) throws Exception {// 创建OSSClient实例。OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);String url = "";try {// 填写字符串。String content = "Hello OSS,你好世界";// 创建PutObjectRequest对象。PutObjectRequest putObjectRequest = new PutObjectRequest(BUCKET_NAME, objectName, in);// 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。// ObjectMetadata metadata = new ObjectMetadata();// metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());// metadata.setObjectAcl(CannedAccessControlList.Private);// putObjectRequest.setMetadata(metadata);// 上传字符串。PutObjectResult result = ossClient.putObject(putObjectRequest);url = "https://" + BUCKET_NAME + "." + ENDPOINT.substring(ENDPOINT.lastIndexOf("/")+1) + "/" + objectName;} catch (OSSException oe) {System.out.println("Caught an OSSException, which means your request made it to OSS, "+ "but was rejected with an error response for some reason.");System.out.println("Error Message:" + oe.getErrorMessage());System.out.println("Error Code:" + oe.getErrorCode());System.out.println("Request ID:" + oe.getRequestId());System.out.println("Host ID:" + oe.getHostId());} catch (ClientException ce) {System.out.println("Caught an ClientException, which means the client encountered "+ "a serious internal problem while trying to communicate with OSS, "+ "such as not being able to access the network.");System.out.println("Error Message:" + ce.getMessage());} finally {if (ossClient != null) {ossClient.shutdown();}}return url;}
}

org.example.anno.State.java的内容

package org.example.anno;import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import jakarta.validation.constraints.NotEmpty;
import org.example.validation.StateValidation;import java.lang.annotation.*;import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;@Documented//元注解
@Target({FIELD})
@Retention(RUNTIME)
@Constraint(validatedBy = {StateValidation.class}
)//指定提供校验规则的类
public @interface State {//校验失败的提示信息String message() default "state参数的值只能是已发布的文章或者草稿";//指定分组Class<?>[] groups() default {};//负载Class<? extends Payload>[] payload() default {};
}

org.example.validation.StateValidation.java的内容

package org.example.anno;import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import jakarta.validation.constraints.NotEmpty;
import org.example.validation.StateValidation;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;@Documented//元注解
@Target({FIELD})
@Retention(RUNTIME)
@Constraint(validatedBy = {StateValidation.class}
)//指定提供校验规则的类
public @interface State {//校验失败的提示信息String message() default "state参数的值只能是已发布的文章或者草稿";//指定分组Class<?>[] groups() default {};//负载Class<? extends Payload>[] payload() default {};
}

缺陷以及仍需要进一步改进的地方

首先作为文章管理系统,应该是作为具体网站的后台来使用的,比如在调用addArticle发布文章的时候还应该向用于展示的网页发送数据,以此来进一步实现发布文章这个功能。

其次图片的添加采用了阿里云OSS托管的这个功能。但是每一次在点击添加或者更改图片的时候都会上传一张新的图片,并不会删除或覆盖,这一点也需要改进。

但是作为练手的项目并没有实际的用途,也就不过分追求完美了。

尾声

作为自主开发笔记,很多小的细节以及报错后错误的查找不能很好的进行体现,这也是没办法的事。

在全部完工后,会上传完整的压缩包以及jar包,供学习参考。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/423.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何寻找可靠的第三方软件检测机构

随着科技的飞速发展和数字化进程的加速&#xff0c;软件质量成为了企业竞争的关键。为了确保软件的质量和性能&#xff0c;许多企业选择寻找第三方的软件检测机构来进行软件的质量控制和评估。那么&#xff0c;如何找到一家可靠的第三方软件检测机构呢&#xff1f; 1.明确检测…

怎么设置启用远程桌面? 如何让外网电脑远程本地内网?

如何远程控制电脑&#xff1f;最简单实用的方案是开启电脑系统自带的远程桌面功能&#xff0c;如果涉及跨网、内外网互通&#xff0c;可以同时用快解析内网映射外网。下面是方案的具体实施步骤&#xff0c;供大家参考。 怎么打开设置启用远程桌面&#xff1f; 1.在目标需要远…

05—js对象

一、初识对象 JavaScript是面向对象编程&#xff08;Object Oriented Programming&#xff0c;OOP&#xff09;语言。 面对象是一种复合值&#xff1a;它将很多值集合在一起&#xff0c;可通过名字访问这些值。对象也可看做一种无序的数据集合&#xff0c;由若干个“键值对”…

数据库--Sqlite3

1、思维导图 2sqlite3在linux中是实现数据的增删&#xff0c;改 #include<myhead.h> int main(int argc, const char *argv[]) { //1、定义一个数据库句柄指针 sqlite3* ppDb NULL; //2、创建或打开数据库 if(sqlite3_open("./mydb…

通过两道题理解哈夫曼树

哈夫曼树定义 哈夫曼树&#xff08;Huffman Tree&#xff09;&#xff0c;又称最优二叉树&#xff0c;是一种带权路径长度最短的二叉树。所谓带权路径长度是指树中所有的叶子结点的权值乘以其到根结点的路径长度&#xff08;边数&#xff09;。哈夫曼树广泛应用于数据压缩等领…

Centroid-Aware Feature Recalibration for Cancer Grading in Pathology Images论文速读

Centroid-Aware Feature Recalibration for Cancer Grading in Pathology Images 摘要 癌症分级是病理学中的一项重要任务。人工神经网络在计算病理学领域的最新发展表明&#xff0c;这些方法在提高癌症诊断的准确性和质量方面具有巨大潜力。然而&#xff0c;这些方法的稳健性…

面试官最怕你懂的Kafka面试题,一招致胜!

&#x1f469;&#x1f3fd;‍&#x1f4bb;个人主页&#xff1a;阿木木AEcru &#x1f525; 系列专栏&#xff1a;《Docker容器化部署系列》 《Java每日面筋》 &#x1f4b9;每一次技术突破&#xff0c;都是对自我能力的挑战和超越。 目录 一、前言Kafka的优点Kafka的使用场景…

密码学 | 椭圆曲线密码学 ECC 入门(二)

目录 4 椭圆曲线&#xff1a;更好的陷门函数 5 奇异的对称性 6 让我们变得奇特 ⚠️ 原文地址&#xff1a;A (Relatively Easy To Understand) Primer on Elliptic Curve Cryptography ⚠️ 写在前面&#xff1a;本文属搬运博客&#xff0c;自己留着学习。如果你和我一样…

实力认证!亚数产品入选《中国网络安全行业全景图(第十一版)》

2024年4月12日&#xff0c;安全牛第十一版《中国网络安全行业全景图》&#xff08;以下简称“全景图”&#xff09;正式发布。 亚数信息科技&#xff08;上海&#xff09;有限公司&#xff08;以下简称“亚数”&#xff09;成功入选数字证书、加解密、密钥管理三项细分领域。 此…

Linux 2.进程(守护进程)

守护进程 何谓守护进程常见守护进程进程查看命令pskill命令编写简单守护进程守护进程的父进程 何谓守护进程 daemon&#xff0c;表示守护进程&#xff0c;简称为d&#xff08;进程名后面带d的基本就是守护进程&#xff09; 长期运行&#xff08;一般是开机运行直到关机时关闭&…

【Node.js从基础到高级运用】二十五、Node.js中Cluster的作用

引言 Node.js中的cluster模块允许您轻松创建共享服务器端口的子进程。这是一个核心模块&#xff0c;用于在Node.js应用程序中实现多进程架构&#xff0c;以充分利用多核CPU系统的计算能力。 cluster介绍 当您启动一个Node.js应用程序时&#xff0c;默认情况下它运行在单个进程…

【Python】什么是pip,conda,pycharm,jupyter notebook?conda基本教程

pip--conda--pycharm--jupyter notebook &#x1f343;pip&#x1f343;conda&#x1f343;Pycharm&#x1f343;jupyter notebook&#x1f343;Conda基本教程☘️进入base环境☘️创建一个新的环境☘️激活环境☘️退出环境☘️查看电脑上都安装了哪些环境☘️删除已创建的项目…

Mac 部署 GPT-2 预训练模型 gpt2-chinese-cluecorpussmall

文章目录 下载 GPT-2 模型快速开始 GPT-2 下载 GPT-2 模型 https://huggingface.co/uer/gpt2-chinese-cluecorpussmall git clone https://huggingface.co/uer/gpt2-chinese-cluecorpussmall # 或单独下载 LFS GIT_LFS_SKIP_SMUDGE1 git clone https://huggingface.co/uer/gpt…

使用Docker,【快速】搭建个人博客【WordPress】

目录 1.安装Mysql&#xff0c;创建&#xff08;WordPress&#xff09;用的数据库 1.1.安装 1.2.创建数据库 2.安装Docker 3.安装WodPress&#xff08;使用Docker&#xff09; 3.1.创建文件夹 3.2.查看镜像 3.3.获取镜像 3.4.查看我的镜像 3.5.使用下载的镜像&#xf…

Linux的学习之路:11、地址空间

摘要 本章主要是说一下地址空间&#xff0c;我也只是按照我的理解进行解释&#xff0c;可能说不清楚&#xff0c;欢迎指正 目录 摘要 一、空间布局图 二、代码测试一下 三、进程地址空间 四、测试代码 一、空间布局图 如下方图片可以看出地址空间有几种&#xff0c;这里…

Arduino源代码(ino)在Proteus中调试总结

一、前言 基于BluePill Plus开发板&#xff08;该板是毕设网红板&#xff09; BluePill Plus / WeAct Studio 微行工作室 出品 BluePill-Plus/README-zh.md at master WeActStudio/BluePill-Plus GitHub 首页-WeAct Studio-淘宝网 (taobao.com) 在Proteus中对应的例子是&…

每日OJ题_多源BFS①_力扣542. 01 矩阵(多源BFS解决最短路原理)

目录 多源BFS解决最短路算法原理 力扣542. 01 矩阵 解析代码 多源BFS解决最短路算法原理 什么是单源最短路 / 多源最短路&#xff1f; 之前的BFS解决最短路都是解决的单源最短路。 画图来说&#xff0c;单源最短路问题即为&#xff1a; 而对于多源最短路问题: 如何解决此…

Docker容器逃逸-特权模式-危险挂载-Procfs

Docker容器逃逸-特权模式-危险挂载 Docker这个概念&#xff1a; Docker 容器与虚拟机类似&#xff0c;但二者在原理上不同&#xff0c;容器是将操作系统层虚拟化&#xff0c;虚拟机则是虚拟化硬件&#xff0c;因此容器更具有便携性、高效地利用服务器。 ‍ Docker会遇到的安…

京东微服务microApp使用总结

前言 基于现有业务门户进行微服务基础平台搭建 主应用框架&#xff1a;vue3vite 子应用框架&#xff1a;vue2webpack / vue3vite在这里插入代码片 本地调试即可&#xff1a;主应用子应用进行打通&#xff08;注意&#xff1a;两者都是vue3vite&#xff09; 问题总结 1.嵌入…

压电式微机械超声换能器(PMUT)可替代传统超声换能器 下游应用范围广泛

压电式微机械超声换能器&#xff08;PMUT&#xff09;可替代传统超声换能器 下游应用范围广泛 压电式微机械超声换能器&#xff08;PMUT&#xff09;&#xff0c;是一种基于正逆压电效应与微机械&#xff08;MEMS&#xff09;技术制造而成的发射、接收超声波以实现检测的装置。…