前言

这次大佬问的问题都是很多协议性的细节问题,基本上百分之八十都没去思考过.也没看过(后续会对每个协议做一些简单博客,对基础中间件开发应该是有帮助的)

1. http请求传值可以通过那些途径

urlpath、urlparam、header、body

2. http请求url传递大小、body传递大小限制

  1. http协议对url长度是没有限制的,服务器必须能够处理任何他们提供资源的URI,并且应该能够处理无限长度的URIS,如果服务器不能处理太长的URI的时候,服务器应该返回414状态码,表示URL过长(所以服务器端也是可以做长度限制的)
  2. URL长度限制是由不同浏览器自己限制的,不同浏览器对URL长度限制不一样.body也没有大小限制

3. http请求url后面参数a=x&a=y会选择那一条

  1. http协议中并没有规定同名参数的处理方法.具体处理方法是在服务端接收方,一般时取第一个为参数.
  2. 在Spring中当接收类型为String类型时会将值连接为以","分割开的字符串,如果是集合类型则会整理成元素放入集合中,否则取第一个为参数.

4. put请求参数放在哪里

put请求参数一般放在body中.当然如果是类似id这种可以放在params中或者url的一级地址上.RESTFUL风格中这个方式用来修改数据的,body在浏览器上没有传输大小限制

5. http客户端传递二进制流的contenttype是什么类型;body中是什么格式

  1. http请求头和响应头传输是ASCII文本类型,其中Content-type为传输消息体的类型.告知消息接收端如何解析消息体
  2. 定义传输body为文本信息解析格式(test/ html/json/xml/form表单)之类
  3. 还有一种是文件类型,表示该次传输是二进制流类型,如image/ .. ; video/ ..; application/ ..;之类的
  4. 所以body中的格式信息其实是由数据传输方和接收方自己定义的,可以选择将二进制进行编码后传输再由服务端解码(参考csdn头像上传),或者传输本身的二进制数据(浏览器F12会尝试使用utf-8解析,但是是乱码的,因为本身就不是UTF-8编码的二进制文件)

6. websocket关闭标签页会断开链接么,服务端如何判断是否断开连接了,服务端如何主动断开连接

websocket定义的是浏览器与服务端建立长连接的协议.具体连接创建是由浏览器来执行的,标签页只是浏览器中的一部分而已.所以标签页关闭是不影响连接的.但是标签页中有维护连接保持的心跳机制,所以当标签页关闭后不再进行心跳发送则会由服务端断开连接.

7. websocket心跳机制

  1. websocket由于要判断客户端与服务端是否还在线/离线来及时将连接断开释放资源保证不会因为连接导致的内存溢出问题.所以当连接创建后,会由客户端发送心跳,服务端响应心跳机制来让双方感知对方的存在.
  2. 这里规定客户端发送ping给服务端,服务端给客户端发送pong响应,确保双方的发送数据能力以及在线状态

8. rabbitmq和kafka实现单播和广播

  1. Rabbitmq的发布订阅/路由/通配符模式可以实现广播. 工作队列模式实现单播
  2. Kafka是基于发布订阅模型实现的消息队列,天生就是支持发布订阅的.所以同一队列多个partition多个不同组消费者就可实现广播, 单播的话就创建一个partition和一个消费者组就好了

9. mail发送邮件可否模仿他人邮箱发送

SMTP协议只定义邮件格式,身份验证是邮件服务商自己设置的.所以mail可以模仿他人邮箱发送,并且判断发送方真实性由各邮件服务商自己实现的

10. Git抛弃指定commit(回滚)

  1. 推荐git了解学习模拟网站oschina.gitee
  2. 本地工作区: 当前正在修改的内容.(在这步仅需 git checkout ./ -- filename;删除当前文件改动)
  3. 本地暂存区: 已add. git reset HEAD ./filename(这时会将改动再标记为在工作区)
  4. 本地仓库: 已commit. git reset --hard commitId

11. 算法题: 打印字符串全排列(力扣38)

// 回溯算法: 将不同的数字存放辅助数组中.并做好原数组取出数字标记.用完放回去;
// 最主要的就是向下递归的选择把握以及递归完毕对状态信息的回朔调整
public static String[] permutation(String s) {
    char[] origin = s.toCharArray();
    Set<String> result = new HashSet<>();
    fullArrangement(origin, "", result, new boolean[origin.length]);
    return result.toArray(new String[result.size()]);
}

// 每个位置按照不同的顺序将字符取出再放回,注意重复剪枝即可;
public static void fullArrangement(char[] origin, String s, Set<String> result, boolean[] visit){
    if(s.length() == origin.length){
        result.add(s);
        return;
    }
    // 记录当前数组存放内容以及访问过的元素
    for(int i = 0; i < origin.length; i++){
        if(visit[i]){
            continue;
        }
        visit[i] = true;
        fullArrangement(origin, s.concat(String.valueOf(origin[i])), result, visit);
        visit[i] = false;
    }
}