【开源项目--稻草】Day05

news2024/11/26 8:20:31

【开源项目--稻草】Day05

  • 1. 显示问题列表
    • 1.1 显示问题持续时间
  • 2. 显示问题的标签列表
    • 2.1 实现过程
  • 3.显示问题的图片
  • 4. 实现分页功能
    • 4.1 为什么需要分页(翻页)
    • 4.2 实现分页的sql语句
    • 4.3 PageHelper的使用
    • 控制器的调用和VUE代码的重构
    • 分页导航条的配置

1. 显示问题列表

上次课中显示问题列表中的用户昵称位置属性编写错了

需要修改为

<small class="list-inline-item"
                  v-text="question.userNickName">风继续吹</small>

1.1 显示问题持续时间

现在流行的处理问题时间的方式不是单纯的显示这个问题的提问时间

而是显示出这个问题出现了多久可能又一下情况

  • 刚刚(1分钟之内)
  • XX分钟前(60分钟以内)
  • XX小时前(24小时以内)
  • XX天前
    由于时间是数据库中保存好的信息,这个信息已经以JSON格式发送到了ajax中

所以添加这个功能不需要编写后台代码

首先在index.js文件中添加一个计算持续时间的方法

updateDuration,并在ajax中调用
代码如下

/*
显示当前用户的问题
 */
let questionsApp = new Vue({
    el:'#questionsApp',
    data: {
        questions:[]
    },
    methods: {
        loadQuestions:function () {
            $.ajax({
                url: '/v1/questions/my',
                method: "GET",
                success: function (r) {
                    console.log("成功加载数据");
                    console.log(r);
                    if(r.code === OK){
                        questionsApp.questions = r.data;
                        //调用计算持续时间的方法
                        questionsApp.updateDuration();
                    }
                }
            });
        },
        updateDuration:function () {
            let questions=this.questions;
            for(let i=0;i<questions.length;i++){
                //获得问题中的创建时间属性(毫秒数)
                let createtime=new Date(questions[i].createtime).getTime();
                //获得当前时间的毫秒数
                let now=new Date().getTime();
                //计算时间差(秒)
                let durtaion=(now-createtime)/1000;
                if(durtaion<60){
                    // 显示刚刚
                    //duration这个名字可以随便起,只要保证和页面上取的一样就行
                    questions[i].duration="刚刚";
                }else if(durtaion<60*60){
                    // 显示XX分钟
                    questions[i].duration=
                        (durtaion/60).toFixed(0)+"分钟前";
                }else if (durtaion<60*60*24){
                    //显示XX小时
                    questions[i].duration=
                        (durtaion/60/60).toFixed(0)+"小时前";
                }else{
                    //显示XX天
                    questions[i].duration=
                        (durtaion/60/60/24).toFixed(0)+"天前";
                }}}
    },
    created:function () {
        console.log("执行了方法");
        this.loadQuestions(1);
    }
});

Index.html页面也需要进行一个修改,让计算出的持续时间显示出来

代码如下

<small class="list-inline-item"
                 v-text="question.duration">13分钟前</small>

2. 显示问题的标签列表

页面中的问题是可以多个标签的
在这里插入图片描述
怎么实现显示多个标签呢?

首先来了解一下标签和问题的对应关系
在这里插入图片描述
我们可以看到,在问题表中我们保持了冗余的数据列tag_names,这么做的好处就是减少查询时的复杂度,实际开发中程序员们也可能用这样的方式

2.1 实现过程

实现思路

1.创建一个包含全部标签的Map,map的key是标签名称,value是标签对象

2.从问题实体类中获得tag_names属性,利用字符串的split方法,拆分成字符串数组

3.遍历字符串数组,从Map中通过key(标签名称)获得value(标签对象)

4.将获取的value存入Question实体类中的List<Tag>tags属性

步骤1:

我们在Question实体类中需要定义一个List<Tag> tags

原因是我们需要能够从一个问题中获得多个标签

    //为问题实体类添加标签集合
    //@TableField(exist = false)表示数据库中没有这样的列,防止报错
    @TableField(exist = false)
    private List<Tag> tags;

步骤2:

业务逻辑层添加方法得到包含所有Tag标签的Map

ITagService

public interface ITagService extends IService<Tag> {//获得所有标签的方法
    List<Tag> getTags();//获得所有标签返回Map的方法
    Map<String,Tag> getName2TagMap();}

步骤3:

实现这个方法

package cn.tedu.straw.portal.service.impl;import cn.tedu.straw.portal.model.Tag;
import cn.tedu.straw.portal.mapper.TagMapper;
import cn.tedu.straw.portal.service.ITagService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author tedu.cn
 * @since 2020-12-09
 */
@Service
public class TagServiceImpl extends ServiceImpl<TagMapper, Tag> implements ITagService {//CopyOnWriteArrayList<>是线程安全的集合,适合在高并发的环境下使用
    private final List<Tag> tags=new CopyOnWriteArrayList<>();
    //ConcurrentHashMap是线程安全的Map,适合在高并发的环境下使用
    private final Map<String,Tag> map=new ConcurrentHashMap<>();@Override
    public List<Tag> getTags() {
        //这个if主要是为了保证tags被顺利赋值之后的高效运行
        if(tags.isEmpty()) {
            synchronized (tags) {
                //这个if主要是为了保证不会有两条以上线程为tags重复添加内容
                if (tags.isEmpty()) {
                    //super.list()是父类提供的查询当前指定实体类全部行的代码
                    tags.addAll(super.list());
                    //为所有标签赋值List类型之后,可以同步给map赋值
                    for(Tag t: tags){
                        //将tags中所有标签赋值给map
                        //而map的key是tag的name,value就是tag
                        map.put(t.getName(),t);
                    }
                }
            }
        }
        return tags;
    }
    @Override
    public Map<String, Tag> getName2TagMap() {
        //判断如果map是空,证明上面getTags方法没有运行
        if(map.isEmpty()){
            //那么就调用上面的getTags方法
            getTags();
        }
        return map;
    }
}

步骤4:

在QuestionServiceImpl类中编写代码

将数据库tag_names列中的内容转换成List<Tag>

//根据Question的tag_names列的值,返回List<Tag>
    private  List<Tag> tagNamesToTags(String tagNames){
        //得到的tag_name拆分字符串
        //tagNames="java基础,javaSE,面试题"
        String[] names=tagNames.split(",");
        //names={"java基础","javaSE","面试题"}
        //声明List以便返回
        List<Tag> list=new ArrayList<>();
        Map<String,Tag> map=tagService.getName2TagMap();
        //遍历String数组
        for(String name:names) {
            //根据String数组中当前的元素获得Map对应的value
            Tag tag=map.get(name);
            //将这个value保存在list对象中
            list.add(tag);
        }
        return list;
    }

步骤5:

在我们编写的QuestionServiceImpl类中的getMyQuestions方法中

根据步骤4中编写的方法来获得Question对象中的List<Tag>并赋值

编写完毕后QuestionServiceImpl完整代码如下!

@Service
@Slf4j
public class QuestionServiceImpl extends ServiceImpl<QuestionMapper, Question> implements IQuestionService {
    @Autowired
    IUserService userService;
    @Autowired
    UserMapper userMapper;
    @Autowired
    QuestionMapper questionMapper;
    //按登录用户查询当前用户问题的方法
    @Override
    public List<Question> getMyQuestions() {
        //获得当前登录用户的用户名
        String username=userService.currentUsername();
        log.debug("当前登录用户为:{}",username);
        //如果已经登录,使用之前编写好的findUserByUsername方法
        //查询出当前用户的详细信息(实际上主要需要用户的id)
        User user=userMapper.findUserByUsername(username);
        if(user == null){
            throw ServiceException.gone("登录用户不存在");
        }
        log.debug("开始查询{}用户的问题",user.getId());
        QueryWrapper<Question> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("user_id",user.getId());
        queryWrapper.eq("delete_status",0);
        queryWrapper.orderByDesc("createtime");
        List<Question> list=questionMapper.selectList(queryWrapper);
        log.debug("当前用户的问题数量为:{}",list.size());
        //遍历当前查询出的所有问题对象
        for(Question q: list){
            //将问题每个对象的对应的Tag都查询出来,并赋值为实体类中的List<Tag>
            List<Tag> tags=tagNamesToTags(q.getTagNames());
            q.setTags(tags);
        }
        return list;
    }@Autowired
    ITagService tagService;//根据Question的tag_names列的值,返回List<Tag>
    private  List<Tag> tagNamesToTags(String tagNames){
        //得到的tag_name拆分字符串
        //tagNames="java基础,javaSE,面试题"
        String[] names=tagNames.split(",");
        //names={"java基础","javaSE","面试题"}
        //声明List以便返回
        List<Tag> list=new ArrayList<>();
        Map<String,Tag> map=tagService.getName2TagMap();
        //遍历String数组
        for(String name:names) {
            //根据String数组中当前的元素获得Map对应的value
            Tag tag=map.get(name);
            //将这个value保存在list对象中
            list.add(tag);
        }
        return list;
    }
}

步骤6:

最后修改一下html页面内容,来获取问题的标签

<a class="text-info badge badge-pill bg-light"
            href="tag/tag_question.html" v-for="tag in question.tags">
     <small v-text="tag.name" >Java基础 &nbsp;</small>
</a>

3.显示问题的图片

现在项目中每个问题右侧跟一个图片

这个图片实际上是根据问题的第一个标签的id来决定的

需要在index.js文件中编写显示相关图片的代码

并在合适位置调用

代码如下

/*
显示当前用户的问题
 */
let questionsApp = new Vue({
    el:'#questionsApp',
    data: {
        questions:[]
    },
    methods: {
        loadQuestions:function () {
            $.ajax({
                url: '/v1/questions/my',
                method: "GET",
                success: function (r) {
                    console.log("成功加载数据");
                    console.log(r);
                    if(r.code === OK){
​
                        questionsApp.questions = r.data;
                        //调用计算持续时间的方法
                        questionsApp.updateDuration();
                        //调用显示所有按标签呈现的图片
                        questionsApp.updateTagImage();
                    }
                }
            });
        },
        updateTagImage:function(){
            let questions = this.questions;
            for(let i=0; i<questions.length; i++){
                //获得当前问题对象的所有标签的集合(数组)
               let tags = questions[i].tags;
               //js代码中特有的写法if(tags)
               //相当于判断tags非空
               if(tags){
                   //获取当前问题的第一个标签对应的图片文件路径
                   let tagImage = 'img/tags/'+tags[0].id+'.jpg';
                   console.log(tagImage);
                   //将这个文件路径保存到tagImage属性用,以便页面调用
                   questions[i].tagImage = tagImage;
               }
            }
        },
        updateDuration:function () {
            let questions=this.questions;
            for(let i=0;i<questions.length;i++){
                //获得问题中的创建时间属性(毫秒数)
                let createtime=new Date(questions[i].createtime).getTime();
                //获得当前时间的毫秒数
                let now=new Date().getTime();
                //计算时间差(秒)
                let durtaion=(now-createtime)/1000;
                if(durtaion<60){
                    // 显示刚刚
                    //duration这个名字可以随便起,只要保证和页面上取的一样就行
                    questions[i].duration="刚刚";
                }else if(durtaion<60*60){
                    // 显示XX分钟
                    questions[i].duration=
                        (durtaion/60).toFixed(0)+"分钟前";
                }else if (durtaion<60*60*24){
                    //显示XX小时
                    questions[i].duration=
                        (durtaion/60/60).toFixed(0)+"小时前";
                }else{
                    //显示XX天
                    questions[i].duration=
                        (durtaion/60/60/24).toFixed(0)+"天前";
                }}}
    },
    created:function () {
        console.log("执行了方法");
        this.loadQuestions(1);
    }
});

在index.html文件中绑定

<img src="img/tags/example0.jpg"
                 v-bind:src="question.tagImage"
                 class="ml-3 border img-fluid rounded"
                 alt="" width="208" height="116">

测试即可

4. 实现分页功能

4.1 为什么需要分页(翻页)

1.不会一次显示太多内容,不会产生大量流量,对服务器压力小
2.我们需要的信息,往往在前面几条的内容,后面的内容使用率不高
3.用户体验强,方便记忆位置

4.2 实现分页的sql语句

主要通过limit关键字实现分页查询
只查询userid为11的学生提问的前8条内容

select id,title from question 
where user_id=11 order by createtime desc limit 0,8

LIMIT pageSize OFFSET  pageNumber-1 *(page size)

使用上面的sql语句可以实现分页功能
但是所有信息都需要自己计算,而且计算的方式是固定的,

所以Mybatis提供了一套自动完成计算的翻页组件
PageHelper

4.3 PageHelper的使用

步骤1:

由于PageHelper是Mybatis提供的,没有SpringBoot的默认版本支持

所以像Mybatis一眼我们要自己管理版本

在Straw父项目的pom.xml文件中添加如下代码

 <properties>
        <java.version>1.8</java.version>
        <mybatis.plus.version>3.3.1</mybatis.plus.version>
        <pagehelper.starter.version>1.3.0</pagehelper.starter.version>
 </properties>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>${pagehelper.starter.version}</version>
        </dependency>
        <!-- 其它略  -->
    </dependencies>
</dependencyManagement>

步骤2:

子项目pom.xml文件添加代码

<dependency>
       <groupId>com.github.pagehelper</groupId>
       <artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>

注意父子项目的pom.xml都需要刷新!

步骤3:

原理上

PageHelper.startPage([页码],[每页条数])

PageHelper.startPage(1, 8);

代码中一旦出现了上面的设置

之后的第一个查询,就会按照我们设置的方式进行分页查询

但是查询结果的类型需要变化,变为PageInfo

PageInfo这个类包含了各种分页的信息,和通常情况下我们查询的List

实现分页代码如下

因为返回值类型变了,所以要从业务逻辑层开始重构(修改)

IQuestionService接口重构

public interface IQuestionService extends IService<Question> {//按登录用户查询当前用户问题的方法
    PageInfo<Question> getMyQuestions(
            Integer pageNum,Integer pageSize
    );
}

步骤4:

QuestionServiceImpl重构接口中的方法

@Override
    public PageInfo<Question> getMyQuestions(
            //传入翻页查询的参数
            Integer pageNum,Integer pageSize
    ) {
        //分页查询,决定查询的页数
        if(pageNum==null || pageSize==null){
            //分页查询信息不全,直接抛异常
            throw ServiceException.invalidRequest("参数不能为空");
        }//获得当前登录用户的用户名
        String username=userService.currentUsername();
        log.debug("当前登录用户为:{}",username);
        //如果已经登录,使用之前编写好的findUserByUsername方法
        //查询出当前用户的详细信息(实际上主要需要用户的id)
        User user=userMapper.findUserByUsername(username);
        if(user == null){
            throw ServiceException.gone("登录用户不存在");
        }
        log.debug("开始查询{}用户的问题",user.getId());
        QueryWrapper<Question> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("user_id",user.getId());
        queryWrapper.eq("delete_status",0);
        queryWrapper.orderByDesc("createtime");
        //执行查询之前,要设置分页查询信息
        PageHelper.startPage(pageNum,pageSize);
        //紧接着的查询就是按照上面分页配置的分页查询
        List<Question> list=questionMapper.selectList(queryWrapper);
        log.debug("当前用户的问题数量为:{}",list.size());
        //遍历当前查询出的所有问题对象
        for(Question q: list){
            //将问题每个对象的对应的Tag都查询出来,并赋值为实体类中的List<Tag>
            List<Tag> tags=tagNamesToTags(q.getTagNames());
            q.setTags(tags);
        }
        return new PageInfo<Question>(list);
    }

步骤5:

尝试一下测试

这个测试时包含指定SpringSecurity用户的

新建一个QuestionTest进行测试

@SpringBootTest
public class QuestionTest {
    @Autowired
    IQuestionService questionService;@Test
    //@WithMockUser是Spring-Security提供的注解
    //在测试中如果需要从Spring-Security中获得用户信息,那么就可以用这个注解标记
    //指定用户信息,也要注意,这只是个测试,Spring-Security不会对信息验证
    @WithMockUser(username = "st2",password = "123456")
    public void getQuest(){
        PageInfo<Question> pi=
                questionService.getMyQuestions(1,8);
        for(Question q:pi.getList()){
            System.out.println(q);
        }
    }
}

控制器的调用和VUE代码的重构

首先重构QuestionController

代码如下

@RestController
@RequestMapping("/v1/questions")
@Slf4j
public class QuestionController {
    @Autowired
    IQuestionService questionService;//查询返回当前登录用户发布的问题
    @GetMapping("/my")
    public R<PageInfo<Question>> my(Integer pageNum){
        if(pageNum==null){
            pageNum=1;
        }
        int pageSize=8;
        log.debug("开始查询当前用户的问题");
        //这里要处理个异常,因为用户可能没有登录
        try{
            PageInfo<Question> questions=
               questionService.getMyQuestions(pageNum,pageSize);
            return R.ok(questions);
        }catch (ServiceException e){
            log.error("用户查询问题失败!",e);
            return R.failed(e);
        }
    }
}

然后编写index.js页面代码的重构

let questionsApp = new Vue({
    el:'#questionsApp',
    data: {
        questions:[],
        pageInfo:{}
    },
    methods: {
        loadQuestions:function (pageNum) {
            if(!pageNum){ //如果pageNum为空,默认页码为1
                pageNum=1;
            }
            $.ajax({
                url: '/v1/questions/my',
                method: "GET",
                data:{pageNum:pageNum},
                success: function (r) {
                    console.log("成功加载数据");
                    console.log(r);
                    if(r.code === OK){
                        questionsApp.questions = r.data.list;
                        //调用计算持续时间的方法
                        questionsApp.updateDuration();
                        //调用显示所有按标签呈现的图片
                        questionsApp.updateTagImage();
                        questionsApp.pageInfo=r.data;
                    }
                }
            });
        },
       //之后代码未修改,略 
}        

分页导航条的配置

实现了查询第一页的内容
但是现在还不能翻页
需要配置页面给定的分页导航条

代码如下

<div class="pagination">
<a class="page-item page-link" href="#"
    v-on:click.prevent="loadQuestions(pageInfo.prePage)"
    >上一页</a>
<a class="page-item page-link " href="#"
    v-for="n in pageInfo.navigatepageNums"
    v-on:click.prevent="loadQuestions(n)"
    v-bind:class="
    {'bg-secondary text-light':n == pageInfo.pageNum}"
    ><span v-text="n">1</span></a>
<a class="page-item page-link" href="#"
    v-on:click.prevent="loadQuestions(pageInfo.nextPage)"
    >下一页</a>
</div>

参考资料

PageInfo类中的常用属性

//当前页
private int pageNum;
//每页的数量
private int pageSize;
//当前页的行数量
private int size;
//当前页面第一个元素在数据库中的行号
private int startRow;
//当前页面最后一个元素在数据库中的行号
private int endRow;
//总页数
private int pages;
//前一页页号
private int prePage;
//下一页页号
private int nextPage;
//是否为第一页
private boolean isFirstPage;
//是否为最后一页
private boolean isLastPage;
//是否有前一页
private boolean hasPreviousPage;
//是否有下一页
private boolean hasNextPage;
//导航条中页码个数
private int navigatePages;
//所有导航条中显示的页号
private int[] navigatepageNums;
//导航条上的第一页页号
private int navigateFirstPage;
//导航条上的最后一页号
private int navigateLastPage;

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

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

相关文章

LISA:通过大语言模型进行推理分割

论文&#xff1a;https://arxiv.org/pdf/2308.00692 代码&#xff1a;GitHub - dvlab-research/LISA 摘要 尽管感知系统近年来取得了显著的进步&#xff0c;但在执行视觉识别任务之前&#xff0c;它们仍然依赖于明确的人类指令来识别目标物体或类别。这样的系统缺乏主动推理…

csdn崩溃了?每次都卡

反馈给了官方客服也没有响应&#xff0c;最近几周都是这样的高频率的转圈圈&#xff01;这个入口不受重视&#xff1f;这个对于csdn用户来说&#xff0c;是最最基本的入口 如果CSDN&#xff08;CSDN.net&#xff09;崩溃了&#xff0c;可能会对以下方面产生影响&#xff1a; 开…

【perl】报错合集

perl报错合集 &#xff08;注&#xff1a;可能会不定时更新&#xff09; 1.Name “main::x” used only once: possible typo at … 1.Name "main::x" used only once: possible typo at ...给某个变量赋值但是从来没有用它&#xff0c;或者变量之只用一次但没有…

前沿分享-100 μAh 微型电池

这是SMD 组件形状的固态锂离子微型电池&#xff0c;容量高达 100Ah&#xff0c;在22年的慕尼黑电子展上出现过。 因为是可重复使用的&#xff0c;未来该产品甚至有机会取代容量更高&#xff08;例如100 Ah 时&#xff09;的不可充电硬币电池。 一般应用于超低功率的传感器&…

8.7 作业

1.思维导图 2.写一个函数&#xff0c;获取用户的uid和gid并使用变量接收 #!/bin/bash fun() {uid$(id -u)gid$(id -g) }fun echo $uid $gid 3.整理冒泡排序、选择排序和快速排序的代码 冒泡 #include <myhead.h> void fun(int l,int *arr) {for(int i0;i<l-1;i){f…

【面试题】 本地运行的前端代码,如何让他人访问?

前端面试题库 &#xff08;面试必备&#xff09; 推荐&#xff1a;★★★★★ 地址&#xff1a;前端面试题库 有时候&#xff0c;我前端写好了项目&#xff0c;想要给其他人看一下效果&#xff0c;可以选择将代码部署到test环境&#xff0c;也可以选择让外部通过i…

Linux/centos上如何配置管理samba服务器?

Linux/centos上如何配置管理samba服务器&#xff1f; 1 samba服务相关知识1.1 SMB协议1.2 samba工作原理1.2.1 相关进程1.2.2 samba工作流程1.2.3 samba功能 2 samba服务器安装2.1 利用光驱安装2.2 利用光盘映射文件 3 启动与停止samba服务4 配置samba服务器4.1 samba主配置文件…

睡眠助手/白噪音/助眠夜曲微信小程序源码下载 附教程

睡眠助手/白噪音/助眠夜曲微信小程序源码 附教程 支持分享海报 支持暗黑模式 包含了音频数据 最近很火的助眠小程序&#xff0c;前端vue&#xff0c;可以打包H5&#xff0c;APP&#xff0c;小程序 后台可以设置流量主广告&#xff0c;非常不错的源码 代码完整 完美运营 搭配无…

用神经网络玩转数据聚类:自编码器的原理与实践

一、什么是自编码器 自编码器是一种神经网络模型&#xff0c;它可以学习输入数据的低维表示&#xff0c;也称为隐层特征或编码。自编码器由两部分组成&#xff1a;编码器和解码器。编码器将输入数据映射到隐层特征&#xff0c;解码器将隐层特征重构为输入数据&#xff0c;使其…

自动方向识别式 LSF型电平转换芯片

大家好&#xff0c;这里是大话硬件。 今天这篇文章想分享一下电平转换芯片相关的内容。 其实在之前的文章分享过一篇关于电平转换芯片的相关内容&#xff0c;具体可以看链接《高速电路逻辑电平转换设计》。当时这篇文章也是分析的电平转换芯片&#xff0c;不过那时候更多的是…

如何做好Code Review

本文主要从我们为什么需要CR&#xff1f;CR面临哪些挑战&#xff1f;CR的最佳实践几个方面分析&#xff0c;希望可以给读者一些参考。 为什么需要CR&#xff1f; 代码质量 定性来看&#xff0c;大家都认可Code Review&#xff08;后文简称CR&#xff09;能显著改善代码质量&…

自监督去噪:Blind2Unblind原理分析与总结

文章目录 1. 方法原理1.1 动机与贡献1.2 方法细节(1) Noise2Void(2) re-visible without identity mapping(3) 综合说明 2. 效果3. 总结 1. 方法原理 1.1 动机与贡献 摘要要点&#xff1a;基于盲点去噪的网络受网络设计和/或输入数据的影响会丢失部分信息 --> 有价值的信息…

UNIX 系统概要

UNIX 家族UNIX 家谱家族后起之秀 LinuxUNIX vs LinuxUNIX/Linux 应用领域 UNIX 操作系统诞生与发展UNIX 操作系统概要内核常驻模块shell虚拟计算机特性 其他操作系统 LinuxRichard StallmanGNU 项目FSF 组织GPL 协议Linus Torvalds UNIX 家族 有人说&#xff0c;这个世界上只有…

优维低代码实践:对接数据

优维低代码技术专栏&#xff0c;是一个全新的、技术为主的专栏&#xff0c;由优维技术委员会成员执笔&#xff0c;基于优维7年低代码技术研发及运维成果&#xff0c;主要介绍低代码相关的技术原理及架构逻辑&#xff0c;目的是给广大运维人提供一个技术交流与学习的平台。 优维…

CS 144 Lab Five -- the network interface

CS 144 Lab Five -- the network interface TCP报文的数据传输方式地址解析协议 ARPARP攻击科普 Network Interface 具体实现测试tcp_ip_ethernet.ccTCPOverIPv4OverEthernetAdapterTCPOverIPv4OverEthernetSpongeSocket通信过程 对应课程视频: 【计算机网络】 斯坦福大学CS144…

Gradle Run with --stacktrace option to get the stack trace

IDEA中使用Gradle的时候遇到以下异常&#xff1a; * Try:Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. 解决办法&#xff1a; IDEA中File-Settings-Build&#…

比特鹏哥2-数据类型和变量【自用笔记】

比特鹏哥2-数据类型和变量【自用笔记】 1.数据类型介绍字符&#xff0c;整型&#xff0c;浮点型&#xff0c;布尔类型 2.signed 和unsigned3.数据类型的取值范围sizeof 展示字节大小--- 计算机中单位&#xff1a;字节 4.变量 常量4.1 变量创建变量&#xff08;数据类型 变量名&…

awk基础知识和案例

文章目录 awk1 awk用法入门1.1 BEGIN和END语句块1.2 awk语法1.2.1 常用命令选项1.2.2 awk变量内置变量自定义变量 1.3 printf命令1.3.1 格式1.3.2 演示 1.4 操作符 2 awk高阶用法2.1 awk控制语句(if-else判断)2.2 awk控制语句(while循环)2.3 awk控制语句(do-while循环)2.4 awk控…

PingCAP 入选 Gartner 《Hype Cycle for Data Management 2023》代表厂商

日前&#xff0c;全球科技咨询与研究机构 Gartner 发布了《Hype Cycle for Data Management 2023》&#xff08;2023 年数据管理技术成熟度曲线报告&#xff09;&#xff0c;PingCAP 凭借技术积累和产品优势&#xff0c;入选报告“用于数据管理的生成式人工智能”&#xff08;G…

Win10下webots2020b闪退

下载安装完之后打开软件就会停留在这个界面几秒钟&#xff0c;什么都点不了&#xff0c;然后就会闪退回桌面 原因: webots安装路径中有中文 解决方案&#xff1a; 安装路径下的中文改为英文