Web监听器:Listener

news2025/1/10 21:59:52

Listener

  • 简介
    • 常用监听接口
  • 监听在线用户信息的实现
    • Model层
    • Controller层
    • OnlineUserListener的实现
    • View层
    • 测试

简介

监听器(Listener),是一个实现特定接口的普通Java程序,用于监听Web应用中的对象或信息发生改变时,作出相应的响应处理。当被监听对象的状态发生变化时,服务器会自动调用监听器对象中的方法。监听器常常用于系统加载时进行信息初始化、统计在线人数或用户和网站的访问量等。

在这里插入图片描述

常用监听接口

接口作用
ServletContextListener监听Web的启动与关闭
ServletContextAttributeListener监听ServletContext范围内属性的改变
ServletRequestListener监听用户请求
ServletRequestAttributeListener监听ServletRequest范围内属性的改变
HttpSessionListener监听用户session的开始与结束
HttpSessionAttributeListener监听HttpSession范围内属性的改变

监听在线用户信息的实现

首先,创建一个在线用户的表onlineusers,表结构如下图:

在这里插入图片描述

Model层

然后,创建一个在线用户表onlineusers与之相映射的主体类OnlineUers,代码如下:
其中,在线用户的属性信息:
sign—主键(session_id)
username—用户名
apage—访问的网页
ip—ip地址
atime—访问的时间(注意:Date类型)

package cn.edu.MVCcase.Model.model;

import java.util.Date;

//在线状态用户类
public class OnlineUers {
    private String sign;
    private String username;
    private String apage;
    private String ip;
    private Date atime;

    public OnlineUers() {
        super();
    }

    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getApage() {
        return apage;
    }

    public void setApage(String apage) {
        this.apage = apage;
    }

    public String getIp() {
        return ip;
    }

    public void setIp(String ip) {
        this.ip = ip;
    }

    public Date getAtime() {

        return atime;
    }

    public void setAtime(Date atime) {
        this.atime = atime;
    }

    public OnlineUers(String sign, String username, String apage, String ip, Date atime) {
        this.sign = sign;
        this.username = username;
        this.apage = apage;
        this.ip = ip;
        this.atime = atime;
    }

    @Override
    public String toString() {
        return "OnlineUers{" +
                "sign='" + sign + '\'' +
                ", username='" + username + '\'' +
                ", apage='" + apage + '\'' +
                ", ip='" + ip + '\'' +
                ", atime='" + atime + '\'' +
                '}';
    }
}

接着,设置实现对数据库onlineusers表的操作的接口OnlineUersDao,代码如下:

package cn.edu.MVCcase.Model.dao;

import cn.edu.MVCcase.Model.model.OnlineUers;
import java.util.List;

public interface OnlineUersDao {
    //获取在线用户所有信息
    public List<OnlineUers> getOnlineUserInformation();

    //新增在线用户信息
    public void insertOnlineUserInformation(OnlineUers onlineUers);

    //更新在新用户信息
    public void updateOnlineUserInformation(OnlineUers onlineUers);

    //根据sign删除已下线的用户信息
    public void deleteOfflineUserInformation(String sign);

    //根据sgin获取在线用户信息
    public OnlineUers getOnlineUserInformationBySign(String sign);
}

再实现接口OnlineUersDao的类OnlineUersDaoImpl,同时需要继承Dao的通用基本类CurrencyDao< OnlineUers > (MVC案例的内容),代码如下:

package cn.edu.MVCcase.Model.dao;

import cn.edu.MVCcase.Model.model.OnlineUers;

import java.util.List;

public class OnlineUersDaoImpl extends CurrencyDao<OnlineUers> implements OnlineUersDao  {
    @Override
    public List<OnlineUers> getOnlineUserInformation() {
        String sql = "SELECT `sign`,`username`,`apage`,`ip`,`atime` FROM `onlineusers`";
        return super.getList(sql);
    }

    @Override
    public void insertOnlineUserInformation(OnlineUers onlineUers) {
        String sql = "INSERT `onlineusers` SET `sign`=?,`username`=?,`apage`=?,`ip`=?,`atime`=?";
        super.TableOperation(sql,onlineUers.getSign(),onlineUers.getUsername(),onlineUers.getApage(),onlineUers.getIp(),onlineUers.getAtime());
    }

    @Override
    public void updateOnlineUserInformation(OnlineUers onlineUers) {
        String sql = "UPDATE `onlineusers` SET `username`=?,`apage`=?,`ip`=?,`atime`=? WHERE `sign`=?";
        super.TableOperation(sql,onlineUers.getUsername(),onlineUers.getApage(),onlineUers.getIp(),onlineUers.getAtime(),onlineUers.getSign());
    }

    @Override
    public void deleteOfflineUserInformation(String sign) {
        String sql = "DELETE FROM `onlineusers` WHERE `sign`=?";
        super.TableOperation(sql,sign);
    }

    @Override
    public OnlineUers getOnlineUserInformationBySign(String sign) {
        String sql = "SELECT `sign`,`username`,`apage`,`ip`,`atime` FROM `onlineusers` WHERE `sign`=?";
        return super.getSelect(sql,sign);
    }
}

同时,为了实现解耦,降低模块间的依赖性,提高程序的独立性,在FactoryDao类中添加如下代码:

public static OnlineUersDao getOnlineUersDao() { return new OnlineUersDaoImpl(); }

再接着,设置对业务处理的接口OnlineUersService,代码如下:

package cn.edu.MVCcase.Model.service;

import cn.edu.MVCcase.Model.model.OnlineUers;

import java.util.List;

public interface OnlineUersService {
    //获取在线用户所有信息
    public List<OnlineUers> getOnlineUserInformation();

    //新增在线用户信息
    public void insertOnlineUserInformation(OnlineUers onlineUers);

    //更新在新用户信息
    public void updateOnlineUserInformation(OnlineUers onlineUers);

    //根据sign删除已下线的用户信息
    public void deleteOfflineUserInformation(List<OnlineUers> list);

    //根据sgin获取在线用户信息
    public OnlineUers getOnlineUserInformationBySign(String sign);
}

同理,设置实现接口OnlineUersService的类OnlineUersServiceImpl,代码如下:

package cn.edu.MVCcase.Model.service;

import cn.edu.MVCcase.Model.dao.FactoryDao;
import cn.edu.MVCcase.Model.dao.OnlineUersDao;
import cn.edu.MVCcase.Model.model.OnlineUers;

import java.util.List;

public class OnlineUersServiceImpl implements OnlineUersService {
    OnlineUersDao onlineUersDao = FactoryDao.getOnlineUersDao();

    @Override
    public List<OnlineUers> getOnlineUserInformation() {
        return onlineUersDao.getOnlineUserInformation();
    }

    @Override
    public void insertOnlineUserInformation(OnlineUers onlineUers) {
        onlineUersDao.insertOnlineUserInformation(onlineUers);
    }

    @Override
    public void updateOnlineUserInformation(OnlineUers onlineUers) {
        onlineUersDao.updateOnlineUserInformation(onlineUers);
    }

    @Override
    public void deleteOfflineUserInformation(List<OnlineUers> list) {
        //遍历删除
        if(list != null && list.size() > 0) {
            for (OnlineUers onlineUers:list) {
                onlineUersDao.deleteOfflineUserInformation(onlineUers.getSign());
            }
        }
    }

    @Override
    public OnlineUers getOnlineUserInformationBySign(String sign) {
        return onlineUersDao.getOnlineUserInformationBySign(sign);
    }
}

同理,在类FactoryService中添加如下代码:

public static OnlineUersService getOnlineUersService() { return new OnlineUersServiceImpl(); }

Controller层

最后,调用service来实现业务,代码如下:

package cn.edu.MVCcase.Controller.controller;

import cn.edu.MVCcase.Model.model.OnlineUers;
import cn.edu.MVCcase.Model.service.FactoryService;
import cn.edu.MVCcase.Model.service.OnlineUersService;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;

@WebServlet(urlPatterns={"*.onlineuserdo"})
public class OnlineUserController extends HttpServlet {
    private static final long serialVersionUID = 1L;

    OnlineUersService onlineUersService = FactoryService.getOnlineUersService();

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        doPost(req,resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置字符集
        req.setCharacterEncoding("UTF-8");
        resp.setCharacterEncoding("UTF-8");

        //获取URL的文件名,如/select.studo
        String pathname = req.getServletPath();
        //截取select.studo
        pathname = pathname.substring(1);
        //截取select
        pathname = pathname.substring(0,pathname.length()-13);
        //获取pathname通过反射调用相应的方法
        try {
            Method method = this.getClass().getDeclaredMethod(pathname,HttpServletRequest.class,HttpServletResponse.class);
            method.invoke(this,req,resp);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void onlineuser(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        List<OnlineUers> list = onlineUersService.getOnlineUserInformation();
        req.setAttribute("onlineuser",list);
        req.getRequestDispatcher("/OnlineUser.jsp").forward(req,resp);
    }
}

OnlineUserListener的实现

监听器实现的基本思路:
首先,记录在线用户信息并写入到onlineuser表中(判断是否存在,如果存在,则更新访问时间与访问页面;如果不存在,则插入该信息);同时,假设在线用户超过十分钟处于静止状态(即没有任何操作),则视为用户已下线,onlineuser表中需要删除该信息(OnlineUserServletContextListener类实现:服务器启动时,每五秒进行检查,发现离线用户则删除该信息);最后,游客登录成功后需要将username改为对应的用户名。

在线用户的监听,信息获取或更新的实现,代码如下:

package cn.edu.MVCcase.OnlineUserListener.listener;

import cn.edu.MVCcase.Model.model.OnlineUers;
import cn.edu.MVCcase.Model.service.FactoryService;
import cn.edu.MVCcase.Model.service.OnlineUersService;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;

@WebListener
public class OnlineUserListener implements ServletRequestListener {

    OnlineUersService onlineUersService = FactoryService.getOnlineUersService(); //OnlineUersService对象,用于请求操作数据库

    @Override
    public void requestDestroyed(ServletRequestEvent servletRequestEvent) {

    }

    @Override
    public void requestInitialized(ServletRequestEvent servletRequestEvent) {
        //获取在线用户信息
        HttpServletRequest servletRequest = (HttpServletRequest)servletRequestEvent.getServletRequest();
        HttpSession session = servletRequest.getSession();

        //获取session_id(即sign)
        String sign = session.getId();

        //获取usekey
        String username = (String) session.getAttribute("admin");
        username = username==null?"游客":username;

        //获取访问的页面
        String apage = servletRequest.getRequestURI();

        //获取ip地址
        String ip = servletRequest.getRemoteAddr();

        //操作数据库前先将信息封装
        OnlineUers onlineUers = new OnlineUers();
        onlineUers.setSign(sign);
        onlineUers.setUsername(username);
        onlineUers.setApage(apage);
        onlineUers.setIp(ip);
        onlineUers.setAtime(new Date());

        //获取访问时间
        OnlineUers onlineUersTableOperation = onlineUersService.getOnlineUserInformationBySign(sign);
        if(onlineUersTableOperation != null) {
            //更新访问时间与页面
            onlineUersTableOperation.setAtime(new Date());
            onlineUersTableOperation.setApage(apage);
            onlineUersService.updateOnlineUserInformation(onlineUers);
        }
        else {
            //插入信息
            onlineUersService.insertOnlineUserInformation(onlineUers);
        }
    }
}

离线用户的监听,离线用户信息删除与清空的实现,代码如下:

package cn.edu.MVCcase.OnlineUserListener.listener;

import cn.edu.MVCcase.Model.model.OnlineUers;
import cn.edu.MVCcase.Model.service.FactoryService;
import cn.edu.MVCcase.Model.service.OnlineUersService;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@WebListener
public class OnlineUserServletContextListener implements ServletContextListener {

    //定义十分钟
    public final int MAX_Millis = 10*60*1000;

    OnlineUersService onlineUersService = FactoryService.getOnlineUersService();

    @Override
    //服务器启动时被执行
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        //视为已下线用户信息
        List<OnlineUers> OfflineUsers = new ArrayList<>();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        //设置定时器(每隔五秒执行)
        new Timer(5*1000, new ActionListener(){
            @Override
            //检查的具体方法
            public void actionPerformed(ActionEvent event) {
                //获取在线用户信息
                List<OnlineUers> list = onlineUersService.getOnlineUserInformation();
                if(list != null && list.size() > 0 ) {
                    Date OffDate = null;
                    for (OnlineUers onlineUers:list) {
                        OffDate = onlineUers.getAtime();
                        simpleDateFormat.format(OffDate);
                        Long OffMillis;
                        try {
                            OffMillis = simpleDateFormat.parse(OffDate.toString()).getTime();
                            //当前系统时间,System.currentTimeMillis()
                            //时间转换成时间戳,Long.parseLong(onlineUers.getAtime().toString())
                            if ((System.currentTimeMillis()-OffMillis) > MAX_Millis) {
                                OfflineUsers.add(onlineUers);
                            }
                        } catch (ParseException e) {
                            e.printStackTrace();
                        }
                    }
                }
                //删除已下线用户的信息
                onlineUersService.deleteOfflineUserInformation(OfflineUsers);
                //再清空已下线用户信息
                OfflineUsers.clear();
            }
        }).start();
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}

用户登录的监听,游客登录成功的username对应修改的实现(注:登录代码中凡成功登录跳转主页面的都需添加),代码如下:

//成功登录,username由游客变成对应的用户名
OnlineUersService onlineUersService = FactoryService.getOnlineUersService();
HttpSession session = req.getSession();
OnlineUers onlineUers = onlineUersService.getOnlineUserInformationBySign(session.getId());
if (onlineUers != null) {
    //更换
    onlineUers.setUsername(username);
    //更新
    onlineUersService.updateOnlineUserInformation(onlineUers);
}

View层

现在是重点讲解Listener知识,所以简单做个页面看看,不做太多的修饰,代码如下:

<%@ page import="cn.edu.MVCcase.Model.model.OnlineUers" %>
<%@ page import="java.util.List" %>
<%--
  Created by IntelliJ IDEA.
  User: dell
  Date: 2022/10/15
  Time: 12:57
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>在线用户</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" type="text/css" href="CSS/StudentDao.css">
</head>
<body>
    <form action="<%=request.getContextPath()%>/onlineuser.onlineuserdo" method="post">
        <div id="div_StuDao">
            <table id="StuTB">
                <tr>
                    <th>sign</th>
                    <th>userkey</th>
                    <th>访问的页面</th>
                    <th>ip地址</th>
                    <th>访问的时间</th>
                </tr>

                <%
                    List<OnlineUers> list = (List<OnlineUers>) request.getAttribute("onlineuser");
                    //list有值才进行遍历获取元素
                    if(list != null && list.size()>0) {
                        for(OnlineUers onlineUers:list){
                %>

                <tr>
                    <td><%=onlineUers.getSign()%></td>
                    <td><%=onlineUers.getUsername()%></td>
                    <td><%=onlineUers.getApage()%></td>
                    <td><%=onlineUers.getIp()%></td>
                    <td><%=onlineUers.getAtime()%></td>
                </tr>
                <%
                        }
                    }
                %>
            </table>
        </div>
    </form>
</body>
</html>

测试

administrator表中有两个账号,测试将两个账号分别在不同的浏览器同时登录,admin在onlineuser.onlineuserdo下观看监听情况,小明在登录主页面。如下图:

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

大前端进阶

目录 1.概述和前端工具vscode安装 1.下载安装VScode 2.中文界面配置 3.插件安装 4.设置字体大小 5.开启完整的Emmet语法支持 2.Nodejs 1.Nodejs介绍与安装 2.快速入门-Hello World 3.Node - 实现请求响应 4.Node-操作MYSQL数据库 3.Es6 1.ES6的概述 2.ES6的语法…

Docker实战:使用Dockerfile部署第一个netcore程序

目录 1、创建一个NetCore API项目 2、云服务部署 2.1 首先登录云服务器创建一个测试目录 2.2 新建dockerfile文件用来构建镜像。 2.3 构建镜像 2.4 运行镜像 目录 1、创建一个NetCore API项目 2、云服务部署 2.1 首先登录云服务器创建一个测试目录 2.2 新建dockerfil…

Python3,10h行代码,制作艺术签名,从此走上人生巅峰。

制作艺术签名1、引言2、代码实战2.1 代码示例3、总结1、引言 小鱼&#xff1a;小屌丝&#xff0c;你在画啥呢&#xff1f; 小屌丝&#xff1a;… 我这在练习签名呢。 小鱼&#xff1a;这… 艺术签&#xff1f; 小屌丝&#xff1a;喔&#xff0c;鱼哥&#xff0c;你这真实博才多…

CSDN云IDE怎样克隆代码

文章目录1、怎样从GitHub导入项目&#xff1f;1.1、系统生成SSH-KEY2、克隆代码2.1、克隆代码方式一2.2、克隆代码方式二2.3、克隆代码方式三1、怎样从GitHub导入项目&#xff1f; 1.1、系统生成SSH-KEY 1、打开Terminal 2、查看是否存在现有的ssh密钥 $ ls -al ~/.ssh3、检…

【LeetCode】【二叉树的最近公共祖先】

力扣 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以是它自…

《JavaSE-第十四章》之文件(一)

前言 在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!” 博客主页&#xff1a;KC老衲爱尼姑的博客主页 博主的github&#xff0c;平常所写代码皆在于此 刷题求职神器 共勉&#xff1a;talk is cheap, show me the code 作者是爪哇岛的新手&#xff0c;水…

Go 语言中的并发编程(Let‘s Go 二十八)

Go从底层就支持并发编程&#xff0c;同时实现垃圾回收机制。 先了解并发相关的几个名词概念。 进程&#xff1a;系统进行资源分配和调度的基本单位&#xff0c;使系统结构的基础&#xff0c;它是一个实体。 线程&#xff1a;是程序中一个单一的顺序执行流程&#xff0c;是进程…

python做了个自动关机工具,再也不会耽误我下班啦

上班族经常会遇到这样情况&#xff0c;着急下班结果将关机误点成重启&#xff0c;或者临近下班又通知开会&#xff0c;开完会已经迟了还要去给电脑关机。 【阅读全文】 今天使用PyQt5做了个自动关机的小工具&#xff0c;设置好关机时间然后直接提交即可&#xff0c;下班就可以…

什么是JWT及在JAVA中如何使用?

目录 1、为什么使用JWT? 2、JWT 的 格式 3、使用 JWT 就绝对安全 吗&#xff1f; 4、JWT 的 鉴权 流程 5、JWT 入门案例 5.1 引入依赖 5.2 生成Token 5.3 解析Token 5.4 工具类 JSON Web token简称JWT&#xff0c; 是用于对应用程序上的用户进行身份验证的标记。 也就…

测试中台初始设置

1.0 测试资源池 存在测试资源之后&#xff0c;将测试资源进行统一的管理&#xff0c;针对不同的测试场景和目的来定义不同的测试环境。将测试资源进行组合&#xff0c;测试平台可以对测试资源池进行统一的功能。 2.0 可用性测试及冒烟测试 可用性测试和冒烟测试都是快速验证…

基于Ubuntu搭建CTFd平台(全网最全)

前言&#xff1a; 最近在看《CTF安全竞赛入门》这本书&#xff0c;里面提到了搭建CTFd平台用于练习&#xff0c;学者可以在本地虚拟机上搭建。 所需系统&#xff1a;Ubuntu20.04 怎么安装虚拟机和配置Ubuntu这里就不再赘述了。 记得给Ubuntu配置VM tools1&#xff0c;方便把w…

软考中级(软件设计师)——面向对象程序设计(C++Java二选一的题15分-目标3分)

软考中级(软件设计师)——面向对象程序设计(C&Java二选一的题15分-目标3分) 目录 软考中级(软件设计师)——面向对象程序设计(C&Java二选一的题15分-目标3分) C语法要点 C类的定义&#xff1a; C派生类的定义&#xff1a; C类的外定义函数&#xff1a; C虚函数与…

Python Flask框架-开发简单博客-开篇介绍

作者&#xff1a;Eason_LYC 悲观者预言失败&#xff0c;十言九中。 乐观者创造奇迹&#xff0c;一次即可。 一个人的价值&#xff0c;在于他拥有的&#xff0c;而不是他会的。所以可以不学无数&#xff0c;但不能一无所有&#xff01; 技术领域&#xff1a;WEB安全、网络攻防 关…

PHP基础学习第十六篇(了解数组、创建数组、数组排序、总结数组的使用)

一、什么是数组 数组是一个能在单个变量中存储多个值的特殊变量。 如果有一个项目清单&#xff08;例如&#xff1a;序号名单&#xff09;&#xff0c;将其存储到单个变量中&#xff0c;如下所示&#xff1a; $a1;$b2;$c3; 然而&#xff0c;如果想要遍历数组并找出特定的一…

School assignment

目录 一、常用控制类汇编指令 二、编程实现统计寄存器AX中“1”和“0”的个数 三、编程实现从键盘输入10个1位整数 四、编程实现从键盘输入两个10进制的2位整数的和 五、编写程序练习直接、间接、相对、基址变址寻址 一、常用控制类汇编指令 MOV 传送字或字节. MOVSX 先…

JVM虚拟机

"天下事有难易乎&#xff1f;为之则易&#xff0c;不为则难" 一、初识JVM JVM是一个跨语言的平台&#xff0c;为那些能够跨平台运行的程序提供一个平台&#xff0c;JVM本身与java语言没有必然的联系&#xff0c;它只与特定的二进制文件格式.class文件所关联&#xff…

人生重开模拟器(Python实现)

文章目录人生重开模拟器介绍代码实现打印初始界面设置初始属性设置角色性别设置角色出生点针对每一岁&#xff0c;生成人生经历人生重开模拟器介绍 人生重开模拟器是由VickScarlet上传至GitHub的一款简单的文字网页游戏。 玩家点击“立即重开”并设置角色的初始属性后&#xf…

HTML 学习总结

超级详细的 HTML 学习笔记&#xff0c;一篇入门系列&#xff01;&#xff01;耐心读一遍 复习必备&#xff01;&#xff01; 目录 简要 认识标签 基本结构 常见标签 1. 注释 ---> ctrl / 2. 标题标签 ---> h1 h2 h3 h4 h5 h6 3. 段落标签 ---> p 4. 换行 ---> br …

Git | 一文带你零基础快速上手Git

&#x1f451; 博主简介&#xff1a;    &#x1f947; Java领域新星创作者    &#x1f947; 阿里云开发者社区专家博主、星级博主、技术博主 &#x1f91d; 交流社区&#xff1a;BoBooY&#xff08;优质编程学习笔记社区&#xff09; 前言&#xff1a;本文适合零基础小白…

Docker

目录1、docker介绍1.1 docker是什么1.2 容器与虚拟机的比较2、docker安装2.1 docker 基本组成2.2 安装步骤2.3 阿里云镜像加速2.4 run干了什么3、docker常用命令3.1 帮助命令及启动命令3.2 镜像命令3.3 容器命令4、Docker镜像4.1 镜像是什么&#xff1f;4.2 分层镜像 UnionFS 联…