Gradle 的優勢 原文:https://blog.csdn.net/achenyuan/article/details/80682288 javascript
1. 按約定聲明構建和建設;
2. 強大的支持多工程的構建;
3. 強大的依賴管理(基於Apache Ivy),提供最大的便利去構建工程;
4. 全力支持已有的 Maven 或者Ivy倉庫基礎建設;
5. 支持傳遞性依賴管理,在不須要遠程倉庫和pom.xml和ivy配置文件的前提下;
6. 基於groovy腳本構建,其build腳本使用groovy語言編寫;
7. 具備普遍的領域模型支持構建;
8. 深度 API;
9. 易遷移;
10. 自由和開放源碼,Gradle是一個開源項目,基於 ASL 許可。php
下面是Gradle 基本配置的簡介
build.gradle (做用相似於 maven 中的epom 文件)html
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' }
原文位置(http://www.javashuo.com/article/p-kybxzkni-kr.html)java
目錄文件 | 做用 |
---|---|
.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 項目的子項目包含文件 |
gitignore 該文件是源碼管理的配置文件,不在該文講解。node
既然gradle 是多 module形式,那麼咱們來看看 setting.gradle 配置的內容python
rootProject.name = 'gradle'
從上面目錄的配置文件內容來看,整個project也算是一個module,若是改module底下還有module,就能夠經過setting.gradle配置進來,使得該module底下的gradle,從app module底下能夠看出,module最少要含有 build.gradle文件,這個module的項目編譯文件,該module依賴什麼插件對該目錄進行編譯都在此配置,好比android與android-library,其餘內容可繼承父類的linux
一樣maven項目須要依賴,Gradle也須要jar包android
可是Gradle的jar包去哪裏找呢 根據Build.Gradle 已經指出來了git
repositories {
mavenCentral() maven中心倉庫
}
網址是https://search.maven.org/ 使用搜狗瀏覽器個人打不開,因此我使用了谷歌程序員
裏面有一個jar包是將netty全部的jar包都包含了
我都拷貝出來吧
maven版本下的 還不讓我copy
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <veresion>5.0.0.Alpha2<version> </dependency>
'io.netty:netty-all:4.1.34.Final'
E:\sturts2\gradle03-projext>gradle clean build BUILD SUCCESSFUL in 12s 2 actionable tasks: 2 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(8899).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(8899).sync(); bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } }
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(4096, Delimiters.lineDelimiter())); pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); pipeline.addLast("testHttpServletHandler",new MyChatServerHandler()); } }
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(); } }
客戶端
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",8899).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(); } } }
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(4096, Delimiters.lineDelimiter())); pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8)); pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8)); pipeline.addLast("testHttpServletHandler",new MyChatClientServerHandler()); } }
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); } }
放上執行結果
前後打開了三個客戶端
下面是長鏈接的例子
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(8899).sync(); channelFuture.channel().close().sync(); /* bossGroup.shutdownGracefully(); workGroup.shutdownGracefully();*/ } }
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(5,7,10, TimeUnit.SECONDS)); pipeline.addLast(new MyServerHandler()); } }
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(); } } }
netty實現服務端與客戶端的長聯統統信
<%-- Created by IntelliJ IDEA. User: lenovo Date: 2019/4/17 Time: 18:19 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>
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", 8899).sync(); /* channelFuture.channel().close().sync(); bossGroup.shutdownGracefully(); workGroup.shutdownGracefully();*/ } }
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(8192)); pipeline.addLast(new WebSocketServerProtocolHandler("/ws")); pipeline.addLast(new MyServerhandler()); } }
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(); } }
下載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(20).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()); } }
執行結果
我再執行下一個程序的時候遇到了一個錯誤
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(8899).sync(); // 關閉端口 channelFuture.channel().closeFuture().sync(); /* channelFuture.channel().close().sync();*/ //關閉兩個線程 bossGroup.shutdownGracefully(); workGroup.shutdownGracefully(); } }
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()); } }
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()); } }
客戶端
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", 8899).sync(); channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { eventExecutors.shutdownGracefully(); } } }
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()); } }
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(23).build(); ctx.channel().writeAndFlush(student1); } }
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 =1; //每個字段都有惟一標識符 optional int32 age =2; optional string address = 3; }
多協議消息支援
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 =1; DogType =2; CatType =3; } required DataType data_type = 1; oneof dataBody{ Student student =2; Dog dog =3; Cat cat =4; } } message Dog{ optional string name =1; optional int32 age =2; } message Cat{ optional string name =1; optional int32 age =2; } message Student{ required string name =1; //每個字段都有惟一標識符 optional int32 age =2; optional string address = 3; }
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(8899).sync(); // 關閉端口 channelFuture.channel().closeFuture().sync(); /* channelFuture.channel().close().sync();*/ //關閉兩個線程 bossGroup.shutdownGracefully(); workGroup.shutdownGracefully(); } }
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()); } }
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()); } } }
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", 8899).sync(); channelFuture.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } finally { eventExecutors.shutdownGracefully(); } } }
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()); } }
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(3); if (0==randomInt){ message= DataInfo.MyMessage.newBuilder(). setDataType(DataInfo.MyMessage.DataType.StudentType). setStudent(DataInfo.Student.newBuilder(). setName("張三").setAddress("背景").setAge(23).build()).build(); }else if(1==randomInt){ message= DataInfo.MyMessage.newBuilder(). setDataType(DataInfo.MyMessage.DataType.DogType). setDog(DataInfo.Dog.newBuilder(). setName("小汪").setAge(2).build()).build(); }else { message= DataInfo.MyMessage.newBuilder(). setDataType(DataInfo.MyMessage.DataType.CatType). setCat(DataInfo.Cat.newBuilder(). setName("小貓").setAge(3).build()).build(); } DataInfo.Student student1 = DataInfo.Student.newBuilder().setName("張三").setAddress("背景").setAge(23).build(); ctx.channel().writeAndFlush(message); } }
接下來是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{ 1:optional String username, 2:optional int age, 3:optional boolean married } exception DataException{ 1:optional String message, 2:optional String callStack, 3:optional String data } service PersonService{ Person getPersonByUsername(1:required String username) throws (1:DataException dataException), void savePerson(1:required Person person) throws(1:DataException dataException) }
而後再終端中運行這句話
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(8899); THsHaServer.Args workerThreads = new THsHaServer.Args(serverSocket).minWorkerThreads(2).maxWorkerThreads(4); 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(); } }
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",8899,600)); 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(23); person1.setMarried(true); client.savePerson(person1); } catch (TException e) { e.printStackTrace(); }finally { transport.close(); } } }
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(20); 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()); } }
運行結果
當你執行 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 環境搭建
目前我是真是堅持不下去了,真的是很難啊,環境打很差,我仍是先看基礎的吧,能看完的都是人才啊。