idea插件开发的第六天-开发一个笔记插件

介绍

Demo说明

  • 本文基于maven项目开发,idea版本为2022.3以上,jdk为1.8
  • 本文在JTools插件之上进行开发
  • 本插件目标是做一款笔记插件,用于开发者在开发过程中随时记录信息
  • 仓库地址: jtools-notes

JTools插件说明

  • Tools插件是一个Idea插件,此插件提供统一Spi规范,极大的降低了idea插件的开发难度,并提供开发者模块,可以极大的为开发者开发此插件提供便利
  • Tools插件安装需要idea2022.3以上版本
  • 插件下载连接: https://download.csdn.net/download/qq_42413011/89702325
  • pojo-serializer插件: https://gitee.com/myprofile/pojo-serializer

成果展示

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

依赖安装

		<dependency><groupId>com.fifesoft</groupId><artifactId>rsyntaxtextarea</artifactId><version>3.5.1</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>2.0.52</version></dependency>

点击这里动态安装插件sdk
在这里插入图片描述

创建PluginImpl

package com.lhstack.aaa;import com.lhstack.tools.plugins.Action;
import com.lhstack.tools.plugins.Helper;
import com.lhstack.tools.plugins.IPlugin;
import com.lhstack.tools.plugins.Logger;import javax.swing.*;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class PluginImpl implements IPlugin {/*** 缓存笔记视图,key=project locationHash*/private final Map<String, NotesView> viewMap = new HashMap<>();/*** 缓存logger,key=project locationHash*/private final Map<String, Logger> loggerMap = new HashMap<>();/*** 创建笔记视图** @param locationHash* @return*/@Overridepublic JComponent createPanel(String locationHash) {return viewMap.computeIfAbsent(locationHash, key -> {return new NotesView(locationHash, loggerMap.get(locationHash));});}/*** 缓存logger** @param projectHash* @param logger* @param openThisPage*/@Overridepublic void openProject(String projectHash, Logger logger, Runnable openThisPage) {loggerMap.put(projectHash, logger);}/*** 项目关闭时,清理相关缓存** @param projectHash*/@Overridepublic void closeProject(String projectHash) {NotesView notesView = viewMap.remove(projectHash);if (notesView != null) {notesView.run();}loggerMap.remove(projectHash);}/*** 插件卸载,清理缓存*/@Overridepublic void unInstall() {viewMap.values().forEach(Runnable::run);viewMap.clear();loggerMap.clear();}/*** 插件面板icon** @return*/@Overridepublic Icon pluginIcon() {return Helper.findIcon("logo.svg", PluginImpl.class);}/*** 插件打开,顶部的tab icon** @return*/@Overridepublic Icon pluginTabIcon() {return Helper.findIcon("logo_tab.svg", PluginImpl.class);}/*** 插件名称** @return*/@Overridepublic String pluginName() {return "笔记";}/*** 插件描述** @return*/@Overridepublic String pluginDesc() {return "这是一个笔记插件";}/*** 插件版本** @return*/@Overridepublic String pluginVersion() {return "0.0.1";}/*** 插件内容tab右侧的按钮** @param locationHash* @return*/@Overridepublic List<Action> swingTabPanelActions(String locationHash) {return Arrays.asList(new Action() {@Overridepublic Icon icon() {return Helper.findIcon("icons/home.svg", PluginImpl.class);}@Overridepublic String title() {return "主页";}@Overridepublic void actionPerformed() {//如果未选中,点击则打开主页面板if (!isSelected()) {viewMap.get(locationHash).switchHomeView();}}/*** 按钮是否需要选中* @return*/@Overridepublic boolean isSelected() {return viewMap.get(locationHash).isHomeView();}}, new Action() {@Overridepublic Icon icon() {return Helper.findIcon("icons/content.svg", PluginImpl.class);}@Overridepublic String title() {return "内容";}@Overridepublic void actionPerformed() {//按钮未选中,则触发if (!isSelected()) {//如果不能切换到内容视图,则激活日志面板,打印提示日志if (!viewMap.get(locationHash).switchContentView()) {loggerMap.get(locationHash).activeConsolePanel();loggerMap.get(locationHash).warn("请先选择对应的节点");}}}/*** 按钮是否需要选中* @return*/@Overridepublic boolean isSelected() {return viewMap.get(locationHash).isContentView();}});}
}

META-INF/ToolsPlugin.txt

com.lhstack.aaa.PluginImpl

视图代码

package com.lhstack.aaa;import com.lhstack.tools.plugins.Logger;import javax.swing.*;
import java.awt.*;public class NotesView extends JPanel implements Runnable {private static final String HOME_PAGE = "HOME";private static final String CONTENT_PAGE = "CONTENT";private final HomeView homeView;private final ContentView contentView;private final CardLayout cardLayout;private String currentView;public NotesView(String locationHash, Logger logger) {//笔记主页视图this.homeView = new HomeView(locationHash, this, logger);//笔记内容视图this.contentView = new ContentView(locationHash, this, logger, homeView::getDatas);//创建卡片布局this.cardLayout = new CardLayout();//添加主页视图到布局cardLayout.addLayoutComponent(homeView, HOME_PAGE);//添加内容视图到布局cardLayout.addLayoutComponent(contentView, CONTENT_PAGE);//添加视图到容器this.add(homeView);this.add(contentView);//为容器设置卡片布局this.setLayout(cardLayout);//显示主页视图this.cardLayout.show(this, HOME_PAGE);//缓存当前显示的视图this.currentView = HOME_PAGE;}public void switchHomeView() {//显示主页cardLayout.show(this, HOME_PAGE);//设置当前显示的视图为主页currentView = HOME_PAGE;}public boolean switchContentView() {//切换内容面板,需要判断是否切换成功//获取视图面板当前选中的节点,没有就是falsereturn this.homeView.getSelectedData().map(data -> {//获取到,则将当前节点放入内容视图this.contentView.onShow(data);//切换到内容视图cardLayout.show(this, CONTENT_PAGE);//修改当前缓存视图为内容视图currentView = CONTENT_PAGE;return true;}).orElse(false);}/*** 判断当前是否为内容视图,用于按钮选中效果** @return*/public boolean isContentView() {return currentView.equals(CONTENT_PAGE);}/*** @return*/public boolean isHomeView() {return currentView.equals(HOME_PAGE);}/*** 卸载,项目关闭回调*/@Overridepublic void run() {this.contentView.run();}
}

主页视图

在这里插入图片描述

package com.lhstack.aaa;import com.lhstack.aaa.entity.Data;
import com.lhstack.tools.plugins.Helper;
import com.lhstack.tools.plugins.Logger;import javax.swing.*;
import javax.swing.border.MatteBorder;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Optional;public class HomeView extends JPanel {private final NotesView notesView;private final Logger logger;private final String locationHash;private JTree tree;private List<Data> datas;private DefaultTreeModel treeModel;private DefaultMutableTreeNode root;public HomeView(String locationHash, NotesView notesView, Logger logger) {this.notesView = notesView;this.logger = logger;this.locationHash = locationHash;this.setLayout(new BorderLayout());this.initMenu();this.initContent();}private void initContent() {//加载数据this.datas = DataManager.loadData(locationHash);//创建root节点this.root = new DefaultMutableTreeNode();//初始化树initTree(root, datas);//创建树模型this.treeModel = new DefaultTreeModel(root);//创建treethis.tree = new JTree(treeModel);//不显示root节点this.tree.setRootVisible(false);//设置不可编辑this.tree.setEditable(false);//创建render,自定义未选中的背景色DefaultTreeCellRenderer cellRenderer = new DefaultTreeCellRenderer();//设置为透明背景cellRenderer.setBackgroundNonSelectionColor(new Color(0, 0, 0, 0));this.tree.setCellRenderer(cellRenderer);//自定义选择模式this.tree.setSelectionModel(new DefaultTreeSelectionModel() {@Overridepublic void setSelectionPath(TreePath path) {super.setSelectionPath(path);if (path != null) {tree.scrollPathToVisible(path);}}});//设置不支持多选this.tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);//设置鼠标监听this.tree.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {// 根据点击的位置获取最近的行int row = tree.getClosestRowForLocation(e.getX(), e.getY());// 获取行高和树的行数int rowHeight = tree.getRowHeight();int totalRows = tree.getRowCount();// 如果点击的位置超出了树的行数总高度,取消选中if (e.getY() > totalRows * rowHeight || row == -1) {tree.clearSelection(); // 如果点击的不是任何行,取消选中} else {tree.setSelectionRow(row); // 选中行}//获取选中的节点TreePath treePath = tree.getSelectionPath();if (treePath != null) {//右键菜单if (SwingUtilities.isRightMouseButton(e)) {JPopupMenu popupMenu = new JPopupMenu();JMenuItem addNodeItem = new JMenuItem("新增节点", Helper.findIcon("icons/addNode.svg", HomeView.class));addNodeItem.addActionListener(event -> {try {String name = JOptionPane.showInputDialog("请输入节点名称");if (name == null || name.trim().isEmpty()) {logger.activeConsolePanel();logger.warn("新增节点,节点名称不能为空");return;}//当前节点作为父节点DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) treePath.getLastPathComponent();//获取节点数据Data parentData = (Data) parentNode.getUserObject();//创建数据节点Data data = new Data();data.setName(name);//获取父级几点children,如果没有,则初始化List<Data> childrenList = parentData.getChildren();if (childrenList == null) {childrenList = new ArrayList<>();parentData.setChildren(childrenList);}//添加数据节点到父节点的childrenchildrenList.add(data);DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(data);parentNode.add(newNode);//更新视图treeModel.insertNodeInto(newNode, parentNode, parentNode.getIndex(newNode));//持久化数据DataManager.storeData(datas, locationHash);} catch (Throwable err) {logger.error("添加节点失败: " + err);}});JMenuItem removeItem = new JMenuItem("删除节点", Helper.findIcon("icons/deleteNode.svg", HomeView.class));removeItem.addActionListener(event -> {int confirm = JOptionPane.showConfirmDialog(null, "你确定要删除节点吗,如果是树节点,子节点的内容会放到这个节点的父级", "警告", JOptionPane.OK_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE);if (confirm == JOptionPane.OK_OPTION) {try {DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent();DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent();List<Data> parenDataList;if (parent == null) {parent = root;parenDataList = datas;} else {Data parentData = (Data) parent.getUserObject();if (parentData == null) {parenDataList = datas;} else {parenDataList = parentData.getChildren();if (parenDataList == null) {parenDataList = new ArrayList<>();parentData.setChildren(parenDataList);}}}Enumeration<TreeNode> children = node.children();parent.remove(node);parenDataList.remove((Data) node.getUserObject());if (children != null) {while (children.hasMoreElements()) {DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();parent.add(child);parenDataList.add((Data) child.getUserObject());}}treeModel.reload(parent);logger.info(datas);DataManager.storeData(datas, locationHash);} catch (Throwable err) {logger.error("删除节点错误: " + err);}}});JMenuItem editItem = new JMenuItem("编辑节点", Helper.findIcon("icons/editNode.svg", HomeView.class));editItem.addActionListener(event -> {DefaultMutableTreeNode node = (DefaultMutableTreeNode) treePath.getLastPathComponent();Data data = (Data) node.getUserObject();String name = JOptionPane.showInputDialog(null, "请输入节点名称", data.getName());if (name == null || name.trim().isEmpty()) {logger.activeConsolePanel();logger.warn("编辑节点名称不能为空");return;}data.setName(name);treeModel.nodeStructureChanged(node);DataManager.storeData(datas, locationHash);});JMenuItem openContentItem = new JMenuItem("打开内容", Helper.findIcon("icons/open.svg", HomeView.class));openContentItem.addActionListener(event -> {notesView.switchContentView();});popupMenu.add(addNodeItem);popupMenu.add(removeItem);popupMenu.add(editItem);popupMenu.add(openContentItem);DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) treePath.getLastPathComponent();if (treeNode.getChildCount() > 0) {JMenuItem removeDirItem = new JMenuItem("删除目录", Helper.findIcon("icons/deleteNode.svg", HomeView.class));removeDirItem.setToolTipText("删除整个目录和目录下所有的节点");removeDirItem.addActionListener(event -> {DefaultMutableTreeNode parent = (DefaultMutableTreeNode) treeNode.getParent();treeNode.removeFromParent();List<Data> parentDataList;Data data = (Data) parent.getUserObject();if (data == null) {parentDataList = datas;} else {parentDataList = data.getChildren();if (parentDataList == null) {parentDataList = new ArrayList<>();data.setChildren(parentDataList);}}parentDataList.remove((Data) treeNode.getUserObject());treeModel.reload(parent);DataManager.storeData(datas, locationHash);});popupMenu.add(removeDirItem);}popupMenu.show(e.getComponent(), e.getX() + 10, e.getY() + 10);}if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() == 3) {notesView.switchContentView();}}}});Helper.treeSpeedSearch(tree, true, treePath -> {DefaultMutableTreeNode lastPathComponent = (DefaultMutableTreeNode) treePath.getLastPathComponent();Object userObject = lastPathComponent.getUserObject();if (userObject != null) {Data data = (Data) userObject;return data.getName();}return "";});JScrollPane jScrollPane = new JScrollPane(this.tree);MatteBorder border = BorderFactory.createMatteBorder(1, 0, 0, 0, Color.gray);this.tree.setBorder(border);this.add(jScrollPane, BorderLayout.CENTER);}public Optional<Data> getSelectedData() {return Optional.ofNullable(tree.getSelectionPath()).map(TreePath::getLastPathComponent).map(DefaultMutableTreeNode.class::cast).map(DefaultMutableTreeNode::getUserObject).map(Data.class::cast);}private void initTree(DefaultMutableTreeNode root, List<Data> datas) {datas.forEach(data -> {DefaultMutableTreeNode node = new DefaultMutableTreeNode(data);root.add(node);if (data.getChildren() != null && !data.getChildren().isEmpty()) {initTree(node, data.getChildren());}});}private void initMenu() {JPanel panel = new JPanel();panel.setBorder(null);panel.setLayout(new FlowLayout(FlowLayout.RIGHT));panel.add(Helper.actionButton(Helper.findIcon("icons/unfold.svg", PluginImpl.class), "全部展开", str -> {expandAll();}));panel.add(Helper.actionButton(Helper.findIcon("icons/packup.svg", PluginImpl.class), "全部收起", str -> {collapseAll();}));panel.add(Helper.actionButton(Helper.findIcon("icons/newNode.svg", PluginImpl.class), "新增节点", str -> {SwingUtilities.invokeLater(() -> {try {String name = JOptionPane.showInputDialog("请输入节点名称");if (name == null || name.trim().isEmpty()) {logger.activeConsolePanel();logger.warn("新增节点,节点名称不能为空");return;}TreePath treePath = tree.getSelectionPath();Data data = new Data();data.setName(name);if (treePath != null) {DefaultMutableTreeNode parentNode = (DefaultMutableTreeNode) treePath.getLastPathComponent();Data parentData = (Data) parentNode.getUserObject();List<Data> childrenList = parentData.getChildren();if (childrenList == null) {childrenList = new ArrayList<>();parentData.setChildren(childrenList);} else {parentData.getChildren().add(data);}childrenList.add(data);DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(data);parentNode.add(newNode);treeModel.insertNodeInto(newNode, parentNode, parentNode.getIndex(newNode));} else {datas.add(data);DefaultMutableTreeNode node = new DefaultMutableTreeNode(data);root.add(node);if (root.getChildCount() == 1) {treeModel.reload(root);} else {treeModel.insertNodeInto(node, root, root.getIndex(node));}}DataManager.storeData(datas, locationHash);} catch (Throwable err) {logger.error("添加节点失败: " + err);}});}));this.add(panel, BorderLayout.NORTH);}private void collapseAll() {for (int i = 0; i < tree.getRowCount(); i++) {tree.collapseRow(i);}}private void expandAll() {for (int i = 0; i < tree.getRowCount(); i++) {tree.expandRow(i);}}public List<Data> getDatas() {return datas;}
}

内容视图

在这里插入图片描述

package com.lhstack.aaa;import com.lhstack.aaa.entity.Data;
import com.lhstack.tools.plugins.Logger;
import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
import org.fife.ui.rsyntaxtextarea.TextEditorPane;
import org.fife.ui.rtextarea.RTextScrollPane;import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.Document;
import java.awt.*;
import java.util.List;
import java.util.function.Supplier;public class ContentView extends JPanel implements DocumentListener, Runnable {private final TextEditorPane textEditorPane;private final JLabel title;private final Logger logger;private final String locationHash;private final Supplier<List<Data>> datas;private Data data;public ContentView(String locationHash, NotesView notesView, Logger logger, Supplier<List<Data>> datas) {this.setLayout(new BorderLayout());this.setBorder(null);this.logger = logger;this.textEditorPane = initTextEditorPane();this.title = new JLabel();this.title.setFont(new Font("", Font.PLAIN, 16));this.add(title, BorderLayout.NORTH);RTextScrollPane rTextScrollPane = new RTextScrollPane(this.textEditorPane);rTextScrollPane.setBorder(null);this.add(rTextScrollPane, BorderLayout.CENTER);this.datas = datas;this.locationHash = locationHash;}private TextEditorPane initTextEditorPane() {TextEditorPane pane = new TextEditorPane();pane.setTabSize(2);pane.setLineWrap(true);pane.setHighlightCurrentLine(true);pane.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_MARKDOWN);pane.setCodeFoldingEnabled(true);return pane;}public void onShow(Data data) {this.data = data;this.title.setText(data.getName());this.title.setHorizontalAlignment(JLabel.CENTER);Document document = this.textEditorPane.getDocument();document.removeDocumentListener(this);this.textEditorPane.setText(data.getText());document.addDocumentListener(this);}@Overridepublic void insertUpdate(DocumentEvent e) {this.data.setText(textEditorPane.getText());DataManager.storeData(datas.get(), locationHash);}@Overridepublic void removeUpdate(DocumentEvent e) {this.data.setText(textEditorPane.getText());DataManager.storeData(datas.get(), locationHash);}@Overridepublic void changedUpdate(DocumentEvent e) {this.data.setText(textEditorPane.getText());DataManager.storeData(datas.get(), locationHash);}@Overridepublic void run() {this.textEditorPane.resetKeyboardActions();this.textEditorPane.clearParsers();this.textEditorPane.clearMarkAllHighlights();}
}

数据加载,持久化管理

package com.lhstack.aaa;import com.alibaba.fastjson2.JSON;
import com.lhstack.aaa.entity.Data;
import com.lhstack.tools.plugins.Helper;import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;public class DataManager {public static File loadFile(String locationHash) {try {String path = Helper.getProjectBasePath(locationHash);File file = new File(path, ".idea/JTools/notes");if (!file.exists()) {file.mkdirs();}File dataFile = new File(file, "data.json");if (!dataFile.exists()) {dataFile.createNewFile();}return dataFile;} catch (Throwable e) {throw new RuntimeException(e);}}public static void storeData(List<Data> data, String locationHash) {try {File file = loadFile(locationHash);Files.write(file.toPath(), JSON.toJSONBytes(data));} catch (Throwable e) {throw new RuntimeException(e);}}public static List<Data> loadData(String locationHash) {try {File file = loadFile(locationHash);if(file.length() <= 0){return new ArrayList<>();}byte[] bytes = Files.readAllBytes(file.toPath());return JSON.parseArray(new String(bytes, StandardCharsets.UTF_8), Data.class);} catch (Throwable e) {throw new RuntimeException(e);}}
}

数据结构定义

package com.lhstack.aaa.entity;import java.util.List;
import java.util.Objects;public class Data {private String name;private String text;private List<Data> children;public String getName() {return name;}public Data setName(String name) {this.name = name;return this;}public String getText() {return text;}public Data setText(String text) {this.text = text;return this;}public List<Data> getChildren() {return children;}public Data setChildren(List<Data> children) {this.children = children;return this;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Data data = (Data) o;return Objects.equals(name, data.name) && Objects.equals(text, data.text) && Objects.equals(children, data.children);}@Overridepublic int hashCode() {return Objects.hash(name, text, children);}@Overridepublic String toString() {return name;}
}

操作说明

  1. 选中节点点击添加,会在当前节点新增节点
  2. 未选中节点添加,则在root节点新增节点
  3. 点击节点外部内容,即可取消选中
    在这里插入图片描述
  4. 双击展开树节点
  5. 三击打开内容面板
    在这里插入图片描述
  6. 右键菜单,如果是树,则会多一个删除目录菜单
  7. ``在这里插入图片描述

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

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

相关文章

微型导轨在IC制造设备的应用与优势

微型导轨的精度和稳定性对于机器的准确执行任务至关重要&#xff0c;其精确度通常用微米或毫米来衡量。其尺寸可以做到非常小&#xff0c;常运用在小型设备上&#xff0c;尤其是在IC制造设备中&#xff0c;其应用非常广泛。 在IC制造设备中主要用于半导体芯片的切割、封装和测试…

V2M2引擎源码BlueCodePXL源码完整版

V2M2引擎源码BlueCodePXL源码完整版 链接: https://pan.baidu.com/s/1ifcTHAxcbD2CyY7gDWRVzQ?pwdmt4g 提取码: mt4g 参考资料&#xff1a;BlueCodePXL源码完整版_1234FCOM专注游戏工具及源码例子分享

网站可疑问题

目标站点 Google hack 页面访问 抓包 POST /admin.php?actionlogin HTTP/2 Host: www.xjy.edu.cn Cookie: xkm_sidA6x4Cgw2zx User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:130.0) Gecko/20100101 Firefox/130.0 Accept: text/html,application/xhtmlxml,appl…

使用 Light Chaser 进行大屏数据可视化

引言 在当今数据驱动的世界中&#xff0c;数据可视化变得越来越重要。Light Chaser 是一款基于 React 技术栈的大屏数据可视化设计工具&#xff0c;通过简单的拖拽操作&#xff0c;你可以快速生成漂亮、美观的数据可视化大屏和看板。本文将介绍如何使用 Light Chaser 进行数据…

Redis:string类型

Redis&#xff1a;string类型 string命令设置与读取SETGETMSETMGET 数字操作INCRINCRBYDECRDECRBYINCRBYFLOAT 字符串操作APPENDSTRLENGETRANGESETRANGE 内部编码intembstrraw 在Redis中&#xff0c;字符串string存储的是二进制&#xff0c;以byte为单位&#xff0c;输入的二进…

【HTML+CSS】留言板plus实现全过程

创建一个具有动态留言的简约风格留言板 在本教程中&#xff0c;我们将学习如何创建一个简约风格的留言板&#xff0c;它具备动态留言显示和一些基本动画效果。这个留言板将使用HTML和CSS构建&#xff0c;最终实现一个既美观又实用的界面。 准备工作 首先&#xff0c;确保你的…

面试速通宝典——7

150. 数据库连接池的作用 数据库连接池的作用包括以下几个方面&#xff1a; 资源重用&#xff1a;连接池允许多个客户端共享有限的数据库连接&#xff0c;减少频繁创建和销毁连接的开销&#xff0c;从而提高资源的利用率。 统一的连接管理&#xff1a;连接池集中管理数据库连…

Stream流的终结方法(一)

1.Stream流的终结方法 2.forEach 对于forEach方法&#xff0c;用来遍历stream流中的所有数据 package com.njau.d10_my_stream;import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.function.Consumer; import java.util…

Swagger配置且添加小锁(asp.net)(笔记)

此博客是基于 asp.net core web api(.net core3.1)框架进行操作的。 一、安装Swagger包 在 NuGet程序包管理中安装下面的两个包&#xff1a; swagger包&#xff1a;Swashbuckle.AspNetCore swagger包过滤器&#xff1a;Swashbuckle.AspNetCore.Filters 二、swagger注册 在…

戴尔PowerEdge R840服务器亮黄灯 不开机

最近接修到一台东莞用户的DELL PowerEdge R840 服务器因为意外断电后&#xff0c;无法正常开机的问题&#xff0c; 大概故障现象是 插上电源线 按卡机按钮无响应&#xff0c;无法开机&#xff0c;无显示输出&#xff0c;工程师到现场检修&#xff0c;经过idrac中日志分析&#…

K8S真正删除pod

假设k8s的某个命名空间如&#xff08;default&#xff09;有一个运行nginx 的pod&#xff0c;而这个pod是以kubectl run pod命令运行的 1.错误示范&#xff1a; kubectl delete pod nginx-2756690723-hllbp 结果显示这个pod 是删除了&#xff0c;但k8s很快自动创建新的pod,但是…

C(九)while循环 --- 军训匕首操情景

匕首操&#xff0c;oi~oi~oi~~~~~ 接下来的几篇推文&#xff0c;杰哥记录的是三大循环结构的运行流程及其变式。 本篇的主角是while循环。&#x1f449; 目录&#xff1a; while循环 的组成、运行流程及其变式关键字break 和 continue 在while 循环中的作用while 循环的嵌套题目…

基于SSM的坚果金融投资管理系统、坚果金融投资管理平台的设计与开发、智慧金融投资管理系统的设计与实现、坚果金融投资管理系统的设计与应用研究(源码+定制+开发)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

我为什么决定关闭ChatGPT的记忆功能?

你好&#xff0c;我是三桥君 几个月前&#xff0c;ChatGPT宣布即将推出一项名为“记忆功能”的新特性&#xff0c;英文名叫memory。 这个功能听起来相当吸引人&#xff0c;宣传口号是让GPT更加了解用户&#xff0c;仿佛是要为我们每个人量身打造一个专属的AI助手。 在记忆功…

vue结合element-ui实现列表拖拽变化位置,点击拖动图标拖动整个列表元素,使用tsx格式编写

先来看下需要实现的效果 当鼠标放在左侧图标上时&#xff0c;可以拖动整个列表元素&#xff0c;调整顺序 思路介绍 使用draggable可以设置元素可拖动&#xff0c;然后分别设置三个事件处理函数&#xff0c;监听onDragstart、onDragover、onDragend三个事件 注意&#xff1a…

青少年科普教学系统小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;基础数据管理&#xff0c;作品信息管理&#xff0c;通知公告管理&#xff0c;视频信息管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&#xff0c;视频信息&…

html+css+js实现Collapse 折叠面板

实现效果&#xff1a; HTML部分 <div class"collapse"><ul><li><div class"header"><h4>一致性 Consistency</h4><span class"iconfont icon-jiantou"></span></div><div class"…

【unity进阶知识6】Resources的使用,如何封装一个Resources资源管理器

文章目录 一、Unity资源加载的几种方式1、Inspector窗口拖拽2、Resources3、AssetBundle4、Addressables&#xff08;可寻址资源系统&#xff09;5、AssetDatabase 二、准备三、同步加载Resources资源1、Resources.Load同步加载单个资源1.1、基本加载1.2、加载指定类型的资源1.…

泛型编程--模板【C++提升】(特化、类属、参数包的展开、static、模板机制、重载......你想知道的全都有)

更多精彩内容..... &#x1f389;❤️播主の主页✨&#x1f618; Stark、-CSDN博客 本文所在专栏&#xff1a; C系列语法知识_Stark、的博客-CSDN博客 其它专栏&#xff1a; 数据结构与算法_Stark、的博客-CSDN博客 C系列项目实战_Stark、的博客-CSDN博客 座右铭&#xff1a;梦…

国外电商系统开发-运维系统批量添加服务器

您可以把您准备的txt文件&#xff0c;安装要求的格式&#xff0c;复制粘贴到里面就可以了。注意格式&#xff01; 如果是“#” 开头的&#xff0c;则表示注释&#xff01;