作者:Federer2012_554 | 来源:互联网 | 2022-12-28 15:03
postprotobufjava怎么请求网络数据这是corejava2的例子URLConnectionconnectionurl.openConnection(;url为ht
post protobuf java怎么请求网络数据
这是core java2的例子 URLConnection cOnnection= url.openConnection();//url为http服务器地址 connection.setDoOutput(true); PrintWriter out = new PrintWriter(connection.getOutputStream());//获得输出流 //向服务器传递参数 Enumeration enum = nameValuePairs.keys(); while (enum.hasMoreElements()) { String name = (String)enum.nextElement(); String value = nameValuePairs.getProperty(name); char ch; if (enum.hasMoreElements()) ch = '&'; else ch = '\n'; out.print(name + "=" + URLEncoder.encode(value) + ch); System.out.println(name+ value); } out.close();//获取输入流 BufferedReader in; try { in = new BufferedReader(new InputStreamReader(connection.getInputStream())); } catch (FileNotFoundException exception) { InputStream err = ((HttpURLConnection)connection).getErrorStream(); if (err == null) throw exception; in = new BufferedReader(new InputStreamReader(err)); } StringBuffer respOnse= new StringBuffer(); String line;//读取数据 while ((line = in.readLine()) != null) response.append(line + "\n"); in.close(); return response.toString(); }}
java 怎么使用protobuf库
1.到http://code.google.com/p/protobuf/downloads/list ,选择其中的win版本下载,我选择的是protoc-2.4.1-win32.zip2.下载一个protobuf-java-2.4.1.jar文件(注意,要与你刚才下的proto.exe版本相同)然后就开始开发了。步骤:1.用记事本编写一个.proto文件:}如:编写的是test.proto package protobuf; option java_package = "com.sq.protobuf"; option java_outer_classname = "FirstProtobuf"; message testBuf { required int32 ID = 1; required string Url = 2; }将其放在与刚解压的protoc.exe同级目录中。
2.在cmd中,到protoc-2.4.1-win32文件夹下,执行E:\protoc-2.4.1-win32> protoc.exe --java_out=./ test.proto 则可以找到的一个生成的FirstProtobuf.java文件。
3.在MyEclipse中新建一个java project,建立包com.sq.protobuf,然后将刚才生成的FirstProtobuf.java文件放在其下面。此时会报错,因为没有引入jar包,在package视图下,将protobuf-java-2.4.1.jar引入,即可解决问题。4.建立测试文件:package com.sq.protobuf.test; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.sql.Blob; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.Statement; import com.google.protobuf.InvalidProtocolBufferException; import com.sq.protobuf.FirstProtobuf; public class Test { public static void main(String[] args) { //序列化过程 //FirstProtobuf是生成类的名字,即proto文件中的java_outer_classname //testBuf是里面某个序列的名字,即proto文件中的message testBuf FirstProtobuf.testBuf.Builder builder=FirstProtobuf.testBuf.newBuilder(); builder.setID(777); builder.setUrl("shiqi"); //testBuf FirstProtobuf.testBuf info=builder.build(); byte[] result = info.toByteArray() ; String driver = "oracle.jdbc.driver.OracleDriver"; String url = "jdbc:oracle:thin:@10.64.59.12:1521/orcl"; String user = "parkingsystem"; String password = "parkingsystem"; try { Class.forName(driver); Connection cOnn= DriverManager.getConnection(url, user, password); if(!conn.isClosed()){ System.out.println("Succeeded connecting to the Database!"); //此处只能使用prepareStatement PreparedStatement ps = conn.prepareStatement("insert into test(id,test) values (1,?)"); //写入数据库,要把它改写为流的形式 ByteArrayInputStream stream = new ByteArrayInputStream(result); ps.setBinaryStream(1,stream,stream.available()); Statement statement = conn.createStatement(); Blob blob = null; ps.execute(); ////////////////上述完成将写入数据库的操作,数据库中对应的字段的属性要设置为Blob String sql = "select test from test"; ResultSet rs = statement.executeQuery(sql); if(rs.next()){ blob = rs.getBlob("test"); } byte[] s = blob.getBytes(1,(int)blob.length()); FirstProtobuf.testBuf testBuf = FirstProtobuf.testBuf.parseFrom(s); System.out.println(testBuf); conn.close(); } }catch(Exception e) { e.printStackTrace(); } //反序列化过程 try { FirstProtobuf.testBuf testBuf = FirstProtobuf.testBuf.parseFrom(result); System.out.println(testBuf); } catch (InvalidProtocolBufferException e) { e.printStackTrace(); } } } 发现可以将其序列化,插入到数据库,并可以从数据库出取出后,反序列化,内容可以正常显示出来。
作为java后端,在用protobuf的情况下我该给前端传什么形式的数据?
protobuf是你们落地时存储的数据格式,跟给前端的格式是没有关系的。可以通过工具类直接转json后传给前端。
Class> clazz = Class.forName(className);Method method = clazz.getMethod("parseFrom", byte[].class);JsonFormat().printToString((GeneratedMessage) method.invoke(clazz, bytes));其中className是你根据protobuf文件生成的java类,bytes是读取的protobuf对象的字节数组。
了解一下ProtoBuf
我们在进行网络通信调用的时候,总是需要将内存的数据块经过序列化,转换成为一种可以通过网络流进行传输的格式。而这种格式在经过了传输之后再经过序列化,能还原成我们预想中的数据结构。
那么我们对于这种用于中间网络传输的数据格式就有一定的要求。
首先它可以准确地描述数据内容,在此基础上我们则希望它尽量的小。 最开始流行起来的是XML,可扩展标记语言。由于它可以用来标记数据、定义数据类型,所以用户可以自己定义数据自己的语言,从而让对不同的数据结构化成统一的格式称为了可能。 而另外一个我们熟知的则是JSON(Javascript Object Notation, JS 对象简谱)。
尽管JSON中缺少了XML中的标签属性等描述方式,但是足够简介和清晰的层次结构使得其成为了必XML更受欢迎的数据交换格式。 同一份数据显然JSON的数据量比XML所使用的空间更少。那么空间省略在哪里呢?一方面是json使用更简单的字符来定义数据间的关联关系;另一方面是JSON减少了对数据类型的描述。
但是丢少的数据类型再哪里呢? 以Java中的 OpenFeign 举例,JSON中缺少的类型定义被定义道程序中的接口中了。当进行序列化与反序列化时,JSON格式并不记录数据的类型,具体的数据类型在序列化方与反序列化方通过事先约定的接口来进行定义。这样就减少了信息传输过程中的信息量,从而让数据得以压缩。
但是JSON由于没有定义数据类型,所以在传输的过程中实际上就都是文本流,那么这种方法还可以进一步压缩吗? 结合上文的讨论,我们先说结论:方法是有的,并写当前的实现方式是ProtoBuf。但在此之前我们先来了解一下ProtoBuf。 我们可以先看看官方给出的定义与描述: 同样的,ProtoBuf也是一种支持序列化反序列化的方法,并且他具有很多优点: 实际上,ProtoBuf提供了一种通用的数据描述方式,这种定义数据的方式是通用的,就如同JSON或者XML一样。
接下来我们来来回答本节一开始的问题,针对JSON来说,ProtoBuf是如何将体积变得更小的呢?答案很简单,就是为数据序列化反序列化提供更多的先验知识。 本文暂不过度深入ProtoBuf原理,但是可以通过一张图来进行简要说明(): ProtoBuf中的数据是按顺序进行排列,而整体的结构为若干个field,每一个field中由 Tag-[Length]-Value 组成。Length是可选的,而是否存在Length是通过Tag的类型来决定的。也就是说如果是指定的类型,比如int64,那我们就可以知道Value的长度,也就不用在依靠Length来对其空间进行描述(redis中的压缩列表也是这个思想)。
那么field应该对应的是什么字段呢?这个则是在序列化与反序列化时在ProtoBuf的服务端与客户端之间进行预先定义的。而因为提前定义了field的类型、排序,所以field本身可以不用对字段名、字段位置进行描述,只需要根据字段类型选用合适的二进制序列化方法,将字段本身的value值进行序列化传输即可。 稍微总结一下: ProtoBuf通过对传输字段的名称、顺序进行预定义,从而在传输结构中只需要顺序的记录每个字段的类型标签和二进制值。 尽管上文和官方中都是以XML或者JSON来对ProtoBuf进行对比。
但是因为ProtoBuf本身就是二进制序列化方式,所以从压缩比上比较感觉有点欺负人。 对应的在Java中二进制常用的序列化器有Kryo和Hessian。但事实上,由于Kryo和Hessian中都需要对Java类名和字段信息进行存储。而ProtoBuf则只有Tag-Length-Value的数据对,且Value更是有针对性的特殊编码,所以空间占用小的很多。
Kryo是专门针对Java进行优化了的。所以在使用的便捷性上来说Kryo则更加方便。但ProtoBuf是跨平台的,且由于进行了字段的顺序定义,所以似的ProtoBuf定义后的接口是可以向前兼容的(只向后追加字段),而这种优势是Kryo所没有的。
ProtoBuf是跨语言的,使用ProtoBuf的第一步是先定一个 proto 文件 ,而由于ProtoBuf 2和3语言版本的不同,其定义格式会有所不同,具体的细节还是得参考官方文档:https://developers.google.cn/protocol-buffers/docs/proto3 对于ProtoBuf 3 的定义文档我们可以按如下方法定义: 其中message关键字是定义的文件名,而 string、int32则是预定的字段类型,repeated则是描述字段为可重复任意多次的字段。 ProtoBuf通过这种形式的文件定义了传输信息的文件结构。 但是之前小节中我们知道了ProtoBuf是通过 Tag-[Length]-Value 组成的数据组来进行信息传输的,那么proto文件中定义的内容如何转换为实际传输的对象呢? ProtoBuf的做法是,为每一种语言提供一个生成器protoc。
通过使用protoc则可以根据.proto文件生成为一组java文件。对应的官方语法演示样例为: 官方的生成参考为:https://developers.google.com/protocol-buffers/docs/reference/java-generated 生成后的java文件将提供对应的实体以及数据的构造方法等文件,从而支持后续的使用。 需要注意的是,ProtoBuf是本质上是序列化方法,具体是通过Spring Cloud 的OpenFeign进行接口调用,还是通过grpc进行接口调用,都是可以的。 本文对ProtoBuff进行了概念的整理,并没有对每个细节都进行深入的梳理,可以当作概念科普来进行阅读。
如何将.proto通过命令转换成.java文件
1.http://code.google.com/p/protobuf/downloads/list 下载 protoc-2.4.1-win32.zip 至本地并解压
2.通过命令行将.proto的文件生成为.java的文件官网上是这样写的
protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/addressbook.proto
下面用图形来说明如果操作。