Netty的基本使用
Gradle 的优点 原文:https://blog.csdn.net/achenyuan/article/details/80682288
1. 按约定声明构建和建设;
2. 强大的支持多工程的构建;
3. 强大的依赖管理(基于Apache Ivy),提供最大的便利去构建工程;
4. 全力支持已有的 Maven 或者Ivy仓库基础建设;
5. 支持传递性依赖管理,在不需要远程仓库和pom.xml和ivy配置文件的前提下;
6. 基于groovy脚本构建,其build脚本使用groovy语言编写;
7. 具有广泛的领域模型支持构建;
8. 深度 API;
9. 易迁移;
10. 自由和开放源码,Gradle是一个开源项目,基于 ASL 许可。
下面是Gradle 基本配置的简介
build.gradle (作用类似于 maven 中的epom 文件)
plugins {
id 'java'
id 'war'
} group 'gradle02-projext'
version '1.0-SNAPSHOT' sourceCompatibility = 1.8 dependencies {
testCompile group: 'junit', name: 'junit', version: '4.11'
testCompile group: 'junit', name: 'junit', version: '4.12'
}
原文位置(https://blog.csdn.net/cluzax/article/details/46583771)
目录文件 | 作用 |
---|---|
.gradle | gradle项目产生文件(自动编译工具产生的文件) |
.idea | IDEA项目文件(开发工具产生的文件) |
app | 其中一个module,复用父项目的设置,可与父项目拥有相同的配置文件 |
build | 自动构建时生成文件的地方 |
gradle | 自动完成gradle环境支持文件夹 |
.gitignore | git源码管理文件 |
build.gradle | gradle 项目自动编译的配置文件 |
gradle.properties | gradle 运行环境配置文件 |
gradlew | 自动完成 gradle 环境的linux mac 脚本,配合gradle 文件夹使用 |
gradlew.bat | 自动完成 gradle 环境的windows 脚本,配合gradle 文件夹使用 |
local.properties | Android SDK NDK 环境路径配置 |
*.iml | IDEA 项目文件 |
setting.gradle | gradle 项目的子项目包含文件 |
- .gradle .idea 是在分别在 gradle ,IDEA 运行时候会生成的文件,一般这样的文件也不会纳入源代码管理之中。
- app文件夹,是其中一个module,里面的文件内容与父类差不多,若没有定义,则在项目中使用父类的设置(意思就是,里面也能包含build.gradle、gradle.properties、setting.gradle 等相关gradle文件,怎么理解?其实每一层都是一个module,整个项目是一个大的 module 而已)
- gradle 文件夹,用于保存gradle 下载路径的配置文件位置,用于没有gradle环境的环境初始化使用
- build.gradle 项目的编译环境配置,比如制定项目依赖的lib包。
- gradle.properties 配置gradle运行环境的文件,比如配置gradle运行模式,运行时jvm虚拟机的大小
- gradlew && gradlew.bat 代替gradle 命令实现自动完成gradle环境搭建。配合gradle文件夹的内容,会降到IDEA如何搭配gradlew使用。
- local.properties 配置android NDK,SDK的地方,恩,非android项目可能没有这个文件,这个路径根据不同想电脑不同,一般也不会纳入源代码管理之中,一般可以写一个local.properties.simple 文件,告知需要修改该文件名并写上本地SDK NDK 路径。simple文件纳入源码管理之中。
- setting.gradle 子项目包含文件,声明当前目录下含有什么module,当然你的app底下加上这样的文件,也能继续在app底下加module。和我第点说的,整个project就是一个大的module,每个module下面还能包含相应的module。如果你理解这个了,其实app目录单独作为一个项目管理也是可以的,,把相应的配置文件配上而已,相当于主目录应用 android 的gradle plugin (下一点会说到这个)
gitignore 该文件是源码管理的配置文件,不在该文讲解。
既然gradle 是多 module形式,那么我们来看看 setting.gradle 配置的内容
rootProject.name = 'gradle'
从上面目录的配置文件内容来看,整个project也算是一个module,如果改module底下还有module,就可以通过setting.gradle配置进来,使得该module底下的gradle,从app module底下可以看出,module最少要含有 build.gradle文件,这个module的项目编译文件,该module依赖什么插件对该目录进行编译都在此配置,比如android与android-library,其他内容可继承父类的
同样maven项目需要依赖,Gradle也需要jar包
但是Gradle的jar包去哪里找呢 根据Build.Gradle 已经指出来了
repositories {
mavenCentral() maven中心仓库
}
网址是https://search.maven.org/ 使用搜狗浏览器我的打不开,所以我使用了谷歌
里面有一个jar包是将netty所有的jar包都包含了
我都拷贝出来吧
maven版本下的 还不让我copy
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <veresion>5.0..Alpha2<version> </dependency>
'io.netty:netty-all:4.1.34.Final'
E:\sturts2\gradle03-projext>gradle clean build BUILD SUCCESSFUL in 12s
actionable tasks: executed
E:\sturts2\gradle03-projext>
下面先上一个代码,输出helloworld 我再学习的时候,也是一脸懵或许等一下就好了吧
按照我的习惯,先写配置
plugins {
id 'java'
id 'war'
} group 'gradle03-projext'
version '1.0' sourceCompatibility = 1.8
targetCompatibility = 1.8 repositories {
mavenCentral()
} dependencies {
/*testCompile group: 'junit', name: 'junit', version: '4.11'*/
testCompile group: 'junit', name: 'junit', version: '4.12'
compile(
'io.netty:netty-all:4.1.34.Final'
)
}
TestServer
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel; /**
* Description: gradle03
* Created by lenovo on 2019/4/17 19:39
*/
public class TestServer { public static void main (String[] args) throws InterruptedException { /*netty中大量的就是对线程的处理对线程的控制,对io的一些异步的操作*/
/*先定义两个线程组NIo 就是异步的*/
/*事件循环组:*/
EventLoopGroup bossLoopGroup = new NioEventLoopGroup();
EventLoopGroup workLoopGroup = new NioEventLoopGroup(); ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossLoopGroup,workLoopGroup).channel(NioServerSocketChannel.class).childHandler(new TestServerInitializer()); ChannelFuture channelFuture = serverBootstrap.bind().sync();
channelFuture.channel().closeFuture().sync(); bossLoopGroup.shutdownGracefully();
workLoopGroup.shutdownGracefully(); }
}
TestHttpServerHandler
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil; import javax.servlet.http.HttpServlet;
import java.nio.charset.Charset; /**
* Description: gradle03
* Created by lenovo on 2019/4/17 20:50
*/
public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> { @Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
if (msg instanceof HttpRequest){ ByteBuf content = Unpooled.copiedBuffer("hello world", CharsetUtil.UTF_8);
DefaultFullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text/plain");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());
ctx.writeAndFlush(response);
} }
}
TestServerInitializer
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec; /**
* Description: gradle03
* Created by lenovo on 2019/4/17 20:46
*/
public class TestServerInitializer extends ChannelInitializer<SocketChannel> { @Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("httpServerCode",new HttpServerCodec());
pipeline.addLast("testHttpServletHandler",new TestHttpServerHandler());
}
}
浏览器中是可以访问到的
http://localhost:8899/
现在分析时间执行的流程,和方法回调
执行结果就是这个
channelRegister
channelRegister
channelActive
channelActive
channelReadComplete
等你停下来3秒,管道就自动取消了注册
channelRegister
channelRegister
channelActive
channelActive
channelReadComplete
channelReadComplete
channelInactive
channelUnregister
使用netty能做什么,也是对请求进行响应
Netty并没与实现servlet规范,netty编写代码要实现的步骤
1.编写服务器
2.在服务器中编写我们自定义的Servletinitializer对象
3.在Servletinitializer中去使用很多的handler
现在再放上一个例子 客户端通信
服务端
package com.netty.chatting; import com.netty.socket.MyServletInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel; /**
* Description: gradle03
* Created by lenovo on 2019/4/18 10:14
*/
public class MyChattingServer {
public static void main (String[] args) throws InterruptedException { NioEventLoopGroup bossGroup = new NioEventLoopGroup(); NioEventLoopGroup workerGroup = new NioEventLoopGroup(); ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).
childHandler(new MychatServerInitalizer()); serverBootstrap.bind().sync();
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully(); } }
MyChatServer
package com.netty.chatting; import com.netty.socket.MyHttpServerHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil; import java.net.Socket; /**
* Description: gradle03
* Created by lenovo on 2019/4/18 10:21
*/
/*
public class MychatServerInitalizer extends ChannelInitializer<SocketChannel> { @Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new DelimiterBasedFrameDecoder(4096, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); pipeline.addLast(new MyChatServerHandler());
}
}
*/
public class MychatServerInitalizer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new DelimiterBasedFrameDecoder(, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); pipeline.addLast("testHttpServletHandler",new MyChatServerHandler());
}
}
MyChatInitializer
package com.netty.chatting; import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;
import jdk.nashorn.internal.objects.Global; /**
* Description: gradle03
* Created by lenovo on 2019/4/18 10:43
*/
public class MyChatServerHandler extends SimpleChannelInboundHandler<String> { public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); @Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
Channel channel = ctx.channel();
channelGroup.forEach(ch -> {
if (channel!=ch){
ch.writeAndFlush(channel.remoteAddress()+"发送的消息"+msg+"\n"); }else{
ch.writeAndFlush("自己"+msg+"\n");
}
});
} @Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
super.handlerAdded(ctx);
Channel channel = ctx.channel();
channelGroup.writeAndFlush("服务器-"+channel.remoteAddress()+"加入\n");
channelGroup.add(channel); } @Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
super.handlerRemoved(ctx);
Channel channel = ctx.channel();
channelGroup.writeAndFlush("服务器-"+channel.remoteAddress()+"离开\n");
System.out.println(channelGroup.size());
} @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
Channel channel = ctx.channel();
System.out.println(channel.remoteAddress()+"上线\n");
} @Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
super.channelInactive(ctx);
Channel channel = ctx.channel();
System.out.println(channel.remoteAddress()+"下线\n");
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
super.exceptionCaught(ctx, cause);
ctx.close();
}
}
MyChatServerHandler
客户端
package com.netty.chatting; import com.netty.socket.MySClientInitializer;
import com.sun.org.apache.bcel.internal.generic.NEW;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader; /**
* Description: gradle03
* Created by lenovo on 2019/4/18 11:16
*/
public class MyChatClientServer {
public static void main (String[] args){ EventLoopGroup eventExecutors = new NioEventLoopGroup(); try {
Bootstrap bootstrap = new Bootstrap(); bootstrap.group(eventExecutors).channel(NioSocketChannel.class).handler(new MyChatClientInitializer());
Channel channel = bootstrap.connect("localhost",).sync().channel(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in)); for (;;){
channel.writeAndFlush(bufferedReader.readLine()+"\r\n");
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
eventExecutors.shutdownGracefully();
} }
}
MyChatClientServer
package com.netty.chatting; import com.netty.socket.MyClientHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil; public class MyChatClientInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new DelimiterBasedFrameDecoder(, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); pipeline.addLast("testHttpServletHandler",new MyChatClientServerHandler());
}
}
MyChatClientInitializer
package com.netty.chatting; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; /**
* Description: gradle03
* Created by lenovo on 2019/4/18 11:17
*/
public class MyChatClientServerHandler extends SimpleChannelInboundHandler<String> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(msg);
}
}
MyChatClientServerhandler
放上执行结果
先后打开了三个客户端
下面是长连接的例子
package com.netty.longConnection; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler; /**
* Description: gradle03
* Created by lenovo on 2019/4/18 15:37
*/
public class MyServer {
public static void main (String[] args) throws InterruptedException {
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup(); ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup,workGroup).channel(NioServerSocketChannel.class).
handler(new LoggingHandler(LogLevel.INFO)).
childHandler(new MyServletInitializer()); ChannelFuture channelFuture = serverBootstrap.bind().sync();
channelFuture.channel().close().sync(); /* bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();*/
}
}
Myserver
package com.netty.longConnection; import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.timeout.IdleStateHandler; import java.util.concurrent.TimeUnit; /**
* Description: gradle03
* Created by lenovo on 2019/4/18 15:41
*/
public class MyServletInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new IdleStateHandler(,,, TimeUnit.SECONDS)); pipeline.addLast(new MyServerHandler());
}
}
MyServerinitializer
package com.netty.longConnection; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.timeout.IdleStateEvent; /**
* Description: gradle03
* Created by lenovo on 2019/4/18 15:48
*/
public class MyServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
super.userEventTriggered(ctx, evt); if (evt instanceof IdleStateEvent){
IdleStateEvent event = (IdleStateEvent) evt; String eventType = null;
switch (event.state()){
case READER_IDLE:
eventType="读空闲";
case WRITER_IDLE:
eventType="写空闲";
case ALL_IDLE:
eventType="读写空闲";
break;
} System.out.println(ctx.channel().remoteAddress()+"超时事件"+eventType);
ctx.channel().close();
}
}
}
MyServerhandler
netty实现服务端与客户端的长联通通信
<%--
Created by IntelliJ IDEA.
User: lenovo
Date: //
Time: :
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>webSocket客户端</title>
<script>
var socket;
if(window.WebSocket){
socket= new WebSocket("ws://localhost:8899/ws");
socket.onmessage = function (event) {
var ta = document.getElementById("responseText");
ta.value = ta.value+"\n"+event.data; }
socket.onopen = function (event) {
var ta = document.getElementById("responseText");
ta.value="连接开启"; }
socket.onclose= function (event) {
var ta = document.getElementById("responseText");
ta.value = ta.value+"\n"+"连接关闭";
} }else {
alert("浏览器不支持websocket");
}
function send(message) {
if(!window.WebSocket){
return;
}if(socket.readyState == WebSocket.OPEN){
socket.send(message);
}else {
alert("连接尚未开启")
}
} </script>
</head>
<body> <form onsubmit="false">
<textarea name="message" style="width: 400px; height: 200px"></textarea> <input type="button" value="发送数据" onclick="send(this.form.message.value)"> <h3>服务端输出:</h3>
<textarea id="responseText" style="width: 400px; height: 300px;"></textarea> <input type="button" onclick="javascript:document.getElementById('responseText').value=''" value="清空内容"> </form> </body>
</html>
index.jsp
package com.netty.ServerSocke; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler; /**
* Description: gradle03
* Created by lenovo on 2019/4/18 16:38
*/
public class MyServer {
public static void main (String[] args) throws InterruptedException {
NioEventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup(); ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup,workGroup).channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO)).childHandler(new MyServerInitializer());
ChannelFuture channelFuture = serverBootstrap.bind("localhost", ).sync(); /* channelFuture.channel().close().sync();
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();*/ }
}
MyServlet
package com.netty.ServerSocke; import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler; /**
* Description: gradle03
* Created by lenovo on 2019/4/18 16:43
*/
public class MyServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast( new HttpServerCodec());
pipeline.addLast(new ChunkedWriteHandler());
pipeline.addLast(new HttpObjectAggregator());
pipeline.addLast(new WebSocketServerProtocolHandler("/ws")); pipeline.addLast(new MyServerhandler());
}
}
MyServerInitializer
package com.netty.ServerSocke; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; import java.time.LocalDateTime; /**
* Description: gradle03
* Created by lenovo on 2019/4/18 17:13
*/
public class MyServerhandler extends SimpleChannelInboundHandler<TextWebSocketFrame> { @Override
protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
System.out.println("收到消息"+msg.text());
ctx.channel().writeAndFlush(new TextWebSocketFrame("服务事件"+ LocalDateTime.now())); } @Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
super.handlerAdded(ctx);
System.out.println("handlerAdded"+ctx.channel().id());
} @Override
public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
super.handlerRemoved(ctx); System.out.println("handlerremove"+ctx.channel().id().asLongText());
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
super.exceptionCaught(ctx, cause);
System.out.println("异常发生exceptionCaught");
ctx.close(); }
}
MyServerHandler
下载protobuf
Protocol Buffer 简称 ProtoBuf 是用于结构化数据串行化的灵活、高效、自动的方法,又如 XML,不过它更小、更快、也更简单。你可以定义自己的数据结构,然后使用代码生成器生成的代码来读写这个数据结构。你甚至可以在无需重新部署程序的情况下更新数据结构
网址(https://github.com/protocolbuffers/protobuf/releases/tag/v3.7.1)
二选一
下载成功了之后别忘了在你的环境变量中进行配置。
选择你对应的版本
在google中去寻找你的jar包
https://search.maven.org/artifact/com.google.protobuf/protobuf-java/3.7.1/bundle
不过好像不能复制,我只能手写了
'com.google.protobuf:protobuf-java:3.7.1'
com.google.protobuf:protobuf-java-util:3.7.1
在idea中使用protobef 也是花费了我一番力气,首先毋庸置疑先安装插件
此时我创建的Student.proto文件的图标应该发生变化的但是没有发生变化
尝试另外一种解决方案
这下就发生了变化
详细讲解配置文件的连接(https://www.meiwen.com.cn/subject/chzzcxtx.html)
syntax = "proto2";
package cn.edu.aynu.protobuf; //可以自定义
option optimize_for = SPEED; //默认也是speed加速解析
option java_package = "cn.edu.aynu.protobuf";
option java_outer_classname = "DataInfo"; //这个名字也可以自己定义 message Student{
required string name =1; //每一个字段都有唯一标识符这些标识符是用来在消息的二进制格式中识别各个字段的,一旦开始使用就不能够再改 变
optional int32 age =2;
optional string address = 3;
}
所指定的消息字段修饰符必须是如下之一:
² required:一个格式良好的消息一定要含有1个这种字段。表示该值是必须要设置的;
² optional:消息格式中该字段可以有0个或1个值(不超过1个)。
² repeated:在一个格式良好的消息中,这种字段可以重复任意多次(包括0次)。重复的值的顺序会被保留。表示该值可以重复,相当于Java中的List。
由于一些历史原因,基本数值类型的repeated的字段并没有被尽可能地高效编码。在新的代码中,用户应该使用特殊选项[packed=true]来保证更高效的编码。如:
repeated int32 samples = 4 [packed=true]; |
required是永久性的:在将一个字段标识为required的时候,应该特别小心。如果在某些情况下不想写入或者发送一个required的 字段,将原始该字段修饰符更改为optional可能会遇到问题——旧版本的使用者会认为不含该字段的消息是不完整的,从而可能会无目的的拒绝解析。在这 种情况下,你应该考虑编写特别针对于应用程序的、自定义的消息校验函数。Google的一些工程师得出了一个结论:使用required弊多于利;他们更 愿意使用optional和repeated而不是required。当然,这个观点并不具有普遍性。
在终端上输入命令
表示在protoc --java_out= src/mian/java 这个目录下生成代码,源文件在
src/protobuf/Student.proto 目录下。
这里出现了一个小问题我再斜着跳语句的时候
E:\sturts2\gradle05-project>protoc --java_out = src/main/java src/protobuf/Student.proto
src/main/java: Permission denied
我查了很多,但是网上几乎没有人遇到过这个问题,根本搜不到后来我又敲了一遍
E:\sturts2\gradle05-project>protoc --java_out=src/main/java src/protobuf/Student.proto
发现问题了吧,对就是空格,= 好前后的空格。把前后的空格去掉就执行成功了。
需要指出的是,你绝对不能修改生成的DataInfo 这个文件,因为现在我们还不具备修改这个文件的个水平。
新建一个java类
package cn.edu.aynu.protobuf; import com.google.protobuf.InvalidProtocolBufferException; /**
* Description: gradle05
* Created by lenovo on 2019/4/19 17:26
*/
public class ProobufTest {
public static void main (String[] args) throws InvalidProtocolBufferException {
DataInfo.Student student = DataInfo.Student.newBuilder().setName("张三").
setAge().setAddress("北京").build(); //先构建一个java对象 byte[] bytes = student.toByteArray(); //将java对象转换为一个字节数组
DataInfo.Student student1 = DataInfo.Student.parseFrom(bytes);//从字节数组中将java对象的信息给恢复过来 System.out.println(student1.getAddress());
System.out.println(student1.getName());
System.out.println(student1.getAge()); }
}
protobufTest
执行结果
我再执行下一个程序的时候遇到了一个错误
com.google.protobuf.InvalidProtocolBufferException: While parsing a protocol message, the input ende
或者是无法远程连接
我的原因是我写错了一个关闭
应该写成 channelFuture.channel().closeFuture().sync();
结果写成了 channelFuture.channel().close().sync();
所以就导致了上面的两个问题,如果你将下面连个注释掉虽然服务不会停但是当你启动客户端的时候就会发生 连接被拒绝,没有远程服务
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
下面粘上我正确的代码
package cn.edu.aynu.netty; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler; /**
* Description: gradle05
* Created by lenovo on 2019/4/19 17:50
*/
public class MyServer {
public static void main (String[] args) throws InterruptedException { /*同理首先要构建事件*/
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup(); ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup,workGroup).channel(NioServerSocketChannel.class).
handler(new LoggingHandler(LogLevel.INFO)).
childHandler(new ServerInitializer()); // 绑定端口后
ChannelFuture channelFuture = serverBootstrap.bind().sync();
// 关闭端口
channelFuture.channel().closeFuture().sync();
/* channelFuture.channel().close().sync();*/ //关闭两个线程
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
MyServer
package cn.edu.aynu.netty; import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; /**
* Description: gradle05
* Created by lenovo on 2019/4/19 17:55
*/
public class ServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ProtobufVarint32FrameDecoder()); pipeline.addLast(new ProtobufDecoder(DataInfo.Student.getDefaultInstance()));//解码器把字节数组转换为真正的对象
pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
pipeline.addLast(new ProtobufEncoder());
pipeline.addLast(new MyServerHandler());
}
}
MyServerInitializer
package cn.edu.aynu.netty; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; /**
* Description: gradle05
* Created by lenovo on 2019/4/19 17:59
*/
public class MyServerHandler extends SimpleChannelInboundHandler<DataInfo.Student> { @Override
protected void channelRead0(ChannelHandlerContext ctx, DataInfo.Student msg) throws Exception {
System.out.println(msg.getAddress());
System.out.println(msg.getAge());
System.out.println(msg.getName());
}
}
MyServerHandler
客户端
package cn.edu.aynu.netty; import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader; /**
* Description: gradle05
* Created by lenovo on 2019/4/19 18:07
*/
public class MyClient {
public static void main (String[] args) throws IOException, InterruptedException {
NioEventLoopGroup eventExecutors = new NioEventLoopGroup(); try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventExecutors).channel(NioSocketChannel.class).handler(new MyClientInitializer());
ChannelFuture channelFuture = bootstrap.connect("localhost", ).sync();
channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) {
e.printStackTrace();
} finally {
eventExecutors.shutdownGracefully();
}
} }
MyClient
package cn.edu.aynu.netty; import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; /**
* Description: gradle05
* Created by lenovo on 2019/4/19 18:15
*/
public class MyClientInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ProtobufVarint32FrameDecoder()); pipeline.addLast(new ProtobufDecoder(DataInfo.Student.getDefaultInstance()));//解码器把字节数组转换为真正的对象
pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
pipeline.addLast(new ProtobufEncoder()); pipeline.addLast(new MyClientHandler());
}
}
MyClientInitializer
package cn.edu.aynu.netty; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; /**
* Description: gradle05
* Created by lenovo on 2019/4/19 18:15
*/
public class MyClientHandler extends SimpleChannelInboundHandler<DataInfo.Student> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, DataInfo.Student msg) throws Exception { } @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx);
DataInfo.Student student1 = DataInfo.Student.newBuilder().setName("张三").setAddress("背景").setAge().build();
ctx.channel().writeAndFlush(student1); }
}
MyClientHandler
syntax = "proto2";
package cn.edu.aynu.protobuf; //可以自定义
option optimize_for = SPEED; //默认也是speed加速解析
option java_package = "cn.edu.aynu.netty";
option java_outer_classname = "DataInfo"; message Student{
required string name =; //每一个字段都有唯一标识符
optional int32 age =;
optional string address = ;
}
Student.propo
多协议消息支援
syntax = "proto2";
package cn.edu.aynu.protobuf; //可以自定义
option optimize_for = SPEED; //默认也是speed加速解析
option java_package = "cn.edu.aynu.netty";
option java_outer_classname = "DataInfo"; message MyMessage{
enum DataType{
StudentType =;
DogType =;
CatType =;
}
required DataType data_type = ;
oneof dataBody{
Student student =;
Dog dog =;
Cat cat =;
}
} message Dog{
optional string name =;
optional int32 age =;
} message Cat{
optional string name =;
optional int32 age =;
} message Student{
required string name =; //每一个字段都有唯一标识符
optional int32 age =;
optional string address = ;
}
Student.propo
package cn.edu.aynu.netty; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler; /**
* Description: gradle05
* Created by lenovo on 2019/4/19 17:50
*/
public class MyServer {
public static void main (String[] args) throws InterruptedException { /*同理首先要构建事件*/
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workGroup = new NioEventLoopGroup(); ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup,workGroup).channel(NioServerSocketChannel.class).
handler(new LoggingHandler(LogLevel.INFO)).
childHandler(new ServerInitializer()); // 绑定端口后
ChannelFuture channelFuture = serverBootstrap.bind().sync();
// 关闭端口
channelFuture.channel().closeFuture().sync();
/* channelFuture.channel().close().sync();*/ //关闭两个线程
bossGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
MyServer
package cn.edu.aynu.netty; import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; /**
* Description: gradle05
* Created by lenovo on 2019/4/19 17:55
*/
public class ServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ProtobufVarint32FrameDecoder()); pipeline.addLast(new ProtobufDecoder(DataInfo.MyMessage.getDefaultInstance()));//解码器把字节数组转换为真正的对象
pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
pipeline.addLast(new ProtobufEncoder());
pipeline.addLast(new MyServerHandler());
}
}
MyServerInitializer
package cn.edu.aynu.netty; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; /**
* Description: gradle05
* Created by lenovo on 2019/4/19 17:59
*/
public class MyServerHandler extends SimpleChannelInboundHandler<DataInfo.MyMessage> { @Override
protected void channelRead0(ChannelHandlerContext ctx, DataInfo.MyMessage msg) throws Exception {
DataInfo.MyMessage.DataType dataType = msg.getDataType();
if (dataType == DataInfo.MyMessage.DataType.StudentType){
DataInfo.Student student = msg.getStudent();
System.out.println(student.getAddress());
System.out.println(student.getAge());
System.out.println(student.getName());
}else if(dataType == DataInfo.MyMessage.DataType.DogType){
DataInfo.Dog dog = msg.getDog(); System.out.println(dog.getName());
System.out.println(dog.getAge());
}else{
DataInfo.Cat cat = msg.getCat();
System.out.println(cat.getName());
System.out.println(cat.getAge());
} }
}
MyServerHandler
client
package cn.edu.aynu.netty; import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel; import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader; /**
* Description: gradle05
* Created by lenovo on 2019/4/19 18:07
*/
public class MyClient {
public static void main (String[] args) throws IOException, InterruptedException {
NioEventLoopGroup eventExecutors = new NioEventLoopGroup(); try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(eventExecutors).channel(NioSocketChannel.class).handler(new MyClientInitializer());
ChannelFuture channelFuture = bootstrap.connect("localhost", ).sync();
channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) {
e.printStackTrace();
} finally {
eventExecutors.shutdownGracefully();
}
} }
MyClientServer
package cn.edu.aynu.netty; import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender; /**
* Description: gradle05
* Created by lenovo on 2019/4/19 18:15
*/
public class MyClientInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ProtobufVarint32FrameDecoder()); pipeline.addLast(new ProtobufDecoder(DataInfo.MyMessage.getDefaultInstance()));//解码器把字节数组转换为真正的对象
pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());
pipeline.addLast(new ProtobufEncoder()); pipeline.addLast(new MyClientHandler());
}
}
MyClientInitializer
package cn.edu.aynu.netty; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler; import java.util.Random; /**
* Description: gradle05
* Created by lenovo on 2019/4/19 18:15
*/
public class MyClientHandler extends SimpleChannelInboundHandler<DataInfo.MyMessage> {
@Override
protected void channelRead0(ChannelHandlerContext ctx, DataInfo.MyMessage msg) throws Exception { } @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
super.channelActive(ctx); DataInfo.MyMessage message = null;
int randomInt = new Random().nextInt(); if (==randomInt){ message= DataInfo.MyMessage.newBuilder().
setDataType(DataInfo.MyMessage.DataType.StudentType).
setStudent(DataInfo.Student.newBuilder().
setName("张三").setAddress("背景").setAge().build()).build();
}else if(==randomInt){
message= DataInfo.MyMessage.newBuilder().
setDataType(DataInfo.MyMessage.DataType.DogType).
setDog(DataInfo.Dog.newBuilder().
setName("小汪").setAge().build()).build();
}else {
message= DataInfo.MyMessage.newBuilder().
setDataType(DataInfo.MyMessage.DataType.CatType).
setCat(DataInfo.Cat.newBuilder().
setName("小猫").setAge().build()).build();
} DataInfo.Student student1 = DataInfo.Student.newBuilder().setName("张三").setAddress("背景").setAge().build();
ctx.channel().writeAndFlush(message); }
}
MyServerHandler
接下来是apache Thrift (详细讲解可以参考 https://www.cnblogs.com/fingerboy/p/6424248.html)
简单来说,是Facebook公布的一款开源跨语言的RPC框架.
Thrift最初由Facebook开发的,后来提交给了Apache基金会将Thrift作为一个开源项目。当时facebook开发使用它是为了解决系统中各系统间大数据量的传输通信以及系统之间语言环境不同需要跨平台的特性,所以Thrift是支持跨语言,比如C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml都支持。Thrift是一个典型的CS结构,客户端和服务端可以使用不同的语言开发。既然客户端和服务端能使用不同的语言开发,那么一定就要有一种中间语言来关联客户端和服务端的语言,没错,这种语言就是IDL(Interface Description Language)。
RPC全称为Remote Procedure Call,意为远程过程调用.
假设有两台服务器A,B.A服务器上部署着一个应用a,B服务器上部署着一个应用b,现在a希望能够调用b应用的某个函数(方法),但是二者不在同一个进程内,不能直接调用,就需要通过网络传输,在AB服务器之间建一条网络传输通道,a把参数传过去,b接收到参数调用自己的方法,得到结果,再通过网络传回给a,简单讲就是A通过网络来调用B的过程.这个过程要涉及的东西很多,比如多线程,Socket,序列化反序列化,网络I/O,很复杂,于是牛掰的程序员把这些封装起来做成一套框架,供大家使用,就是RPC框架.
下载地址(http://thrift.apache.org/download),然后将下载
不会安装的可以参考这个(https://blog.csdn.net/haihaa/article/details/76577797)
在idea 下使用Gradle写一个Thrift的例子
注意图标的变化
namespace java thrift.generated typedef i16 short
typedef i32 int
typedef i64 long
typedef bool boolean
typedef string String struct Person{
:optional String username,
:optional int age,
:optional boolean married
} exception DataException{
:optional String message,
:optional String callStack,
:optional String data
} service PersonService{
Person getPersonByUsername(:required String username) throws (:DataException dataException), void savePerson(:required Person person) throws(:DataException dataException) }
data.thrift
然后再终端中运行这句话
E:\sturts2\gradle05-project>thrift --gen java src/Thrift/data.thrift
如果你在环境变量中已经配置好了,cmd命令行中也能访问到,但是在idea 中的终端上不能访问,那么你可以尝试将程序都关掉,或者将电脑重启
这时再打开就可以了。
当在idea终端总运行后会出现一个
因为生成的这个目录不在java 目录下,所以将其拷贝到java 目录下
需要导入依赖
"org.apache.thrift.:thrift-maven-plugin:0.10.0"
thrift的一个架构
package cn.edu.aynu.thrift; import com.sun.org.apache.bcel.internal.generic.NEW;
import org.apache.thrift.TProcessorFactory;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.server.THsHaServer;
import org.apache.thrift.server.TServer;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.THttpClient;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TTransportException;
import thrift.generated.PersonService; /**
* 这是服务端
*/
public class ThriftServer {
public static void main (String[] args) throws TTransportException { TNonblockingServerSocket serverSocket = new TNonblockingServerSocket();
THsHaServer.Args workerThreads = new THsHaServer.Args(serverSocket).minWorkerThreads().maxWorkerThreads(); PersonService.Processor<PersonServiceImpl> processor = new PersonService.Processor<>(new PersonServiceImpl()); workerThreads.protocolFactory(new TCompactProtocol.Factory());
workerThreads.transportFactory(new TFramedTransport.Factory());
workerThreads.processorFactory(new TProcessorFactory(processor)); TServer server = new THsHaServer(workerThreads);
System.out.println("Thrift Server Started"); //这是一个死循环
server.serve(); }
}
ThriftServer
package cn.edu.aynu.thrift; import org.apache.thrift.TException;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;
import thrift.generated.Person;
import thrift.generated.PersonService; /**
* Description: gradle05
* Created by lenovo on 2019/4/20 11:20
*/
public class ThriftClient {
public static void main (String[] args){
TTransport transport = new TFramedTransport(new TSocket("localhost",,));
TCompactProtocol protocol = new TCompactProtocol(transport); PersonService.Client client = new PersonService.Client(protocol); try {
transport.open();
Person person = client.getPersonByUsername("张三");
System.out.println(person.getAge());
System.out.println(person.getUsername());
System.out.println(person.isMarried()); System.out.println("-----------------------");
Person person1 = new Person(); person1.setUsername("李艾");
person1.setAge();
person1.setMarried(true); client.savePerson(person1); } catch (TException e) {
e.printStackTrace();
}finally {
transport.close();
} }
}
ThriftClient
package cn.edu.aynu.thrift; import org.apache.thrift.TException;
import thrift.generated.DataException;
import thrift.generated.Person;
import thrift.generated.PersonService; /**
* Description: gradle05
* Created by lenovo on 2019/4/20 10:58
*/
public class PersonServiceImpl implements PersonService.Iface { @Override
public Person getPersonByUsername(String username) throws DataException, TException {
System.out.println("Got client Param"+username);
Person person = new Person();
person.setUsername(username);
person.setAge();
person.setMarried(false); return person;
} @Override
public void savePerson(Person person) throws DataException, TException { System.out.println("Got Client Param");
System.out.println(person.getUsername());
System.out.println(person.getAge());
System.out.println(person.isMarried());
}
}
PersonServiceImpl
运行结果
当你执行 gradle wrapper
会出现3个文件
还可以在built.gradle中指定版本
这样就不需要在终端中输入命令。
Grpc 的一些了解知识
官网(https://grpc.io/docs/tutorials/basic/java.html)
https://grpc.io/docs/quickstart/java.html
Grpc与Gradle整合,我是失败了,你们可以试试,我现在先往下看,等过段时间不忙了,我再重新看一下官网把这个问题给找出来。
https://github.com/grpc/grpc-java
我这个目前是一直都不对,我先记录一下等回头再学习
下面这个例子是grpc 通信实例与JVM 回调
我上面最基本的环境都搭建不起来多以这个例子我也跑不起来,先过,看下面的例子,等我有空了再把这个部分内容补充回来
。。。。。。。。。。。。。。。。。。。。。。。
所有的有关grpc 的内容都暂且略过。
。。。。。。。。。。
1。grpc 服务器流式调用实现
2.grpc 双向流式数据通信详解
3.grpc 与Gradle 流式整合
下面就主要讲解,Gradle插件问题解决方案,与Nodejs 环境搭建
目前我是真是坚持不下去了,真的是很难啊,环境打不好,我还是先看基础的吧,能看完的都是人才啊。
Netty的基本使用的更多相关文章
- 谈谈如何使用Netty开发实现高性能的RPC服务器
RPC(Remote Procedure Call Protocol)远程过程调用协议,它是一种通过网络,从远程计算机程序上请求服务,而不必了解底层网络技术的协议.说的再直白一点,就是客户端在不必知道 ...
- 基于netty http协议栈的轻量级流程控制组件的实现
今儿个是冬至,所谓“冬大过年”,公司也应景五点钟就放大伙儿回家吃饺子喝羊肉汤了,而我本着极高的职业素养依然坚持留在公司(实则因为没饺子吃没羊肉汤喝,只能呆公司吃食堂……).趁着这一个多小时的时间,想跟 ...
- 从netty-example分析Netty组件续
上文我们从netty-example的Discard服务器端示例分析了netty的组件,今天我们从另一个简单的示例Echo客户端分析一下上个示例中没有出现的netty组件. 1. 服务端的连接处理,读 ...
- 源码分析netty服务器创建过程vs java nio服务器创建
1.Java NIO服务端创建 首先,我们通过一个时序图来看下如何创建一个NIO服务端并启动监听,接收多个客户端的连接,进行消息的异步读写. 示例代码(参考文献[2]): import java.io ...
- 从netty-example分析Netty组件
分析netty从源码开始 准备工作: 1.下载源代码:https://github.com/netty/netty.git 我下载的版本为4.1 2. eclipse导入maven工程. netty提 ...
- Netty实现高性能RPC服务器优化篇之消息序列化
在本人写的前一篇文章中,谈及有关如何利用Netty开发实现,高性能RPC服务器的一些设计思路.设计原理,以及具体的实现方案(具体参见:谈谈如何使用Netty开发实现高性能的RPC服务器).在文章的最后 ...
- Netty构建分布式消息队列(AvatarMQ)设计指南之架构篇
目前业界流行的分布式消息队列系统(或者可以叫做消息中间件)种类繁多,比如,基于Erlang的RabbitMQ.基于Java的ActiveMQ/Apache Kafka.基于C/C++的ZeroMQ等等 ...
- 基于Netty打造RPC服务器设计经验谈
自从在园子里,发表了两篇如何基于Netty构建RPC服务器的文章:谈谈如何使用Netty开发实现高性能的RPC服务器.Netty实现高性能RPC服务器优化篇之消息序列化 之后,收到了很多同行.园友们热 ...
- Netty构建分布式消息队列实现原理浅析
在本人的上一篇博客文章:Netty构建分布式消息队列(AvatarMQ)设计指南之架构篇 中,重点向大家介绍了AvatarMQ主要构成模块以及目前存在的优缺点.最后以一个生产者.消费者传递消息的例子, ...
- JAVA通信系列三:Netty入门总结
一.Netty学习资料 书籍<Netty In Action中文版> 对于Netty的十一个疑问http://news.cnblogs.com/n/205413/ 深入浅出Nettyhtt ...
随机推荐
- [开发技巧]·HTML检测输入已完成自动填写下一个内容
[开发技巧]·HTML检测输入已完成自动填写下一个内容 个人网站 --> http://www.yansongsong.cn 在上一个博客中简易实现检测输入已完成,我们实现了检测输入已完成,现在 ...
- 图像检索(6):局部敏感哈希索引(LSH)
图像检索中,对一幅图像编码后的向量的维度是很高.以VLAD为例,基于SIFT特征点,设视觉词汇表的大小为256,那么一幅图像编码后的VLAD向量的长度为$128 \times 256 = 32768 ...
- Java并发编程系列-AbstractQueuedSynchronizer
原创作品,可以转载,但是请标注出处地址:https://www.cnblogs.com/V1haoge/p/10566625.html 一.概述 AbstractQueuedSynchronizer简 ...
- 在线生成二维码的API接口
现在很多大网站都有这样的一个功能,使用手机扫描一下网页上的二维码便可快速在手机上访问网站.想要实现这样的功能其实很简单,下面麦布分享几个在线生成网址二维码的API接口.都是采用http协议接口,无需下 ...
- Jquer + Ajax 制作上传图片文件
没什么 说的 直接 上代码 //选择图片并上传 function selectImg(node){ var f = node.value; var file = node.files[0]; if( ...
- 数据结构——Java实现顺序栈
一.分析 栈是限定仅在表的一端进行插入或删除操作的线性表,对于栈来说,操作端称为栈顶,另一端则称为栈底,栈的修改是按照后进先出的原则进行的,因此又称为后进先出的线性表. 顺序栈是指利用顺序存储结构实现 ...
- while死循环导致的内存溢出
场景:新开发的功能内测,新调用了其它模块的接口,一如既往的点鼠标,计费,但是许久都没有响应页面遮罩一直锁着,最后抛出了以下异常 咋一看这个异常信息,不就是锁表了吗?把锁表进程Kill掉,再来一遍,结果 ...
- Java建造者模式
建造者模式 建造者模式适用场景: 建造一个复杂的对象适用,将构建对象的过程分开,每个类单独构造对象的一部分,最后组装起来,返回我们需要的对象. 下面的例子主要讲解构造一个飞船 Demo: //要获得的 ...
- 1.4 GPU分析
shader 加宏 编译说明glsl
- Snapde和常用的CSV文件编辑器对比
Snapde,一个专门为编辑超大型数据量CSV文件而设计的单机版电子表格软件:它运行的速度非常快,反应非常灵敏. CSV是一种用逗号分隔列.回车分割行的文本文件,市面上常用的CSV编辑软件有:Snap ...