Jetty 9.1上的Java WebSockets(JSR-356)

最终发布了Jetty 9.1 ,将Java WebSockets(JSR-356)引入了非EE环境。 这真是个好消息,今天的帖子将介绍如何将这个出色的新API与Spring Framework一起使用。

JSR-356定义了基于注释的简洁模型,以允许现代Java Web应用程序使用WebSockets API轻松创建双向通信通道。 它不仅涵盖服务器端,还涵盖客户端端,这使得该API真正易于在任何地方使用。

让我们开始吧! 我们的目标是构建一个WebSockets服务器,该服务器接受来自客户端的消息并将其广播到当前连接的所有其他客户端。 首先,让我们定义消息格式,作为此简单的Message类,它将交换服务器和客户端。 我们可以将自己限制为String之类的东西,但我想向您介绍另一个新API的功能– 用于JSON处理的Java API(JSR-353) 。

package com.example.services;public class Message {private String username;private String message;public Message() {}public Message( final String username, final String message ) {this.username = username;this.message = message;}public String getMessage() {return message;}public String getUsername() {return username;}public void setMessage( final String message ) {this.message = message;}public void setUsername( final String username ) {this.username = username;}
}

为了分隔与服务器和客户端有关的声明, JSR-356定义了两个基本注释:分别为@ServerEndpoint@ClientEndpoit 。 我们的客户端端点,我们将其称为BroadcastClientEndpoint ,将仅侦听服务器发送的消息:

package com.example.services;import java.io.IOException;
import java.util.logging.Logger;import javax.websocket.ClientEndpoint;
import javax.websocket.EncodeException;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;@ClientEndpoint
public class BroadcastClientEndpoint {private static final Logger log = Logger.getLogger( BroadcastClientEndpoint.class.getName() );@OnOpenpublic void onOpen( final Session session ) throws IOException, EncodeException  {session.getBasicRemote().sendObject( new Message( "Client", "Hello!" ) );}@OnMessagepublic void onMessage( final Message message ) {log.info( String.format( "Received message '%s' from '%s'",message.getMessage(), message.getUsername() ) );}
}

就是这样! 很干净,的代码不言自明的片:当客户端得到了连接到服务器和@ 的onMessage被称为每次服务器@OnOpen被称为发送消息给客户端。 是的,它非常简单,但是有一个警告: JSR-356实现可以处理任何简单对象,但不能处理诸如Message is之类的复杂对象。 为了解决这个问题, JSR-356引入了编码器解码器的概念。

我们都喜欢JSON ,那么为什么不定义自己的JSON编码器和解码器呢? JSON处理的Java API(JSR-353)可以为我们完成这项简单的任务。 要创建编码器,只需实现Encoder.Text <Message>并使用JsonObjectBuilder将对象基本序列化为某个字符串,在我们的情况下为JSON字符串。

package com.example.services;import javax.json.Json;
import javax.json.JsonReaderFactory;
import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;public class Message {public static class MessageEncoder implements Encoder.Text< Message > {@Overridepublic void init( final EndpointConfig config ) {}@Overridepublic String encode( final Message message ) throws EncodeException {return Json.createObjectBuilder().add( "username", message.getUsername() ).add( "message", message.getMessage() ).build().toString();}@Overridepublic void destroy() {}}
}

对于解码器部分,一切看起来都非常相似,我们必须实现Decoder.Text <Message>并使用JsonReader从字符串反序列化我们的对象。

package com.example.services;import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonReaderFactory;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;public class Message {public static class MessageDecoder implements Decoder.Text< Message > {private JsonReaderFactory factory = Json.createReaderFactory( Collections.< String, Object >emptyMap() );@Overridepublic void init( final EndpointConfig config ) {}@Overridepublic Message decode( final String str ) throws DecodeException {final Message message = new Message();try( final JsonReader reader = factory.createReader( new StringReader( str ) ) ) {final JsonObject json = reader.readObject();message.setUsername( json.getString( "username" ) );message.setMessage( json.getString( "message" ) );}return message;}@Overridepublic boolean willDecode( final String str ) {return true;}@Overridepublic void destroy() {}}
}

最后,我们需要告诉客户端(和服务器,它们共享相同的解码器和编码器),我们拥有用于消息的编码器和解码器。 最简单的方法就是将它们声明为@ServerEndpoint@ClientEndpoit批注的一部分。

import com.example.services.Message.MessageDecoder;
import com.example.services.Message.MessageEncoder;@ClientEndpoint( encoders = { MessageEncoder.class }, decoders = { MessageDecoder.class } )
public class BroadcastClientEndpoint {
}

为了使客户的示例更完整,我们需要某种方式使用BroadcastClientEndpoint连接到服务器并基本上交换消息。 ClientStarter类最终确定图片:

package com.example.ws;import java.net.URI;
import java.util.UUID;import javax.websocket.ContainerProvider;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;import org.eclipse.jetty.websocket.jsr356.ClientContainer;import com.example.services.BroadcastClientEndpoint;
import com.example.services.Message;public class ClientStarter {public static void main( final String[] args ) throws Exception {final String client = UUID.randomUUID().toString().substring( 0, 8 );final WebSocketContainer container = ContainerProvider.getWebSocketContainer();    final String uri = "ws://localhost:8080/broadcast";  try( Session session = container.connectToServer( BroadcastClientEndpoint.class, URI.create( uri ) ) ) {for( int i = 1; i <= 10; ++i ) {session.getBasicRemote().sendObject( new Message( client, "Message #" + i ) );Thread.sleep( 1000 );}}// Application doesn't exit if container's threads are still running( ( ClientContainer )container ).stop();}
}

只需几句注释,此代码即可完成操作:我们正在ws:// localhost:8080 / broadcast连接到WebSockets端点,随机选择一些客户端名称(来自UUID)并生成10条消息,每条消息都有1秒的延迟(请确保我们有时间将它们全部收回来)。

服务器部分看起来并没有很大不同,并且在这一点上无需任何其他注释就可以理解(服务器可能只是将接收到的每条消息广播给所有连接的客户端)。 这里要提到的重要一点:每当新客户端连接到服务器端点时,都会创建服务器端点的新实例(这就是对等体集合是静态的),这是默认行为,可以轻松更改。

package com.example.services;import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;import javax.websocket.EncodeException;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;import com.example.services.Message.MessageDecoder;
import com.example.services.Message.MessageEncoder;@ServerEndpoint( value = "/broadcast", encoders = { MessageEncoder.class }, decoders = { MessageDecoder.class } 
) 
public class BroadcastServerEndpoint {private static final Set< Session > sessions = Collections.synchronizedSet( new HashSet< Session >() ); @OnOpenpublic void onOpen( final Session session ) {sessions.add( session );}@OnClosepublic void onClose( final Session session ) {sessions.remove( session );}@OnMessagepublic void onMessage( final Message message, final Session client ) throws IOException, EncodeException {for( final Session session: sessions ) {session.getBasicRemote().sendObject( message );}}
}

为了使该端点可用于连接,我们应该启动WebSockets容器并在其中注册该端点。 与往常一样, Jetty 9.1可以轻松地以嵌入式模式运行:

package com.example.ws;import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;import com.example.config.AppConfig;public class ServerStarter  {public static void main( String[] args ) throws Exception {Server server = new Server( 8080 );// Create the 'root' Spring application contextfinal ServletHolder servletHolder = new ServletHolder( new DefaultServlet() );final ServletContextHandler context = new ServletContextHandler();context.setContextPath( "/" );context.addServlet( servletHolder, "/*" );context.addEventListener( new ContextLoaderListener() );   context.setInitParameter( "contextClass", AnnotationConfigWebApplicationContext.class.getName() );context.setInitParameter( "contextConfigLocation", AppConfig.class.getName() );server.setHandler( context );WebSocketServerContainerInitializer.configureContext( context );        server.start();server.join(); }
}

上面片段中最重要的部分是WebSocketServerContainerInitializer.configureContext :它实际上是创建WebSockets容器的实例。 因为我们还没有添加任何端点,所以容器基本上位于此处,什么也不做。 Spring Framework和AppConfig配置类将为我们完成最后的连接。

package com.example.config;import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.websocket.DeploymentException;
import javax.websocket.server.ServerContainer;
import javax.websocket.server.ServerEndpoint;
import javax.websocket.server.ServerEndpointConfig;import org.eclipse.jetty.websocket.jsr356.server.AnnotatedServerEndpointConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.WebApplicationContext;import com.example.services.BroadcastServerEndpoint;@Configuration
public class AppConfig  {@Inject private WebApplicationContext context;private ServerContainer container;public class SpringServerEndpointConfigurator extends ServerEndpointConfig.Configurator {@Overridepublic < T > T getEndpointInstance( Class< T > endpointClass ) throws InstantiationException {return context.getAutowireCapableBeanFactory().createBean( endpointClass );   }}@Beanpublic ServerEndpointConfig.Configurator configurator() {return new SpringServerEndpointConfigurator();}@PostConstructpublic void init() throws DeploymentException {container = ( ServerContainer )context.getServletContext().getAttribute( javax.websocket.server.ServerContainer.class.getName() );container.addEndpoint( new AnnotatedServerEndpointConfig( BroadcastServerEndpoint.class, BroadcastServerEndpoint.class.getAnnotation( ServerEndpoint.class )  ) {@Overridepublic Configurator getConfigurator() {return configurator();}});}  
}

如前所述,默认情况下,容器会在每次新客户端连接时创建服务器端点的新实例,并通过调用构造函数来实现,在本例中为BroadcastServerEndpoint.class.newInstance() 。 这可能是理想的行为,但是由于我们使用的是Spring Framework和依赖项注入,因此此类新对象基本上是不受管的bean。 由于JSR-356的精心设计(在我看来),通过实现ServerEndpointConfig.Configurator可以很容易地提供您自己的创建端点实例的方式。 SpringServerEndpointConfigurator就是这种实现方式的一个示例:每次请求新的终结点实例时,它都会创建一个新的托管Bean(如果您想要单个实例,则可以在AppConfig中将终结点的一个实例创建为Bean并一直返回)。

我们检索WebSockets容器的方式特定于Jetty :从名称为“ javax.websocket.server.ServerContainer”的上下文属性中获取 (将来可能会更改)。 容器到达后,我们通过提供我们自己的ServerEndpointConfig (基于Jetty已经提供的AnnotatedServerEndpointConfig )来添加新的(托管!)端点。

要构建和运行我们的服务器和客户端,我们只需要这样做:

mvn clean package
java -jar target\jetty-web-sockets-jsr356-0.0.1-SNAPSHOT-server.jar // run server
java -jar target/jetty-web-sockets-jsr356-0.0.1-SNAPSHOT-client.jar // run yet another client

例如,通过运行服务器和几个客户端(我运行了其中的四个 ,即“ 392f68ef ”,“ 8e3a869d ”,“ ca3a06d0 ”,“ 6cb82119 ”),您可能会在控制台的输出中看到每个客户端都接收到所有消息来自所有其他客户端(包括其自身的消息):

Nov 29, 2013 9:21:29 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Hello!' from 'Client'
Nov 29, 2013 9:21:29 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #1' from '392f68ef'
Nov 29, 2013 9:21:29 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #2' from '8e3a869d'
Nov 29, 2013 9:21:29 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #7' from 'ca3a06d0'
Nov 29, 2013 9:21:30 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #4' from '6cb82119'
Nov 29, 2013 9:21:30 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #2' from '392f68ef'
Nov 29, 2013 9:21:30 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #3' from '8e3a869d'
Nov 29, 2013 9:21:30 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #8' from 'ca3a06d0'
Nov 29, 2013 9:21:31 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #5' from '6cb82119'
Nov 29, 2013 9:21:31 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #3' from '392f68ef'
Nov 29, 2013 9:21:31 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #4' from '8e3a869d'
Nov 29, 2013 9:21:31 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #9' from 'ca3a06d0'
Nov 29, 2013 9:21:32 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #6' from '6cb82119'
Nov 29, 2013 9:21:32 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #4' from '392f68ef'
Nov 29, 2013 9:21:32 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #5' from '8e3a869d'
Nov 29, 2013 9:21:32 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #10' from 'ca3a06d0'
Nov 29, 2013 9:21:33 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #7' from '6cb82119'
Nov 29, 2013 9:21:33 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #5' from '392f68ef'
Nov 29, 2013 9:21:33 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #6' from '8e3a869d'
Nov 29, 2013 9:21:34 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #8' from '6cb82119'
Nov 29, 2013 9:21:34 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #6' from '392f68ef'
Nov 29, 2013 9:21:34 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #7' from '8e3a869d'
Nov 29, 2013 9:21:35 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #9' from '6cb82119'
Nov 29, 2013 9:21:35 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #7' from '392f68ef'
Nov 29, 2013 9:21:35 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #8' from '8e3a869d'
Nov 29, 2013 9:21:36 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #10' from '6cb82119'
Nov 29, 2013 9:21:36 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #8' from '392f68ef'
Nov 29, 2013 9:21:36 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #9' from '8e3a869d'
Nov 29, 2013 9:21:37 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #9' from '392f68ef'
Nov 29, 2013 9:21:37 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #10' from '8e3a869d'
Nov 29, 2013 9:21:38 PM com.example.services.BroadcastClientEndpoint onMessage
INFO: Received message 'Message #10' from '392f68ef'
2013-11-29 21:21:39.260:INFO:oejwc.WebSocketClient:main: Stopped org.eclipse.jetty.websocket.client.WebSocketClient@3af5f6dc

太棒了! 我希望这篇介绍性博客文章能够显示在Java中使用现代Web通信协议变得多么容易,这要归功于Java WebSockets(JSR-356) , 用于JSON处理的Java API(JSR-353)以及诸如Jetty 9.1之类的出色项目!

  • 与往常一样,完整的项目可在GitHub上获得 。

在我们的JCG合作伙伴 Andrey Redko的Andriy Redko {devmind}博客上, 引用 了Jetty 9.1上的Java WebSockets(JSR-356) 。

翻译自: https://www.javacodegeeks.com/2013/12/java-websockets-jsr-356-on-jetty-9-1.html

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

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

相关文章

如何用python画组合图形_python结合G2绘制精美图形

$.getJSON(top10.json, function (data) { var Frame G2.Frame; var frame new Frame(data); var chart new G2.Chart({ id: c1, width: 500, height: 400 }); chart.source(frame, { pct: {alias: 年化相对收益率(%)}, }); // 去除 X 轴标题 chart.axis(name, { title: nul…

edup无线网卡驱动安装linux,UBUNTU_15.0.4 usb无线网卡驱动安装方法

前言&#xff1a;为了摆脱网线的束缚&#xff0c;我买了个无线网卡&#xff1b; widnows 上好用&#xff0c;易安装。linux 上&#xff0c;按照自带教程上去做&#xff0c;没有成功。后来在搜索了多篇 解决问题的文章。 再加上自己的方法&#xff0c;终于完成了。貌似信号还可以…

LeetCode Golang 9.回文数

9. 回文数 第一种办法 &#xff1a;itoa 转换为字符串进行处理&#xff1a; package mainimport ("strconv""fmt" )//判断一个整数是否是回文数。回文数是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&#xff09;读都是一样的整数。…

关于使用JQ scrollTop方法进行滚动定位

没图我说个锤子&#xff0c;先来个自拍镇楼。 又到了每周周五总结时间。我广州刘德华又来讲故事了。这一周没啥任务&#xff0c;就一个任务&#xff0c;产品口头交代了两句&#xff0c;也没有psd没有设计图没有样式。自由发挥&#xff0c;你自己敲代码做个作品出来。 what&…

ssh密钥登录

方法一:使用下例中ssky-keygen和ssh-copy-id&#xff0c;仅需通过3个步骤的简单设置而无需输入密码就能登录远程Linux主机。 ssh-keygen 创建公钥和密钥。 ssh-copy-id 把本地主机的公钥复制到远程主机的authorized_keys文件上。ssh-copy-id 也会给远程主机的用户主目录&#x…

Spring REST:异常处理卷。 2

这是有关使用Spring进行REST异常处理的系列的第二篇文章。 在我以前的文章中&#xff0c;我描述了如何在REST服务中组织最简单的异常处理。 这次&#xff0c;我将更进一步&#xff0c;我将向您展示何时最好在ControllerAdvice级别上使用异常处理 。 介绍 在开始本文的技术部分…

python 装饰器有哪些_python装饰器有什么用

简言之&#xff0c;python装饰器就是用于拓展原来函数功能的一种函数&#xff0c;这个函数的特殊之处在于它的返回值也是一个函数&#xff0c;使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。 一般而言&#xff0c;我们要想拓展原来函数代码&…

jQuery数据转换与提交

json2.js序列化,即JSON对象转换成String字符串&#xff1a; JSON.stringify({ id: 1, name: jsons });反序列化,即String转JSON对象&#xff1a; JSON.parse("{ id: 1, name: jsons }");jquery.json2xml.jsJSON对象转换为XML字符串&#xff1a; $.json2xml({ id: 1, …

linux中查看相关日志记录,linux重启查看日志及历史记录 查询原因

linux系统文件通常在/var/log中下面是对下面常出现的文件进行解释/var/log/message ---------------------------------------系统启动后的信息和错误日志/var/log/secure ------------------------------------------与安全相关的日志信息/var/log/maillog ------------------…

04,认证、权限、频率

认证组件 Django原生的authentic组件为我们的用户注册与登录提供了认证功能&#xff0c;十分的简介与强大。同样DRF也为我们提供了认证组件&#xff0c;一起来看看DRF里面的认证组件是怎么为我们工作的&#xff01;models.py# 定义一个用户表和一个保存用户Token的表 class Use…

sun.misc.Unsafe和堆外内存

sun.misc.Unsafe类允许您执行许多Java中不应该做的事情&#xff0c;但是在非常特殊的情况下仍然有用。 必须在99&#xff05;的时间避免这种情况&#xff0c;但是在极少数情况下&#xff0c;这是唯一有意义的解决方案。 这篇文章考虑了它在OpenHFT中的使用方式以及我希望在Jav…

jq获取input选取的文件名_tushare获取交易数据并可视化分析

获取数据是金融量化分析的第一步&#xff0c;找不到可靠、准确的数据&#xff0c;量化分析就无从谈起。随着信息技术的不断发展&#xff0c;数据获取渠道也越来越多&#xff0c;尤其是Python网络爬虫&#xff0c;近几年愈来愈火。然而&#xff0c;很多人毕竟精力有限&#xff0…

linux电脑做笔记软件,知识管理工具, 自由格式数据库, 笔记软件以及个人信息管理...

myBase Desktop 7.3.5 for Linux/MacOSX/Windows 2020-2-20新增 [数学公式 MathJax for Markdown]、[自动锁屏保护]、[粘贴图片为附件]、[完整复制带图片内容]&#xff0c;以及部分问题修订&#xff0c;详见&#xff1a;更新日志&#xff1b;数学公式插件&#xff1a;缺省安装后…

js模板引擎

模板引擎 function tmpl(str, o) {return str.replace(/\\?\{([^{}] )\}/g, function (match, name) {return (o[name] undefined) ? : o[name];});}调用示例 var html tmpl(html, { user_id: user_id, user_name: user_name });更多专业前端知识&#xff0c;请上 【猿204…

原来游戏技术行业最大的秘密竟然是...

欢迎大家前往腾讯云社区&#xff0c;获取更多腾讯海量技术实践干货哦~ 本文由腾讯游戏云发表于云社区专栏 本篇文章主要是分享游戏业务面临的安全风险场景&#xff0c;以及基于这些场景的特点&#xff0c;我们应该如何做好对应的防护。 【一、背景&#xff1a;游戏行业DDoS攻击…

Leetcode 565. Array Nesting

题目 链接&#xff1a;https://leetcode.com/problems/array-nesting/ Level: Medium Discription: A zero-indexed array A of length N contains all integers from 0 to N-1. Find and return the longest length of set S, where S[i] {A[i], A[A[i]], A[A[A[i]]], ... }…

指定Gradle构建属性

属性是用于轻松自定义Gradle构建和Gradle环境的宝贵工具。 我将在本文中演示一些用于指定Gradle构建中使用的属性的方法。 Gradle支持项目属性和系统属性 。 这篇文章中有趣的是两者之间的主要区别是如何访问它们。 通过常规Java / Groovy系统属性访问方法访问系统属性时&…

python数字转中文字符_Python实现中文数字转换为阿拉伯数字的方法示例

本文实例讲述了Python实现中文数字转换为阿拉伯数字的方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a; 一、需求 今天写了三千二百行代码。 今天写了3200行代码。 两行意思相同&#xff0c;只是表达方式不太能够&#xff0c;统一掉。 二、原理 数字的特征是 数字 …

调程序时的小错误

1.未能找到类型或命名空间名称“Form1”(是否缺少 using 指令或程序集引用?) 应该是复制代码的时候&#xff0c;把程序入口处的命名空间和Form1的命名空间不一致 2.检索 COM 类工厂中 CLSID 为 {XXXX-XXXX-XXX-XXXXX-XXX} 的组件时失败&#xff0c;原因是出现以下错误: 80040…

eclipse中设置Linux编码环境,更改eclipse中console编码

1.在eclipse.ini的-vmargs下面加上「-Dfile.encodingUTF-8」。2.eclipse-->Window-->Preferences-->General-->Workspace-->Text file encoding-->UTF-83.Installed JREs-->Default VM Arguments:-->-Dfile.encodingUTF-84.eclipse-->Run-->Run …