SpringBoot实现WebSocket发送接收消息 + Vue实现SocketJs接收发送消息

SpringBoot实现WebSocket发送接收消息 + Vue实现SocketJs接收发送消息

参考:

1、http://www.mchweb.net/index.php/dev/887.html

2、http://itonline.blog.csdn.net/article/details/81221103?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~default-1-81221103-blog-121078449.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~default-1-81221103-blog-121078449.pc_relevant_aa&utm_relevant_index=1

3、http://blog.csdn.net/yingxiake/article/details/51224569

使用场景

广播模式 :使用场景:给所有连接了这个通道的客户端发送消息。

  • convertAndSend()
  • @SendTo

点对点模式 :使用场景:单独给当前用户发送消息。

  • 下面两种方式,都默认加了一个前缀:/user

  • convertAndSendToUser()

  • @SendToUser

一、后端SpringBoot + WebSocket基础配置

1、导包

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>

2、配置config

  • 细节:必须配置跨域。低版本的SpringBoot(2.1.5.RELEASE 就不行)不行,需要使用高版本。低版本的解决方案还未找到。
  • 跨域配置使用:.setAllowedOriginPatterns("*")。。不能使用:.setAllowedOrigins("*")
package com.cc.ws.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;

/**
 * <p>@EnableWebSocketMessageBroker 的作用</p>
 * <li>注解开启使用STOMP协议来传输基于代理(message broker)的消息,</li>
 * <li>这时控制器支持使用 @MessageMapping,就像使用 @RequestMapping一样</li>
 * @author cc
 *
 */
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    /** <p>启动简单Broker</p>
     * <p>表示客户端订阅地址的前缀信息,也就是客户端接收服务端消息的地址的前缀信息</p>
     * <p>代理的名字:都是自定义的</p>
     *
     * /user     点对点(默认也是/user,可以自定义,但是必须和setUserDestinationPrefix中的设置一致)
     * /topic1   广播模式1
     * /topic2   广播模式2
     *
     * /mass     广播模式:群发
     */
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker(
                "/user", "/topic1", "/topic2", "/mass"
        );
        // 点对点使用的订阅前缀(客户端订阅路径上会体现出来),不设置的话,默认也是 /user/
        // 注意,这里必须和上面设置的Broker:/user 一致(两个都可以自定义,但必须一致)。否则连接不上
        registry.setUserDestinationPrefix("/user/");
        // 指服务端接收地址的前缀,意思就是说客户端给服务端发消息的地址的前缀
//        registry.setApplicationDestinationPrefixes("/socket");
    }

    /**
     * 这个方法的作用是添加一个服务端点,来接收客户端的连接。
     * registry.addEndpoint("/socket")表示添加了一个/socket端点,客户端(前端)就可以通过这个端点来进行连接。
     * withSockJS()的作用是开启SockJS支持。
     * @param registry registry
     */
    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        // 注册一个STOMP的endpoint端点,并指定使用SockJS协议
        // 前端使用这个地址连接后端 WebSocket接口
        registry.addEndpoint("/broadcast", "/point")
                // 允许所有源跨域。还可以指定ip配置:http://ip:*
                // 低版本的SpringBoot(2.1.5.RELEASE 就不行)不行
                .setAllowedOriginPatterns("*")
                .withSockJS();
    }

}

3、启动类,配置定时器

  • @EnableScheduling
@SpringBootApplication
@EnableScheduling
public class WebSocketDemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(WebSocketDemoApplication.class, args);
    }
}

二、前端基础配置

    let socket1 = new SockJS('http://服务器ip:服务器端口/broadcast');
   
    let stompClient1 = Stomp.over(socket1);//广播模式

    stompClient1.connect({}, (frame) => {
      stompClient1.subscribe('/topic1/', (message) => {
        console.log(message.body);
      });
    });

三、后端不接收,只发送

  • 使用spring Scheduled 定时发送消息

  • 直接使用:SimpMessagingTemplate 的 convertAndSend广播模式 和 convertAndSendToUser点对点模式

1、后端

  • 注意点对点发送:

convertAndSendToUser的默认前缀(/user)是在WebSocketConfig配置文件中配置的。

代码:

    @Resource
    private SimpMessagingTemplate simpMsgTemp;

    /** 广播推送消息1:会发送给所有连接了 topic1 这个通道的客户端。
     * topic1:在Broker中配置
     **/
    @Scheduled(cron = "0/1 * * * * ?")
    public void getSocket(){
        String msg = String.format("%s 的第 %s 个消息", "topic1", LocalDateTime.now().getSecond());
        log.info("{}",msg);
        simpMsgTemp.convertAndSend("/topic1/", msg);
    }

    /** 广播推送消息2:多指定一个uri。相当于另一条通道(推荐使用)
     * <li>自定义url后缀,还可以实现用户和用户单点发送。</li>
     * topic2:在Broker中配置
     * custom:是自定义的
     */
    @Scheduled(cron = "0/1 * * * * ?")
    public void getSocketUser(){
        String msg = String.format("topic2 的第 %s 个消息", LocalDateTime.now().getSecond());
        log.info("{}",msg);
        simpMsgTemp.convertAndSend("/topic2/custom" ,msg);
    }

    /**点对点发送 convertAndSendToUser(第一个参数:一般是用户id)
     *  -> 假如用户id是1。用用户id是1的在两个地方登陆了客户端(比如不同的浏览器登陆同一个用户),
     *  -> convertAndSendToUser会把消息发送到用户1登陆的两个客户端中
     * 发送到:/user/{userId}/cs 下。cs是自定义的,且必须自定义一个。
     */
    @Scheduled(cron = "0/1 * * * * ?")
    public void pointToPoint(){
        //这个用户id是后端获取的当前登陆的用户id
        String userId = "123";
        String msg = String.format("点对点:第 %s 个消息。用户id:%s", LocalDateTime.now().getSecond(), userId);
        log.info("{}",msg);
        //发送
        simpMsgTemp.convertAndSendToUser(userId,"/cs/" ,msg);
    }

2、前端

  • 注意点对点的接收方式,用户id需要取出前端存的用户id
    //这样才能同时接收后端来的三套不同通道的消息。
    // broadcast 和后端:registerStompEndpoints中的配置必须一致
    // point     和后端:registerStompEndpoints中的配置必须一致
    // broadcast、point 也可以只用一个,这里只是为了好区分。
    let socket1 = new SockJS('http://172.16.8.1:8099/broadcast');
    let socket2 = new SockJS('http://172.16.8.1:8099/broadcast');
    let socket3 = new SockJS('http://172.16.8.1:8099/point');
    // console.log("wb:" + socket)

    let stompClient1 = Stomp.over(socket1);
    let stompClient2 = Stomp.over(socket2);
    let stompClient3 = Stomp.over(socket3);

    // ----------------广播模式1--------------------
    stompClient1.connect({}, (frame) => {
      console.log('-----------frame1', frame)
      stompClient1.subscribe('/topic1/', (message) => {
        console.log(message.body);
        this.msg = message.body;
        // console.log(JSON.parse(message.body));
      });
    });

    // ----------------广播模式2--------------------
    stompClient2.connect({}, (frame) => {
      console.log('-----------frame2', frame)
      stompClient2.subscribe('/topic2/custom', (message) => {
        console.log(message.body);
        this.user = message.body;
        // console.log(JSON.parse(message.body));
      });
    });

    // ----------------点对点模式--------------------
    //前端获取的 userId
    let userId = '123';
    //连接WebSocket服务端
    stompClient3.connect({},(frame) => {
      console.log('Connected:' + frame);
      stompClient3.subscribe('/user/' + userId + '/cs/',
          (response) => {
            this.peer = response.body;
      });
    });

四、后端接收、接收后再发送

  • 也可以只接收消息,不发送。看业务需求。
  • 使用 @MessageMapping 接收前端发送过来的消息
  • 使用:@SendTo 广播模式、@SendToUser 点对点模式
  • 使用:SimpMessagingTemplate 的 convertAndSend广播模式 和 convertAndSendToUser 点对点模式

1、后端

    @Resource
    private SimpMessagingTemplate simpMsgTemp;

    /** <p>广播模式一、接收前端的消息,处理后给前端返回一个消息。</p>
     * <li>后端 把消息处理后 发送到 /mass/getResponse 路径下</li>
     * <ol>
     *     <li>@MessageMapping("/massRequest1") :作用:接收前端来的消息。类似于@RestController</li>
     *     <li>@SendTo("/mass/getResponse1"):作用跟convertAndSend类似,广播发给与该通道相连的客户端。SendTo 发送至 Broker 下的指定订阅路径 </li>
     *     <li>@SendToUser("/mass/getResponse1"):作用跟convertAndSendToUser类似,定点发送。SendTo 发送至 Broker 下的指定订阅路径 </li>
     *     <li>/mass 必须在配置文件配置</li>
     *     <li>/getResponse1 自定义的后缀</li>
     * </ol>
     */
    @MessageMapping("/massRequest1")
    @SendTo("/mass/getResponse1")
    public String mass1(String chatRoomRequest){
        //处理前端消息……
        log.info("前端消息:{}",chatRoomRequest);
        //返回消息
        return "@SendTo 广播一(单次) 后端处理完成!";
    }

    /** 广播模式二、接收前端的消息,可以多次给前端发消息
     * <li>/mass 必须在配置文件配置</li>
     * <li>/getResponse2 自定义的后缀</li>
     */
    @MessageMapping("/massRequest2")
    public void mass2(String chatRoomRequest){
        log.info("前端的消息:{}",chatRoomRequest);

        for (int i = 0; i < 5; i++) {
            String msg = "后端处理后的 广播二(多次):" + i;
            simpMsgTemp.convertAndSend("/mass/getResponse2", msg);
        }
        simpMsgTemp.convertAndSend("/mass/getResponse2",
                "后端处理后的 广播二(多次),后端处理完成!");
    }

    /** <p>点对点一、接收前端消息,只能返回一次消息(必须登陆系统才能使用。)</p>
     * <li>只有发送原始消息的客户端才会收到响应消息,而不是所有连接的客户端都会收到响应消息。</li>
     * <li>/alone/getResponse1:自定义的,不需要在配置文件配置。</li>
     *
     * <p>@SendToUser</p>
     * <li>默认该注解前缀为 /user</li>
     * <li>broadcast属性,表明是否广播。就是当有同一个用户登录多个session时,是否都能收到。取值true/false.</li>
     *
     * @param principal Principal :登陆用户的信息,需要使用spring s安全框架写入信息?
     */
    @MessageMapping("/aloneRequest1")
    @SendToUser("/alone/getResponse1")
    public String alone1(String chatRoomRequest){
        //处理前端消息……
        log.info("前端消息:{}",chatRoomRequest);
        //返回消息
        return "@SendToUser 点对点一(单次) 后端处理完成!";
    }

    /** 点对点二、接收前端消息,可以多次给前端发消息
     * <li>convertAndSendToUser —— 发送消息给指定用户id的</li>
     * <li>如果用户1在两个地方(A/B)登陆可以客户端,并且连接了该通道,其中一个如A给后端发消息,后端返回消息,A/B两个地方都会收到消息</li>
     * <ol>
     *     <li>@MessageMapping("/aloneRequest2") 接收前端指定用户消息,</li>
     *     <li>/alone/getResponse2 不用在配置文件中配置</li>
     *     <li>返回消息 发送到 user/{userId}/alone/getResponse2 下 (定点发送)</li>
     * </ol>
     */
    @MessageMapping("/aloneRequest2")
    public void alone2(String chatRoomRequest){
        //后端获取的当前登陆的用户的id(和前端一致)
        String userId = "456";
        log.info("前端的消息:{}",chatRoomRequest);

        for (int i = 0; i < 5; i++) {
            String msg = "后端处理后的 点对点二(多次):" + i;
            simpMsgTemp.convertAndSendToUser(userId,"/alone/getResponse2", msg);
        }
        simpMsgTemp.convertAndSendToUser(userId,"/alone/getResponse2",
                "后端处理后的 点对点二(多次),后端处理完成!");
    }

2、前端

  • 3点对点一 未实现。
    //连接SockJS的 broadcast
    let socket1 = new SockJS('http://172.16.8.7:8099/broadcast');
    let socket2 = new SockJS('http://172.16.8.7:8099/broadcast');
    let socket3 = new SockJS('http://172.16.8.7:8099/point');
    let socket4 = new SockJS('http://172.16.8.7:8099/point');
    //使用STMOP子协议的WebSocket客户端
    let stompClient1 = Stomp.over(socket1);
    let stompClient2 = Stomp.over(socket2);
    let stompClient3 = Stomp.over(socket3);
    let stompClient4 = Stomp.over(socket4);

    //1广播模式一
    stompClient1.connect({},(frame) => {
      console.log('广播模式一:' + frame);
      //1发送消息
      stompClient1.send("/massRequest1",{},"我是前端来 广播模式一 的消息!");

      //2接收消息
      stompClient1.subscribe('/mass/getResponse1',(response) => {
        this.broadcast1 = response.body
      });
    });

    //2广播模式二
    stompClient2.connect({},(frame) => {
      console.log('广播模式二:' + frame);
      //1发送消息
      stompClient2.send("/massRequest2",{},"我是前端来 广播模式二 的消息");

      //2接收消息
      stompClient2.subscribe('/mass/getResponse2',(response) => {
        this.broadcast2 = response.body
      });
    });

    //3点对点一 :必须登陆系统才能实现。要往:Principal设置用户登陆信息才行
    //1发送消息
    // stompClient3.send("/aloneRequest1",{},"我是前端来 点对点一 的消息");
    stompClient3.connect({},(frame) => {
      console.log('点对点一1:' + frame);
      stompClient3.send("/aloneRequest1",{},"我是前端来 点对点一 的消息");
      //2接收消息
      stompClient3.subscribe('/user/alone/getResponse1' ,(response) => {
        console.log('-------response.body', response.body)
        this.point1 = response.body
      });
    });

    //4点对点二:必须获取现在登陆了的用户id,且必须和后端一致才行。
    stompClient4.connect({},(frame) => {
      console.log('点对点二:' + frame);
      //1发送消息
      stompClient4.send("/aloneRequest2",{},"我是前端来 点对点二 的消息");

      //2接收消息
      //前端获取的当前登陆的用户userId(和后端一致)
      let userId = '456';
      stompClient4.subscribe('/user/'+userId+'/alone/getResponse2',(response) => {
        this.point2 = response.body
      });
    });
本文转载于网络 如有侵权请联系删除

相关文章

  • 平板摄像头+算力搞定3D空间实时重建和理解,清华和禾多科技新成果入选CVPR 2022 Oral

    明敏发自凹非寺 量子位|公众号QbitAI仅仅需要一个平板电脑,就能实现3D空间的实时重建和理解了!看,只要拿着平板电脑走一走,房间内的物体就能被实时重建、分割和识别出来,整个过程行云流水。要知道,3D重建和语义理解,是机器人、自动驾驶、AR/VR等领域的关键共性技术,长期以来面临算法复杂度高,难以实时处理的挑战。现在,只用一个小小的平板就搞定了。这就是清华大学联合禾多科技提出的增量式稀疏卷积网络(INcrementalSparseConvolution,INS-Conv)。在不损失性能的同时,极大地降低了算法的复杂度。目前,该论文已被CVPR2022(Oral)收录。那么具体是怎么做的呢?增量式稀疏卷积网络本论文的核心之处,是提出了一种增量式稀疏卷积神经网络(INcrementalSparseConvolution,INS-Conv)。算法复杂、推理速度慢、算力要求高是长期以来,3D语义理解算法在应用场景中面临的核心挑战。比如自动驾驶场景,就要求三维感知系统能够对快速变化的路况做出实时判断,而且要精确识别车辆、行人、路标等。尽管过去很多密集3D卷积网络在精度上取得了不错成绩,但是对芯

  • Taro中如何将store加载到项目中

    上面文章我们了解了如何创建store,最后导出时,在函数内部创建了store,所以导出时,函数需要调用,然后通过provicer组件将其注入到项目中。在入口App.js组件中:第一步:从react-thunk中导出rProvider第二步:导入store,第三步,通过provicer将store导入。代码如下:import{Component}from'react' import{Provider}from'react-redux' importconfigStorefrom'./store' import'./app.scss' conststore=configStore() classAppextendsComponent{ componentDidMount(){} componentDidShow(){} componentDidHide(){} componentDidCatchError(){} //在App类中的render()函数没有实际作用 //请勿修改此函数 rende

  • 次模块示例聚类的GPU加速优化器感知评估

    亚模块功能的优化构成了执行聚类的可行方法。强大的逼近保证和可行的优化流数据使这种群集方法变得有利。从技术上讲,子模块函数将数据子集映射为实数值,这表明特定子集的“代表性”。然后,可以使用最佳集来划分数据空间并推断群集。基于示例的聚类是可能的子模块函数之一,但是具有很高的计算复杂度。但是,对于实际应用,特定的实时或挂钟运行时间是决定性的。在这项工作中,我们提出了一种新颖的方法来评估GPU上的这一特定功能,从而牢记优化器的必要性并减少了挂钟运行时间。为了讨论我们的GPU算法,我们研究了不同的运行时关键问题属性的影响,例如数据维数和子集中数据点的数量,以及所需浮点精度的影响。在可重现的实验中,根据是否使用CPU上的多线程计算进行比较以及所需的浮点精度类型,我们的GPU算法能够实现高达72倍的竞争性加速。与单精度单线程CPU计算相比,半精度GPU计算导致高达452倍的大加速。原文:Theoptimizationofsubmodularfunctionsconstitutesaviablewaytoperformclustering.Strongapproximationguaranteesan

  • SAP PM入门系列28 - IW67 Display Tasks

    SAPPM入门系列28-IW67DisplayTasksSAPPM模块里IW67这个事务代码用于查询PMNotification单据下的任务列表。执行事务代码IW67,系统进入如下界面:输入查询参数,执行,得到如下报表结果:选中某个Notification,点击Tasks按钮,进入如下界面,点击’Notification’按钮,系统展开其抬头信息,如下图示:如下是一个典型的PMnotification的显示界面(IW23),另外,在事务代码IW67初始查询界面里的’OnlyUncompletedTasks’,用于查询未完成任务清单,-完-2021-1-25写于长三角某市。

  • springboot系列学习(二十六):spring Security框架整合thymeleaf,在前段也可以实现安全框架,一步一步带你整合使用,小白必看(三)

    之前的认证授权,退出功能已经在配置类里面实现了。现在还有一个问题问题就是前端页面的东西,不同的权限看见的东西是不一样的,这个咋实现。之前我们可以在前段用if判断来看当前的用户的权限进行,但是现在可以和thymeleaf整合,使用这个就可以实现。具体如何做整合步骤1导入依赖<dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity5</artifactId> <version>3.0.4.RELEASE</version> </dependency>复制 2前段导入springsecurity和thymeleaf的标签 手打这个之后,alt+enter这个之后就导入了,我们就可以看到页面出现了这个 其实这个就可以使用了,但是我希望在页面写标签的时候有提示,那么这个就要写全,所以这样写 这样在前段就可以对应的标签如果注销404了,就是因为它默认防止csrf跨站请求

  • 12岁小读者使用Python暴力破解Wi-Fi密码

    这一代后浪在父母的光环加持下,猛点技能点。有些从小学开始敲基因,有些一天能写2000首诗,有些发表的论文已经达到硕士毕业水平。但是在编程领域还有另外一群后浪,有些仅仅靠着自己的自学开始做游戏,建网站,在同龄人的互联网领域里叱诧风云 像之前还有小读者问行哥现在12岁已经学完Python基础,不知道对Python的其它方向该如何选择这不,就有小读者给行哥投稿,他写代码生成密码本,并利用pywifi工具包对自家Wi-Fi进行暴力破解,下文分享给大家看看1.投稿内容Hello我是狂飙今天来分享一些我对Python破解WiFi的一些看法,思路如下:1.首先我们需要生成密码本,因为大部分wifi密码为八位数字,所以我们就生成八位数字密码本。2.然后判断电脑是否连接wifi3.创建wifi连接文件,选择要连接wifi名称,检查加密单元4.接下来删除所有连接过的wifi判断wifi是否连接。5.最后需要一个八位以上的密码本,一行一行读取就可以了。完整的代码就发给大家了不要忘记生成密码本,然后说找不到password.txt的文件啊#coding:utf-8 importpywifi frompywif

  • 性能工具之Jmeter小白入门系列之一

    一、简单了解 ApacheJMeter™TheApacheJMeter™applicationisopensourcesoftware,a100%pureJavaapplicationdesignedtoloadtestfunctionalbehaviorandmeasureperformance.ItwasoriginallydesignedfortestingWebApplicationsbuthassinceexpandedtoothertestfunctions.官网网站为:https://jmeter.apache.org/安装l官网:http://jmeter.apache.org/download_jmeter.cgil下载完成后直接解压缩即可,无须安装(前置条件,本机需要有java运行虚拟机环境)。l点击bin目录下的jmeter.bat文件即可启动jmeter.帮助文档:https://jmeter.apache.org/usermanual/get-started.html插件安装 访问:https://jmeter-plugins.org/install/Inst

  • One order popup window 显示逻辑

    版权声明:署名,允许他人基于本文进行创作,且必须基于与原先许可协议相同的许可协议分发本文(CreativeCommons)CreatedbyJerryWang,lastmodifiedonApr10,2014点newbutton创建新的serviceorder时, 如果transactiontype不唯一,则将所有的transactiontype以popupwindow的形式显示出来供enduser选择:

  • BERT训练猛提速!谷歌新研究将BERT预训练时间从3天缩短到76分钟

    【新智元导读】BERT是目前最强大的NLP预训练模型,也是工业界目前最耗时的应用,计算量远高于ImageNet。谷歌的研究人员提出新的优化器,使用1024块TPU,将BERT的训练时间从3天成功缩短到76分钟,提速65.2倍!去年,谷歌发布了最强预训练模型BERT,宣告了NLP领域的一项重大突破。BERT在33亿文本的语料上训练语言模型,再分别在不同的下游任务上微调,在11个不同的NLP任务均得到了目前为止最好的结果。不过,在33亿文本的语料上预训练一个BERT模型的成本是非常大的,谷歌用了16个自己的TPU集群(一共64块TPU)来训练大号版本的BERT,一共花了约4天的时间。如此巨大的训练成本,让普通研究者难以尝试自己去训练一个BERT。有没有办法加快BERT的训练呢?近日,来自Google、UCBerkeley、UCLA的几位研究人员提出新的优化器——LAMB优化器,将训练的batchsize推到硬件的极限,使用TPUPod(1024块TPUv3芯片),将BERT的训练时间从3天缩短到了76分钟!论文地址:https://arxiv.org/pdf/1904.00962.pd

  • 技术盛会!WeTest携手CSDN,聚焦一线互联网公司的架构、数据库和运维案例

    在互联网大潮下,2017年的就业环境越发恶劣,技术人如何去适应技术变革和学习新技术,以及如何快速增强自身的技术实力成为亟需解决的问题。如果你在看完一本技术图书后还是疑惑不解,处于目前项目遇到困难时无人请教的尴尬境地,亦不清楚业界同行在使用什么技术以及用得如何……你或许需要别人醍醐灌顶的几句话,优秀的技术人才思考和解决问题的方式,甚而他们在面对成长瓶颈时的晋升之道。成长固然没有绝对的公式可循,但可以通过别人处事之道来启发自己,而技术人也理应时刻为自己充电,从而有效地为自己的发展保驾护航。由CSDN主办,腾讯WeTest支持的内容型技术峰会中国软件开发者大会(SDCC)将于2017年3月17日-19日进驻上海,包含三大主题技术峰会:互联网运维开发实战峰会、数据库核心技术与应用实战峰会、互联网应用架构实战峰会。大会介绍:作为SDCC(中国软件开发者大会)系列技术峰会的一部分,SDCC 2017·上海站继续秉承干货实料(案例)的内容原则,这三场峰会将邀请业内顶尖的架构师和技术专家,共同探讨运维工具研发与实践、运维自动化系统的构建、大数据与运维、云上的运维案例分析、虚拟化技术、应用性能检测与管理

  • 太吾绘卷多分支选择的一些代码实现方式

    最近有一款国产游戏『太吾绘卷』很火。这个游戏怎么归类比较麻烦,从整体上来说,这是款『文字冒险类』游戏,而它的文案数值以及系统水平很高。决定一款游戏成就的往往是游戏的长处,而太吾绘卷的优点,明显就是那过硬的文字功底以及完整的数值系统。当然,仅仅只有这两个因素顶多让那其成为一个『好玩』的游戏,而成为爆款的原因则是这个游戏以及制作团队有着太多为人乐道的梗(比如蛐蛐邪教啥的)其中有一个梗就是关于这款游戏代码的。因为制作者只学了一个月编程就上阵了,所以『俺寻思着这行代码能不能跑,结果就真的能跑,还没bug!』关于这个代码梗,出现了几种声音,一般情况下,大家都视制作者为神人,自学代码一个月就能写游戏了。也有人反而还会发出『人家学一个月就能做游戏了,程序员是不是要失业了?』这让我想起某个地方看到的一个争论:一个开发对产品说,产品也许可以去稍微学一点代码相关知识比较好。产品:『没有必要!』我看到很多美术自学代码,最后独立制作出游戏的。我看到很多音乐人自学代码,最后独立制作出游戏的。太吾这个是我见到第一个文案以及逻辑功底深厚的人自学代码,最后制作出游戏的。所以我讨厌前面那种『没有必要』的人。我一个游戏人

  • 干货 | YJango的卷积神经网络——介绍

    作者|YJango整理|AI科技大本营(rgznai100)原文-https://zhuanlan.zhihu.com/p/27642620PS:YJango是我的网名,意思是我写的教程,并不是一种网络结构。关于卷积神经网络的讲解,网上有很多精彩文章,且恐怕难以找到比斯坦福的CS231n(http://cs231n.github.io/convolutional-networks/)还要全面的教程。 所以这里对卷积神经网络的讲解主要是以不同的思考侧重展开,通过对卷积神经网络的分析,进一步理解神经网络变体中“因素共享”这一概念。注意:该文会跟其他的现有文章有很大的不同。读该文需要有本书前些章节作为预备知识,不然会有理解障碍。没看过前面内容的朋友建议看公开课视频:深层神经网络设计理念(https://zhuanlan.zhihu.com/p/26647094)。当中的知识可以更好的帮助理解该文。其他阅读地址:《超智能体》gitbook阅读地址:YJango的卷积神经网络——介绍,看前先刷新浏览器 https://yjango.gitbooks.io/superorganism/conte

  • POJ 3150 Cellular Automaton(矩阵快速幂)

    CellularAutomaton TimeLimit:12000MSMemoryLimit:65536K TotalSubmissions:3504Accepted:1421 CaseTimeLimit:2000MS DescriptionAcellularautomatonisacollectionofcellsonagridofspecifiedshapethatevolvesthroughanumberofdiscretetimestepsaccordingtoasetofrulesthatdescribethenewstateofacellbasedonthestatesofneighboringcells.Theorderofthecellularautomatonisthenumberofcellsitcontains.Cellsoftheautomatonofordernarenumberedfrom1ton.Theorderofthecellisthenumberofdifferentvaluesitmaycontain.Usually,valuesofacellof

  • Django入门之路

    Web框架开发-Django基础之web应用,Http协议 web框架开发-web框架简介,wsgiref模块,DIY一个web框架 web框架开发-Django简介 web框架开发-静态文件配置 web框架开发-路由控制 web框架开发-Django视图层 web框架开发-模板层 web框架开发-Django模型层(1)之ORM简介和单表操作 web框架开发-Django模型层(2)-多表操作 web框架开发-Ajax web框架开发-分页器(Paginator) web框架开发-Django的Forms组件 web框架开发-Django组件cookie与session web框架开发-Django用户认证组件 web框架开发-快速认识Django中间件 web开发实战-开发BLOG

  • 程序员成熟的标志

    程序员在经历了若干年编程工作之后,很想知道自己水平到底如何?自己是否已经成为成熟的程序员?虽然程序员会对自己有一个自我评价,但是,自己的评价和社会的评价、专业的评价会有差异,所以程序员自己并不能肯定这个评价。现实中,除了各种证书之外,很少有人会专门给出一个程序员的成熟度的评价。人们往往是偶发性地就事论事地对程序员的工作作出好与不好,行与不行的评论。因此,程序员对此感到很茫然,不知道要从那些方面去评价自己的能力。 一个程序员到底成熟不成熟,我想从以下几个方面谈谈自己的看法。 1、技术标志 如果程序员不会编程序那决不是程序员,程序员至少要掌握一门程序设计语言,要能够用这种语言去编写程序去解决他想解决的问题。但是,成熟的程序员往往掌握不止一种程序语言,三到四种语言的掌握是必须的,一种二种语言的精通也是必须的。除了从掌握程序设计语言个数之外,我们还可以从其他几个方面去看看程序员在技术上水平。例如,函数编写能力(命名、格式、大小、分类、参数、复用等),面向过程的能力,面向对象的能力,数据库技术能力,效率处理能力,安全处理能力,网络处理能力,软件构架能力,人机交互能力,通用软件能力,软件文档能力等

  • STM32F429 利用CUBEMX移植FATFS文件系统成功!!!

    文件系统对于一个专业的嵌入式系统而言必不可少,博主这两天利用STM32F429成功移植了FATFS,特来分享一下学习心得,避免新人采坑。 我是在SD卡上实现的,因此你需要利用SDIO接口扩展一个SD卡,具体实现如下:      进入Configuration界面,基本参数的不用配置,但是需要开启中断和DMA,配置如下:            点击OK,关闭Configuration窗口。 在MiddleWares下拉列表中打开FATFS,选中SD卡。    进入FATFS的Configuration界面,配置如下:    解释一下改动的两个参数,一个选择读取中文类型的文件,另一个是使能长字节名称命名(如果不选择,只有8字节,超过8字节会出现HardwareFault),文件系统的磁盘选择3个(方便挂载其他内存) 最后,再设置选择中,把stack的空间大小设置为0X1000大小。    以上,便完成可在CUBEMX中配置FATF

  • 实验九

    学号20182325《数据结构与面向对象程序设计》实验9报告 课程:《程序设计与数据结构》 班级:1823 姓名:袁源 学号:20182325 实验教师:王志强 实验日期:2019年12月8日 必修/选修:必修 1.实验内容 (1)初始化:根据屏幕提示(例如:输入1为无向图,输入2为有向图)初始化无向图和有向图(可用邻接矩阵,也可用邻接表),图需要自己定义(顶点个数、边个数,建议先在草稿纸上画出图,然后再输入顶点和边数)(2分) (2)图的遍历:完成有向图和无向图的遍历(深度和广度优先遍历)(4分) (3)完成有向图的拓扑排序,并输出拓扑排序序列或者输出该图存在环(3分) (4)完成无向图的最小生成树(Prim算法或Kruscal算法均可),并输出(3分) (5)完成有向图的单源最短路径求解(迪杰斯特拉算法)(3分) 2.实验过程及结果 (1)初始化:根据屏幕提示(例如:输入1为无向图,输入2为有向图)初始化无向图和有向图(可用邻接矩阵,也可用邻接表),图需要自己定义(顶点个数、边个数,建议先在草稿纸上画出图,然后再输入顶点和边数)(2分) (2)图的遍历:完成有向图

  • 物理知识相关内容总结

    在这个充满OI的博客里写物理显得有些格格不入。但最近学的一些内容非常有意思,在这里记录一下。 帕普斯定理 可以理解为一个平面图形,绕图形外一轴旋转得到的体积等于图形面积乘以其重心经过的圆周。即\(V=S\cdotl\) 用这个方法可以代替复杂的微元法求解平面物体的重心。例如半圆的重心在直径中垂线上离圆心\(\dfrac{4R}{3\pi}\)的距离上。而对于复杂的图形,求体积就得用定积分了。 微元法求张力 例如有一道题:一个圆环的最大张力为\(T\),已知质量\(M\)与半径\(r\),求在平面上旋转的最大角速度。 取圆上一段微元(弧),设其圆心角为\(\theta\)。显然张力提供向心力,那么求出两边张力的合力就好了。不要跟我一样傻到用余弦定理!有结论\(\lim\limits_{x\rightarrow0}\)时,\(\theta\)等于\(r\)乘以\(\theta\)所对的弧。因此合力也就趋向\(T\theta\)。通过\(F=m\omega^2r\)求解,我们发现\(F\)、\(m\)这两个都是和\(\theta\)线性相关的,于是\(\theta\)就消去了。 虚功 很有

  • 136. Single Number

    136.SingleNumber Givenanon-emptyarrayofintegers,everyelementappearstwiceexceptforone.Findthatsingleone. Note: Youralgorithmshouldhavealinearruntimecomplexity.Couldyouimplementitwithoutusingextramemory? Example1: Input:[2,2,1]Output:1 Example2: Input:[4,1,2,1,2]Output:4 题解 第一种:将数据存到一个list中,相同的就remove掉 classSolution{ publicintsingleNumber(int[]nums){ List<Integer>no_duplicate_list=newArrayList(); for(inti:nums){ if(no_duplicate_list.contains(i)){ no_duplicate_list.remove(newInteger(i)); con

  • 互联网运营中的10大数据分析方法

    https://www.sohu.com/a/212888005_468714 http://www.woshipm.com/data-analysis/758063.html 道家强调四个字,叫“道、法、术、器”。“器”是指物品或工具,在数据分析领域指的就是数据分析的产品或工具,“工欲善其事,必先利其器”;“术”是指操作技术,是技能的高低、效率的高下,如对分析工具使用的技术(比如用Excel进行数据分析的水平);“法”是指选择的方法,有句话说“选择比努力重要”;“道”是指方向,是指导思想,是战略。那么如何做好数据分析呢,今天推荐一篇关于互联网运营中的十大数据分析方法。 1 细分分析 细分分析是分析的基础,单一维度下的指标数据的信息价值很低。 细分方法可以分为两类,一类逐步分析,比如:来北京市的访客可分为朝阳,海淀等区;另一类是维度交叉,如:来自付费SEM的新访客。 细分用于解决所有问题。比如漏斗转化,实际上就是把转化过程按照步骤进行细分,流量渠道的分析和评估也需要大量用到细分的方法。 2 对比分析 对比分析主要是指将两个相互联系的指标数据进行比较,从数量上展示和说明研究对象的规模大

  • 利用python进行折线图,直方图和饼图的绘制

     我用10个国家某年的GDP来绘图,数据如下:labels  =['USA','China','India','Japan','Germany','Russia','Brazil','UK','France','Italy']quants  =[15094025.0,11299967.0,4457784.0,4440376.0,3099080.0,2383402.0,2293954.0,2260803.0,2217900.0,1846950.0]首先绘制折线图,代码如下:defdraw_line(labels,quants):   ind=np.linspace(0,9,10)   fig=plt.figure(1)   ax =fig.add_subplot(111)   ax.plot(ind,quants)   ax.set_title('Top10GDPCountries

相关推荐

推荐阅读