<JAVA - 大作业(1)文本编辑器 >

背景

  • JAVA上机大作业:qq / 代码评价系统

  • 第一次上机主题是练习JAVA自带的GUI图形化编程

  • 目的:实现一个跟window10记事本界面相同,功能相近的文本编辑器,时间有剩余的话再添加类似notepad++上的一些额外功能。

  • 记事本结构

    • 标题栏

      显示标题title

    • 菜单栏

      文件、编辑、格式、查看、帮助 - 菜单项

      • <文件>下拉栏有:新建、新窗口、打开、保存、退出

      • <编辑>下拉栏有:撤销、恢复、剪切、复制、粘贴、删除

      • <格式>下拉栏有:字体

      • <帮助>下拉栏有:关于

    • 文本区域

      • 底侧滚动条

设计思路

  • 菜单栏:

    • 主体就是一个JFrame,设置一些属性,然后设置菜单栏JMenuBar,add菜单项JMenu,菜单项的下拉栏add菜单子项JMenuItem
  • 文本区域:

    • 完成菜单栏之后就是一个占屏幕率超大的JTextArea,注意该文本区域需要将他设置为静态,并且写一个静态get函数得到它,因为有跨类的需要改该文本属性。由于有滚动条,后续还要加上显示行号的功能,所以用一个JScrollPane装载它。
  • 文件菜单子栏:

    • 新建:就新建一个窗口new TextEdition(),并且把当前窗口退出dispose(),退出前调用一次保存函数savefile()

    • 新窗口:

      • 新建一个窗口,并且当前窗口不退出,两窗口相互不影响,即默认退出操作使用DISPOSE_ON_CLOSE(当然可以自己写,退出时加上是否保存询问)
    • 打开:

      • 使用JFileChooser,界面为打开界面,打开跳出一个Dialog对话框,选择文件进行打开,InputStreamReader+BufferedReader
    • 保存:

      • 使用JFileChooser,界面为保存界面,跟打开操作一样,OutputStreamWriter+BufferedWriter
    • 退出:

      • 调用保存函数savefile(),并且dispose()当前窗口
  • 编辑菜单子栏:

    • 撤销:

      • 撤销与恢复都需要用到撤销管理类um = new UndoManager(),在监听器初始化时注册撤销可编辑监听器 - 文本区域getDocument().addUndoableEditListener,撤销操作就是 um.undo()
    • 恢复:

      • 恢复操作与上一致,监听器设置好以后,调用um.redo()即是恢复
    • 剪切:

      • 剪切与复制、粘贴是一起完成,需要用到系统剪切板clipboard = this.getToolkit().getSystemClipboard(),剪切就是复制+删除操作
    • 复制:

      • 先将文本区域的文本放到string里面,创建能传输指定 String 的 StringSelection,把系统剪切板的内容设置成StringSelection:clipboard.setContents(editText,null);
    • 粘贴:

      • 先将系统剪切板的内容放在一个Transferable里面,之后再将Transferable转成string,文本区域append即可
    • 删除

      • getSelectionStart,getSelectionEnd得到头尾,再replaceRange替换成空文本即可
  • 格式菜单子栏:

    • 字体

      • 新建一个窗体设置字体,用JComboBox实现下拉列表,一个JTextField放演示文本,再是确认取消按钮,三个JPanel分别装这三部分整理布局排版,确认按钮点击后就调用静态get函数得到父窗体的文本区域设置其属性。
  • 帮助菜单子栏:

    • 关于

      • 弹出一个新窗体,里面用label写文本显示

TextEdition - 主窗体类实现

主窗体属性

ublic class TextEditor extends JFrame implements ActionListener{
// 其实我们这里也可以用ItemListener用于捕获带有item的组件产生的事件,
// 而ActionListener是所有监听器的父类,可以监听到所有的事件,由于担心还会有其他的事件需要监听,
// 所以就直接用 ActionListener 了 //菜单栏
private JMenuBar menuBar;
//菜单项
private JMenu menu_File,menu_Edit,menu_Help,menu_Format;
//file菜单项内容
private JMenuItem item_new,item_newwindow,item_open,item_save,item_exit;
//edit菜单项内容
private JMenuItem item_undo,item_redo,item_cut,item_copy,item_stick,item_delete;
//help菜单项内容
private JMenuItem item_about;
//format菜单项内容
private JMenuItem item_word_format; //文本区域
private static JTextArea edit_text_area; //static因为要在其他窗口对其他字体格式进行改动
//文本滚动条
private JScrollPane scroll_bar;
//撤销管理
private UndoManager um;
//系统剪切板
private Clipboard clipboard;
//文件选择器
private JFileChooser fileChooser;

主窗体构造器

public TextEditor()
{
initMenuBar();
initEditText();
initListener(); this.setJMenuBar(menuBar);
this.setSize(800,600);
this.add(scroll_bar);
this.setTitle("黄龙士文本编辑器");
this.setVisible(true);
this.setLocationRelativeTo(null); //窗体位于正中间位置
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // EXIT_ON_CLOSE https://www.cnblogs.com/lihaiming93/p/4752422.html 后续还要改,加上退出询问
}

initMenuBar() - 初始化菜单栏

private void initMenuBar() {

		//初始化菜单栏
menuBar = new JMenuBar(); //file菜单项
menu_File = new JMenu("文件(F)");
menu_File.setMnemonic('f'); // 设置快捷键-alt+f:打开 - 也可以传入KeyEvent.VK_F
item_new = new JMenuItem("新建");
item_newwindow = new JMenuItem("新窗口");
item_open = new JMenuItem("打开");
item_save = new JMenuItem("保存");
item_save.setAccelerator(KeyStroke.getKeyStroke('S',java.awt.Event.CTRL_MASK,false));//给item添加快捷键 CTRL_MASK = ctrl键
item_exit = new JMenuItem("退出");
menu_File.add(item_new);
menu_File.add(item_newwindow);
menu_File.add(item_open);
menu_File.add(item_save);
menu_File.add(item_exit); //edit菜单项
menu_Edit = new JMenu("编辑(E)");
menu_Edit.setMnemonic('e');
item_undo = new JMenuItem("撤销");
item_redo = new JMenuItem("恢复");
item_cut = new JMenuItem("剪切");
item_copy = new JMenuItem("复制");
item_stick = new JMenuItem("粘贴");
item_delete = new JMenuItem("删除");
menu_Edit.add(item_undo);
menu_Edit.add(item_redo);
menu_Edit.add(item_cut);
menu_Edit.add(item_copy);
menu_Edit.add(item_stick);
menu_Edit.add(item_delete); //help菜单项
menu_Help = new JMenu("帮助(H)");
menu_Help.setMnemonic('h');
item_about = new JMenuItem("关于");
menu_Help.add(item_about); //format菜单项
menu_Format = new JMenu("格式(O)");
menu_Format.setMnemonic('o');
item_word_format = new JMenuItem("字体(F)"); //CTRL_MASK = ctrl键
item_word_format.setAccelerator(KeyStroke.getKeyStroke('F',java.awt.Event.CTRL_MASK,false));//给item添加快捷键
menu_Format.add(item_word_format); //加入菜单栏
menuBar.add(menu_File);
menuBar.add(menu_Edit);
menuBar.add(menu_Format);
menuBar.add(menu_Help);
}

initEditText() - 初始化文本区域

private void initEditText() {

		edit_text_area = new JTextArea();
scroll_bar = new JScrollPane(edit_text_area);
//垂直滚动条总是出现 - 自动出现:JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED||VERTICAL_SCROLLBAR_ALWAYS
scroll_bar.setRowHeaderView(new LineNumberHeaderView()); //显示行号
// 具体显示行号类:https://blog.csdn.net/wangjianyu0115/article/details/50780269 scroll_bar.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
scroll_bar.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS); um = new UndoManager();
clipboard = this.getToolkit().getSystemClipboard();
}

saveFile - 保存文件

private void saveFile() {
// TODO Auto-generated method stub File file =null;
int result; //int型值,showSaveDialog返回值用来判断用户是否选择了文件或路径。
fileChooser = new JFileChooser("C:\\Users\\62473\\Desktop\\"); //打开用户默认目录
result = fileChooser.showSaveDialog(rootPane); // 设置Dialog的根View根布局 显示对话框 if(result == JFileChooser.APPROVE_OPTION) {
file = fileChooser.getSelectedFile(); // 若点击了确定按钮,给file填文件路径
}
else return; //按取消键后不会运行下面代码 try{
OutputStreamWriter write = new OutputStreamWriter(new FileOutputStream(file),"UTF-8"); // 对字符进行编码转换 输出流
BufferedWriter writer = new BufferedWriter(write);
for (String value : edit_text_area.getText().split("\n")) { // 实现在JTextArea多行如何转换到实际文本多行
writer.write(value);
writer.newLine();//换行
}
writer.close();
}
catch(IOException e) {
e.printStackTrace();
}
}

openfile() - 打开文件

private void openFile() {

		File file =null;
int result;
fileChooser =new JFileChooser("C:\\Users\\62473\\Desktop\\");
result = fileChooser.showOpenDialog(rootPane); if(result == JFileChooser.APPROVE_OPTION) {
file = fileChooser.getSelectedFile(); // 若点击了确定按钮,给file填文件路径
}
else return; //按取消键后不会运行下面代码 if(file.isFile() && file.exists()) {
try {
edit_text_area.setText(""); //清空目前文本内容
InputStreamReader inputStreamReader = new InputStreamReader(new FileInputStream(file),"UTF-8");
BufferedReader reader = new BufferedReader(inputStreamReader);
String readLine;
while ((readLine = reader.readLine()) != null) {
edit_text_area.append(readLine+'\n');
}
reader.close();
}
catch (IOException e) {
// TODO: handle exception
e.printStackTrace();
}
} }

actionPerformed(ActionEvent e) - 监听事件响应

public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
//https://zhidao.baidu.com/question/2204274734088183468.html if(e.getSource()==item_about)
{
new helpWindow();
}
else if (e.getSource()==item_word_format) {
new aboutFormat();
}
else if (e.getSource()==item_new) {
this.saveFile(); //新建文件前保存原文件
new TextEditor();
this.dispose();
}
else if (e.getSource()==item_newwindow) {
new TextEditor(); //添加新窗口,父窗口不会退出
}
else if (e.getSource()==item_exit){
this.saveFile();
this.dispose(); //退出询问(目前有无更改都会弹出保存窗口)
}
else if (e.getSource()==item_save) {
this.saveFile();
}
else if (e.getSource()==item_open) {
this.openFile();
}
else if (e.getSource()==item_undo&&um.canUndo()) { //撤销可以撤销是撤销上一步文本操作
um.undo();
}
else if (e.getSource()==item_redo&&um.canRedo()) { //恢复就是恢复上一步文本操作(需要被撤销)
um.redo();
}
else if (e.getSource()==item_copy) {
String temptext = edit_text_area.getSelectedText(); //得到选取文本
StringSelection editText = new StringSelection(temptext); //创建能传输指定 String 的 Transferable
clipboard.setContents(editText,null); // 将剪贴板的当前内容设置到指定的 transferable 对象,
// 并将指定的剪贴板所有者作为新内容的所有者注册。
}
else if (e.getSource()==item_cut) {
String temptext = edit_text_area.getSelectedText();
StringSelection editText = new StringSelection(temptext);
clipboard.setContents(editText,null);
int start= edit_text_area.getSelectionStart(); //复制+删除
int end = edit_text_area.getSelectionEnd();
edit_text_area.replaceRange("",start,end);
}
else if (e.getSource()==item_stick) {
Transferable contents = clipboard.getContents(this);
DataFlavor flavor= DataFlavor.stringFlavor;
if( contents.isDataFlavorSupported(flavor))
{
try
{
String str;
str = (String)contents.getTransferData(flavor);
edit_text_area.append(str);
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
else if (e.getSource()==item_delete) {
int start= edit_text_area.getSelectionStart(); //删除
int end = edit_text_area.getSelectionEnd();
edit_text_area.replaceRange("",start,end);
}
}

initListener() - 初始化监听器

public void initListener()
{
// 菜单iter监听
item_new.addActionListener(this);
item_newwindow.addActionListener(this);
item_open.addActionListener(this);
item_save.addActionListener(this);
item_exit.addActionListener(this);
item_undo.addActionListener(this);
item_redo.addActionListener(this);
item_cut.addActionListener(this);
item_copy.addActionListener(this);
item_stick.addActionListener(this);
item_delete.addActionListener(this);
item_word_format.addActionListener(this);
item_about.addActionListener(this); //注册撤销/恢复可编辑监听器
edit_text_area.getDocument().addUndoableEditListener(new UndoableEditListener(){
public void undoableEditHappened(UndoableEditEvent e) {
um.addEdit(e.getEdit());
}
}); }

getEdit_text_area() - 静态get函数得到文本区域

public static JTextArea getEdit_text_area() {
//返回文本编辑区给其他窗口
return edit_text_area;
}

main() - main函数

public static void main(String[] args) {

		TextEditor test = new TextEditor();

	}

}

aboutFormat - 字体窗口实现

字体窗口属性

public class aboutFormat extends JFrame implements ItemListener,ActionListener {

	private JComboBox choose_word_style;	//下拉列表
private JComboBox choose_word_big;
private JComboBox choose_word_pattern;
private JComboBox choose_word_color; private String[] styles = {"宋体","黑体","楷体","微软雅黑","隶书"};
private String[] colors = {"黑色","蓝色","绿色","红色","白色","黄色"};
private String[] word_big = {"2","4","8","16","24","32","64","72"};
private String[] pattern = {"常规","倾斜","粗体"}; private JPanel paneNorth;//用于装四个ComboBox
private JPanel paneCenter;//用来装演示区
private JPanel paneSouth;//用来装按钮 private JTextField showText;//演示文本 private JButton btn_ok;
private JButton btn_cancel; private Font selectedFont = TextEditor.getEdit_text_area().getFont(); //用来封装改变的属性
private String selectedStyle = "宋体"; //默认字体属性
private int selectedBig = 32;
private int selectedPattern = Font.PLAIN;
private Color selectedColor = TextEditor.getEdit_text_area().getForeground(); //颜色要单独加上改

字体窗口构造器

public aboutFormat() {
initBox();
initText();
initButton();
initLocation();
initListener();
addBtnListener(); this.setSize(550,240);
this.setTitle("文字格式");
this.setVisible(true);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}

addBtnListener() - 注册监听

private void addBtnListener() {
// TODO Auto-generated method stub //注册按钮监听
btn_cancel.addActionListener(this);
btn_ok.addActionListener(this);
}

initListener() - 初始化监听器

private void initListener() {		//注册下拉框监听
// TODO Auto-generated method stub
choose_word_style.addItemListener(this);
choose_word_big.addItemListener(this);
choose_word_pattern.addItemListener(this);
choose_word_color.addItemListener(this);
}

initButton() - 初始化按钮

private void initButton() {
// TODO Auto-generated method stub
btn_ok = new JButton("OK");
btn_cancel = new JButton("CANCEL");
}

initText() - 初始化演示文本

private void initText() {
// TODO Auto-generated method stub
showText = new JTextField("字体展示");
showText.setHorizontalAlignment(JTextField.CENTER); //文本居中
showText.setFont(selectedFont);
showText.setEditable(false); //不可编辑
showText.setSize(200,200);
// showText.setForeground(Color.green);//字体颜色
}

initLocation() - 初始化布局

/**
* 初始化布局
* 将每个控件按照一定得布局排在this窗口中
*/
public void initLocation() {
paneNorth = new JPanel();
paneNorth.add(new JLabel("字体:")); //添加下拉区
paneNorth.add(choose_word_style);
paneNorth.add(new JLabel("字号:"));
paneNorth.add(choose_word_big);
paneNorth.add(new JLabel("字形:"));
paneNorth.add(choose_word_pattern);
paneNorth.add(new JLabel("颜色:"));
paneNorth.add(choose_word_color);
paneNorth.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); //让add的组件不置顶
this.add(paneNorth,BorderLayout.NORTH); paneCenter = new JPanel(); //添加展示区
paneCenter.add(showText); this.add(paneCenter, BorderLayout.CENTER); //添加按钮去
paneSouth = new JPanel();
paneSouth.add(btn_ok);
paneSouth.add(btn_cancel);
this.add(paneSouth, BorderLayout.SOUTH); }

initBox() - 初始化下拉栏

/**
* 初始化几个comboBox
* 把相应的选项加入
*/
public void initBox() {
choose_word_style = new JComboBox(styles); //数组传入就不用addItem
choose_word_big = new JComboBox(word_big);
choose_word_pattern = new JComboBox(pattern);
choose_word_color = new JComboBox(colors);
}

actionPerformed(ActionEvent e) - 监听事件响应

@Override
public void actionPerformed(ActionEvent e) { //对按钮的监听
// TODO Auto-generated method stub
if (e.getSource() == btn_cancel) {
this.dispose();//销毁当前窗口
}else if (e.getSource() == btn_ok) { // 调用父窗体的实例,拿到text_area并对其setFont TextEditor.getEdit_text_area().setFont(selectedFont); //改字体
TextEditor.getEdit_text_area().setForeground(selectedColor); //改字体颜色
this.dispose();
}
}

itemStateChanged(ItemEvent e) - 下拉栏的监听

@Override
public void itemStateChanged(ItemEvent e) { //对下拉框的监听
// TODO Auto-generated method stub
if (e.getItem() == "宋体") {
selectedStyle = "宋体";
renewFont();
}else if (e.getItem() == "黑体") {
selectedStyle = "黑体";
renewFont();
}else if (e.getItem() == "楷体") {
selectedStyle = "楷体";
renewFont();
}else if (e.getItem() == "微软雅黑") {
selectedStyle = "微软雅黑";
renewFont();
}else if (e.getItem() == "隶书") {
selectedStyle = "隶书";
renewFont();
}else if (e.getItem() == "常规") {
selectedPattern = Font.PLAIN;
renewFont();
}else if (e.getItem() == "倾斜") {
selectedPattern = Font.ITALIC;
renewFont();
}else if (e.getItem() == "粗体") {
selectedPattern = Font.BOLD;
renewFont();
}else if (e.getItem() == "2") {
selectedBig = 2;
renewFont();
}else if (e.getItem() == "4") {
selectedBig = 4;
renewFont();
}else if (e.getItem() == "8") {
selectedBig = 8;
renewFont();
}else if (e.getItem() == "16") {
selectedBig = 16;
renewFont();
}else if (e.getItem() == "24") {
selectedBig = 24;
renewFont();
}else if (e.getItem() == "32") {
selectedBig = 32;
renewFont();
}else if (e.getItem() == "64") {
selectedBig = 64;
renewFont();
}else if (e.getItem() == "72") {
selectedBig = 72;
renewFont();
}else if (e.getItem() == "红色") {
selectedColor = Color.red;
renewFont();
}else if (e.getItem() == "黑色") {
selectedColor = Color.black;
renewFont();
}else if (e.getItem() == "蓝色") {
selectedColor = Color.blue;
renewFont();
}else if (e.getItem() == "黄色") {
selectedColor = Color.yellow;
renewFont();
}else if (e.getItem() == "绿色") {
selectedColor = Color.green;
renewFont();
}else if (e.getItem() == "白色") {
selectedColor = Color.WHITE;
renewFont();
}
}

renewFont() - 更改默认字体

private void renewFont() {
// TODO Auto-generated method stub
selectedFont = new Font(selectedStyle,selectedPattern,selectedBig);
showText.setFont(selectedFont);
showText.setForeground(selectedColor);
} }

helpWindow - 帮助窗口实现

帮助窗口属性

public class helpWindow extends JFrame {

	private JButton btn_ok;
private JLabel about_label; private JPanel panel ;
private BoxLayout boxlayout; //指定在容器中是否对控件进行水平或者垂直放置

帮助窗口构造器

	public helpWindow() {
panel = new JPanel(); //轻量级面板容器
boxlayout = new BoxLayout(panel,BoxLayout.Y_AXIS); //Y_AXIS - 控件垂直放置
panel.setLayout(boxlayout); btn_ok = new JButton("OK");
btn_ok.setAlignmentX(CENTER_ALIGNMENT); //alignment对齐
// about_label = new JLabel("https://www.cnblogs.com/ymjun/");
about_label = new JLabel("<html><br /><h3 style='text-align:center;color:brown;'>黄龙士文本编辑器</h3>" //JLabel里面可以嵌入html
+ "blog:https://www.cnblogs.com/ymjun/<br />"
+ "github:https://github.com/iym070010<br />"
+ "email:iym070010@163.com<br />"
+ "使用方式跟.txt文本编辑器一致<br />"
+ "<br /><br />"
+ "</html>",JLabel.CENTER);
about_label.setAlignmentX(CENTER_ALIGNMENT); panel.add(about_label);
panel.add(btn_ok); this.add(panel);
this.setSize(400,300);
this.setTitle("关于");
this.setVisible(true);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); btn_ok.addActionListener(e->{ //窗口关闭
this.dispose();
});
}
}

LineNumberHeaderView - TextArea行数显示插件

//package com.ui;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Rectangle;
//TEXTAREA 行号显示插件
public class LineNumberHeaderView extends javax.swing.JComponent { //貌似就是Notepad++行号显示的实现类 /**
* JAVA TextArea行数显示插件
*/
private static final long serialVersionUID = 1L;
private final Font DEFAULT_FONT = new Font(Font.MONOSPACED, Font.PLAIN, 11);
public final Color DEFAULT_BACKGROUD = new Color(228, 228, 228);
public final Color DEFAULT_FOREGROUD = Color.BLACK;
public final int nHEIGHT = Integer.MAX_VALUE - 1000000;
public final int MARGIN = 5;
private int lineHeight;
private int fontLineHeight;
private int currentRowWidth;
private FontMetrics fontMetrics; public LineNumberHeaderView() {
setFont(DEFAULT_FONT);
setForeground(DEFAULT_FOREGROUD);
setBackground(DEFAULT_BACKGROUD);
setPreferredSize(9999);
} public void setPreferredSize(int row) {
int width = fontMetrics.stringWidth(String.valueOf(row));
if (currentRowWidth < width) {
currentRowWidth = width;
setPreferredSize(new Dimension(2 * MARGIN + width + 1, nHEIGHT));
}
} @Override
public void setFont(Font font) {
super.setFont(font);
fontMetrics = getFontMetrics(getFont());
fontLineHeight = fontMetrics.getHeight();
} public int getLineHeight() {
if (lineHeight == 0) {
return fontLineHeight;
}
return lineHeight;
} public void setLineHeight(int lineHeight) {
if (lineHeight > 0) {
this.lineHeight = lineHeight;
}
} public int getStartOffset() {
return 4;
} @Override
protected void paintComponent(Graphics g) {
int nlineHeight = getLineHeight();
int startOffset = getStartOffset();
Rectangle drawHere = g.getClipBounds();
g.setColor(getBackground());
g.fillRect(drawHere.x, drawHere.y, drawHere.width, drawHere.height);
g.setColor(getForeground());
int startLineNum = (drawHere.y / nlineHeight) + 1;
int endLineNum = startLineNum + (drawHere.height / nlineHeight);
int start = (drawHere.y / nlineHeight) * nlineHeight + nlineHeight - startOffset;
for (int i = startLineNum; i <= endLineNum; ++i) {
String lineNum = String.valueOf(i);
int width = fontMetrics.stringWidth(lineNum);
g.drawString(lineNum + " ", MARGIN + currentRowWidth - width - 1, start);
start += nlineHeight;
}
setPreferredSize(endLineNum);
}
}

<JAVA - 大作业(1)文本编辑器 >的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. beeline链接hive报错

    看问题:beeline连接hiveserver2报错.连接串:hive  --service beeline -u jdbc:hive2://localhost:10000/hive 错误:Error ...

  2. 【JMeter4.0】二、JMeter4.0安装与配置

    二.安装配置JMeter jmeter是一个纯java工具,因此,JDK必不可少,现在最新版的jmeter是4.0,建议使用1.8及以上的JDK安装配置JDK,如没有,请见:[JMeter4.0]一. ...

  3. Xshell实现Windows和使用跳板机跳转的远程Linux互传文件

    适用于Linux CentOS版本,本地电脑是Win10版本 查询Linux版本: $lsb_release -a $cat /etc/issue 1.使用Xshell 连接上服务器 2.安装文件传输 ...

  4. JavaScript中函数带与不带括号的区别

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  5. vue-loader was used without the corresponding plugin. Make sure to include VueLoaderPlugin

    场景: . webpack2.4.*集成vue-loader@15.7.2报错 原因: 参考官方文档 https://vue-loader.vuejs.org/migrating.html#a-plu ...

  6. XMPP即时通讯协议使用(六)——开发Openfire聊天记录插件

    转载地址:http://www.cnblogs.com/hoojo/archive/2013/03/29/openfire_plugin_chatlogs_plugin_.html 开发环境: Sys ...

  7. Xcode 及 iOS 常用宏和常量

    Xcode Xcode 工程设置支持 bash 脚本及其语法,如 $(PROJECT_DIR)$(PROJECT_DIR) PROJECT_DIR 代表当前工程的绝对路径,所以 $(PROJECT_D ...

  8. psfstriptable - 从控制台字体中移走嵌入的Uniocde字符表

    总览 psfstriptable 字体文件 [输出文件] 描述 psfstriptable 命令从 字体文件 或者标准输入(此时的 字体文件 是单个破折号(-))读取一个可能含有嵌入Unicode字体 ...

  9. python数字图像处理(四) 频率域滤波

    import matplotlib.pyplot as plt import numpy as np import cv2 %matplotlib inline 首先读入这次需要使用的图像 img = ...

  10. Hibernate纯sql查询VO对象封装

    hibernate 纯sql查询返回结果集(未关联映射)组装VO的问题//须保证别名字段与Vo字段一致 //引号中为vo对象属性需与sql查询返回字段一致.addScalar("chname ...