Netty简介

Netty是由JBOSS提供的一个java开源框架,现为 Github上的独立项目。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。
也就是说,Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发。
“快速”和“简单”并不用产生维护性或性能上的问题。Netty 是一个吸收了多种协议(包括FTP、SMTP、HTTP等各种二进制文本协议)的实现经验,并经过相当精心设计的项目。最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性。

说明:本文只介绍netty框架最基本的应用,而且是每次客户端请求完毕会关闭连接,后续会写一篇客户端先与服务端建立连接,然后一条条发送数据,发送完毕主动关闭连接的博客。

Netty搭建WebSocket服务端

Netty服务端

1.引入依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>1.5.9.RELEASE</version> <!-- 我这里用的1.5.9 -->
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>com.blaze</groupId>
  12. <artifactId>netty-demo</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>netty-demo</name>
  15. <description>Demo project for Spring Boot</description>
  16.  
  17. <properties>
  18. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  19. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  20. <java.version>1.8</java.version>
  21. </properties>
  22.  
  23. <dependencies>
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  27. </dependency>
  28.  
  29. <dependency>
  30. <groupId>org.apache.commons</groupId>
  31. <artifactId>commons-lang3</artifactId>
  32. <version>3.4</version>
  33. </dependency>
  34.  
  35. <!--fastjson-->
  36. <dependency>
  37. <groupId>com.alibaba</groupId>
  38. <artifactId>fastjson</artifactId>
  39. <version>1.2.50</version>
  40. </dependency>
  41.  
  42. <!--netty依赖-->
  43. <dependency>
  44. <groupId>io.netty</groupId>
  45. <artifactId>netty-all</artifactId>
  46. <version>4.1.43.Final</version>
  47. </dependency>
  48.  
  49. </dependencies>
  50.  
  51. <build>
  52. <plugins>
  53. <plugin>
  54. <groupId>org.springframework.boot</groupId>
  55. <artifactId>spring-boot-maven-plugin</artifactId>
  56. <configuration>
  57. <mainClass>com.blaze.nettydemo.server.NettyServer</mainClass>
  58. </configuration>
  59. </plugin>
  60. </plugins>
  61. <finalName>netty-demo</finalName>
  62. </build>
  63.  
  64. </project>

2.Netty服务端

NettyServer

  1. package com.blaze.nettydemo.server;
  2.  
  3. import io.netty.bootstrap.ServerBootstrap;
  4. import io.netty.channel.ChannelFuture;
  5. import io.netty.channel.ChannelInitializer;
  6. import io.netty.channel.ChannelOption;
  7. import io.netty.channel.EventLoopGroup;
  8. import io.netty.channel.nio.NioEventLoopGroup;
  9. import io.netty.channel.socket.SocketChannel;
  10. import io.netty.channel.socket.nio.NioServerSocketChannel;
  11. import org.springframework.stereotype.Component;
  12.  
  13. /**
  14. * create by zy 2019/11/15 9:14
  15. * TODO
  16. */
  17. @Component
  18. public class NettyServer {
  19. public static void main(String[] args) {
  20. int port = 9898;
  21. new NettyServer().bind(port);
  22. }
  23.  
  24. public void bind(int port) {
  25. /**
  26. * interface EventLoopGroup extends EventExecutorGroup extends ScheduledExecutorService extends ExecutorService
  27. * 配置服务端的 NIO 线程池,用于网络事件处理,实质上他们就是 Reactor 线程组
  28. * bossGroup 用于服务端接受客户端连接,workerGroup 用于进行 SocketChannel 网络读写
  29. */
  30. EventLoopGroup bossGroup = new NioEventLoopGroup();
  31. EventLoopGroup workerGroup = new NioEventLoopGroup();
  32. try {
  33. /**
  34. * ServerBootstrap 是 Netty 用于启动 NIO 服务端的辅助启动类,用于降低开发难度
  35. */
  36. ServerBootstrap b = new ServerBootstrap();
  37. b.group(bossGroup, workerGroup)
  38. .channel(NioServerSocketChannel.class)
  39. .option(ChannelOption.SO_BACKLOG, 1024)
  40. .childHandler(new ChildChannelHandler());
  41.  
  42. /**服务器启动辅助类配置完成后,调用 bind 方法绑定监听端口,调用 sync 方法同步等待绑定操作完成*/
  43. ChannelFuture f = b.bind(port).sync();
  44.  
  45. System.out.println(Thread.currentThread().getName() + ",服务器开始监听端口,等待客户端连接.........");
  46.  
  47. /**下面会进行阻塞,等待服务器连接关闭之后 main 方法退出,程序结束*/
  48. f.channel().closeFuture().sync();
  49. } catch (InterruptedException e) {
  50. e.printStackTrace();
  51. } finally {
  52. /**优雅退出,释放线程池资源*/
  53. bossGroup.shutdownGracefully();
  54. workerGroup.shutdownGracefully();
  55. }
  56. }
  57.  
  58. /**
  59. * 初始化连接
  60. */
  61. @Component
  62. private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
  63. @Override
  64. public void initChannel(SocketChannel socketChannel) throws Exception {
  65. /**
  66. * 设置 netty 服务端的 handler
  67. */
  68. socketChannel.pipeline().addLast(new NettyServerHandler());
  69.  
  70. /**
  71. * 如果使用 netty 搭建 http 服务端,则用下面三个设置代替上面一个设置
  72. */
  73. //socketChannel.pipeline().addLast(new HttpServerCodec());// http 编解码
  74. //socketChannel.pipeline().addLast("httpAggregator", new HttpObjectAggregator(512 * 1024)); // http 消息聚合器
  75. //socketChannel.pipeline().addLast(new HttpServerHandler());
  76. }
  77. }
  78. }

NettyServerHandler

  1. package com.blaze.nettydemo.server;
  2.  
  3. import com.alibaba.fastjson.JSON;
  4. import com.blaze.nettydemo.model.RequestModel;
  5. import io.netty.buffer.ByteBuf;
  6. import io.netty.buffer.Unpooled;
  7. import io.netty.channel.ChannelHandlerContext;
  8. import io.netty.channel.ChannelInboundHandlerAdapter;
  9. import org.springframework.stereotype.Component;
  10.  
  11. /**
  12. * create by zy 2019/11/15 10:06
  13. * TODO
  14. */
  15. @Component
  16. public class NettyServerHandler extends ChannelInboundHandlerAdapter {
  17. /**
  18. * 收到客户端消息,自动触发
  19. */
  20. @Override
  21. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  22. /**
  23. * 将 msg 转为 Netty 的 ByteBuf 对象,类似 JDK 中的 java.nio.ByteBuffer,不过 ButeBuf 功能更强,更灵活
  24. */
  25. ByteBuf buf = (ByteBuf) msg;
  26. /**
  27. * readableBytes:获取缓冲区可读字节数,然后创建字节数组
  28. * 从而避免了像 java.nio.ByteBuffer 时,只能盲目的创建特定大小的字节数组,比如 1024
  29. */
  30. byte[] reg = new byte[buf.readableBytes()];
  31. /**
  32. * readBytes:将缓冲区字节数组复制到新建的 byte 数组中
  33. * 然后将字节数组转为字符串
  34. */
  35. buf.readBytes(reg);
  36. String body = new String(reg, "UTF-8");
  37. System.out.println(Thread.currentThread().getName() + ",The server receive order : " + body);
  38.  
  39. String respMsg = "I am Server, success!";
  40.  
  41. /**
  42. * 业务处理代码 此处省略
  43. * ......
  44. */
  45.  
  46. /**
  47. * 回复消息
  48. * copiedBuffer:创建一个新的缓冲区,内容为里面的参数
  49. * 通过 ChannelHandlerContext 的 write 方法将消息异步发送给客户端
  50. */
  51. ByteBuf respByteBuf = Unpooled.copiedBuffer(respMsg.getBytes());
  52. ctx.write(respByteBuf);
  53. }
  54.  
  55. @Override
  56. public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
  57. /**
  58. * flush:将消息发送队列中的消息写入到 SocketChannel 中发送给对方,为了频繁的唤醒 Selector 进行消息发送
  59. * Netty 的 write 方法并不直接将消息写如 SocketChannel 中,调用 write 只是把待发送的消息放到发送缓存数组中,再通过调用 flush
  60. * 方法,将发送缓冲区的消息全部写入到 SocketChannel 中
  61. */
  62. ctx.flush();
  63. }
  64.  
  65. @Override
  66. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  67. /**当发生异常时,关闭 ChannelHandlerContext,释放和它相关联的句柄等资源 */
  68. ctx.close();
  69.  
  70. }
  71. }

3.Netty客户端

NettyClient

  1. package com.blaze.nettydemo.client;
  2.  
  3. import io.netty.bootstrap.Bootstrap;
  4. import io.netty.channel.ChannelFuture;
  5. import io.netty.channel.ChannelInitializer;
  6. import io.netty.channel.ChannelOption;
  7. import io.netty.channel.EventLoopGroup;
  8. import io.netty.channel.nio.NioEventLoopGroup;
  9. import io.netty.channel.socket.SocketChannel;
  10. import io.netty.channel.socket.nio.NioSocketChannel;
  11. import org.springframework.stereotype.Component;
  12.  
  13. /**
  14. * create by zy 2019/11/15 10:08
  15. * TODO
  16. */
  17. @Component
  18. public class NettyClient {
  19. /**
  20. * 使用 3 个线程模拟三个客户端
  21. */
  22. public static void main(String[] args) {
  23. for (int i = 0; i < 3; i++) {
  24. new Thread(new MyThread()).start();
  25. }
  26. }
  27.  
  28. static class MyThread implements Runnable {
  29. /**服务端 ip 及端口*/
  30. @Override
  31. public void run() {
  32. connect("193.168.19.25", 9898);
  33. }
  34.  
  35. public void connect(String host, int port) {
  36. /**配置客户端 NIO 线程组/池*/
  37. EventLoopGroup group = new NioEventLoopGroup();
  38. try {
  39. /**
  40. * Bootstrap 与 ServerBootstrap 都继承(extends)于 AbstractBootstrap
  41. * 创建客户端辅助启动类,并对其配置,与服务器稍微不同,这里的 Channel 设置为 NioSocketChannel
  42. * 然后为其添加 Handler,这里直接使用匿名内部类,实现 initChannel 方法
  43. * 作用是当创建 NioSocketChannel 成功后,在进行初始化时,将它的ChannelHandler设置到ChannelPipeline中,用于处理网络I/O事件
  44. */
  45. Bootstrap b = new Bootstrap();
  46. b.group(group).channel(NioSocketChannel.class)
  47. .option(ChannelOption.TCP_NODELAY, true)
  48. .handler(new ChannelInitializer<SocketChannel>() {
  49. @Override
  50. public void initChannel(SocketChannel ch) throws Exception {
  51. ch.pipeline().addLast(new NettyClientHandler());
  52. }
  53. });
  54.  
  55. /**connect:发起异步连接操作,调用同步方法 sync 等待连接成功*/
  56. ChannelFuture channelFuture = b.connect(host, port).sync();
  57. System.out.println(Thread.currentThread().getName() + ",客户端发起异步连接..........");
  58.  
  59. /**等待客户端链路关闭*/
  60. channelFuture.channel().closeFuture().sync();
  61. } catch (InterruptedException e) {
  62. e.printStackTrace();
  63. } finally {
  64. /**优雅退出,释放NIO线程组*/
  65. group.shutdownGracefully();
  66. }
  67. }
  68.  
  69. }
  70. }

NettyClientHandler

  1. package com.blaze.nettydemo.client;
  2.  
  3. import io.netty.buffer.ByteBuf;
  4. import io.netty.buffer.Unpooled;
  5. import io.netty.channel.ChannelHandlerContext;
  6. import io.netty.channel.ChannelInboundHandlerAdapter;
  7. import org.springframework.stereotype.Component;
  8.  
  9. import java.util.logging.Logger;
  10.  
  11. /**
  12. * create by zy 2019/11/15 10:09
  13. * TODO
  14. */
  15. @Component
  16. public class NettyClientHandler extends ChannelInboundHandlerAdapter {
  17. private static final Logger logger = Logger.getLogger(NettyClientHandler.class.getName());
  18. /**
  19. * 当客户端和服务端 TCP 链路建立成功之后,Netty 的 NIO 线程会调用 channelActive 方法
  20. */
  21. @Override
  22. public void channelActive(ChannelHandlerContext ctx) throws Exception {
  23. String reqMsg = "客户端请求服务端发送的数据";
  24.  
  25. byte[] reqMsgByte = reqMsg.getBytes("UTF-8");
  26. ByteBuf reqByteBuf = Unpooled.buffer(reqMsgByte.length);
  27. /**
  28. * writeBytes:将指定的源数组的数据传输到缓冲区
  29. * 调用 ChannelHandlerContext 的 writeAndFlush 方法将消息发送给服务器
  30. */
  31. reqByteBuf.writeBytes(reqMsgByte);
  32. ctx.writeAndFlush(reqByteBuf);
  33. }
  34.  
  35. /**
  36. * 当服务端返回应答消息时,channelRead 方法被调用,从 Netty 的 ByteBuf 中读取并打印应答消息
  37. */
  38. @Override
  39. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  40. ByteBuf buf = (ByteBuf) msg;
  41. byte[] req = new byte[buf.readableBytes()];
  42. buf.readBytes(req);
  43. String body = new String(req, "UTF-8");
  44. System.out.println(Thread.currentThread().getName() + ",Server return Message:" + body);
  45. ctx.close();
  46. }
  47.  
  48. /**
  49. * 当发生异常时,打印异常 日志,释放客户端资源
  50. */
  51. @Override
  52. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  53. /**释放资源*/
  54. logger.warning("Unexpected exception from downstream : " + cause.getMessage());
  55. ctx.close();
  56.  
  57. }
  58. }

4.Netty Http服务端

NettyServer

  1. package com.blaze.nettydemo.server;
  2.  
  3. import io.netty.bootstrap.ServerBootstrap;
  4. import io.netty.channel.ChannelFuture;
  5. import io.netty.channel.ChannelInitializer;
  6. import io.netty.channel.ChannelOption;
  7. import io.netty.channel.EventLoopGroup;
  8. import io.netty.channel.nio.NioEventLoopGroup;
  9. import io.netty.channel.socket.SocketChannel;
  10. import io.netty.channel.socket.nio.NioServerSocketChannel;
  11. import io.netty.handler.codec.http.HttpObjectAggregator;
  12. import io.netty.handler.codec.http.HttpServerCodec;
  13. import org.springframework.stereotype.Component;
  14.  
  15. /**
  16. * create by zy 2019/11/15 9:14
  17. * TODO
  18. */
  19. @Component
  20. public class NettyServer {
  21. public static void main(String[] args) {
  22. int port = 9898;
  23. new NettyServer().bind(port);
  24. }
  25.  
  26. public void bind(int port) {
  27. /**
  28. * interface EventLoopGroup extends EventExecutorGroup extends ScheduledExecutorService extends ExecutorService
  29. * 配置服务端的 NIO 线程池,用于网络事件处理,实质上他们就是 Reactor 线程组
  30. * bossGroup 用于服务端接受客户端连接,workerGroup 用于进行 SocketChannel 网络读写
  31. */
  32. EventLoopGroup bossGroup = new NioEventLoopGroup();
  33. EventLoopGroup workerGroup = new NioEventLoopGroup();
  34. try {
  35. /**
  36. * ServerBootstrap 是 Netty 用于启动 NIO 服务端的辅助启动类,用于降低开发难度
  37. */
  38. ServerBootstrap b = new ServerBootstrap();
  39. b.group(bossGroup, workerGroup)
  40. .channel(NioServerSocketChannel.class)
  41. .option(ChannelOption.SO_BACKLOG, 1024)
  42. .childHandler(new ChildChannelHandler());
  43.  
  44. /**服务器启动辅助类配置完成后,调用 bind 方法绑定监听端口,调用 sync 方法同步等待绑定操作完成*/
  45. ChannelFuture f = b.bind(port).sync();
  46.  
  47. System.out.println(Thread.currentThread().getName() + ",服务器开始监听端口,等待客户端连接.........");
  48.  
  49. /**下面会进行阻塞,等待服务器连接关闭之后 main 方法退出,程序结束*/
  50. f.channel().closeFuture().sync();
  51. } catch (InterruptedException e) {
  52. e.printStackTrace();
  53. } finally {
  54. /**优雅退出,释放线程池资源*/
  55. bossGroup.shutdownGracefully();
  56. workerGroup.shutdownGracefully();
  57. }
  58. }
  59.  
  60. /**
  61. * 初始化连接
  62. */
  63. @Component
  64. private class ChildChannelHandler extends ChannelInitializer<SocketChannel> {
  65. @Override
  66. public void initChannel(SocketChannel socketChannel) throws Exception {
  67. /**
  68. * 设置 netty 服务端的 handler
  69. */
  70. //socketChannel.pipeline().addLast(new NettyServerHandler());
  71.  
  72. /**
  73. * 如果使用 netty 搭建 http 服务端,则用下面三个设置代替上面一个设置
  74. */
  75. socketChannel.pipeline().addLast(new HttpServerCodec());// http 编解码
  76. socketChannel.pipeline().addLast("httpAggregator", new HttpObjectAggregator(512 * 1024)); // http 消息聚合器
  77. socketChannel.pipeline().addLast(new HttpServerHandler());
  78. }
  79. }
  80. }

HttpServerHandler

  1. package com.blaze.nettydemo.server;
  2.  
  3. import com.alibaba.fastjson.JSONObject;
  4. import io.netty.buffer.ByteBuf;
  5. import io.netty.buffer.Unpooled;
  6. import io.netty.channel.ChannelFutureListener;
  7. import io.netty.channel.ChannelHandlerContext;
  8. import io.netty.channel.ChannelInboundHandlerAdapter;
  9. import io.netty.handler.codec.http.*;
  10. import io.netty.util.CharsetUtil;
  11. import org.springframework.stereotype.Component;
  12.  
  13. /**
  14. * create by zy 2019/11/19 9:21
  15. * TODO
  16. */
  17. @Component
  18. public class HttpServerHandler extends ChannelInboundHandlerAdapter {
  19.  
  20. @Override
  21. public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  22.  
  23. if (msg instanceof FullHttpRequest) {
  24. FullHttpRequest req = (FullHttpRequest) msg;
  25.  
  26. try {
  27. // 1.获取URI
  28. String uri = req.uri();
  29. System.out.println("uri:" + uri);
  30. // 2.获取请求体
  31. ByteBuf buf = req.content();
  32. String content = buf.toString(CharsetUtil.UTF_8);
  33.  
  34. // 3.根据请求的方法uri不同处理不同的逻辑
  35. Object rc = new Object();
  36. switch (uri) {
  37. case "/test1":
  38. // ......
  39. break;
  40. case "/ltest2":
  41. // ......
  42. break;
  43. default:
  44. break;
  45. }
  46. // 4.返回结果
  47. response(ctx, rc);
  48. } finally {
  49. req.release();
  50. }
  51. }
  52. }
  53.  
  54. private void response(ChannelHandlerContext ctx, Object c) {
  55.  
  56. // 1.设置响应
  57. FullHttpResponse resp = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
  58. HttpResponseStatus.OK,
  59. Unpooled.copiedBuffer(JSONObject.toJSONString(c), CharsetUtil.UTF_8));
  60. resp.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/html; charset=UTF-8");
  61. // 2.发送
  62. // 注意必须在使用完之后,close channel
  63. ctx.writeAndFlush(resp).addListener(ChannelFutureListener.CLOSE);
  64. }
  65. }

Http客户端,使用postman请求服务端进行测试即可。

本文参考:https://blog.csdn.net/wangmx1993328/article/details/83036285

Netty搭建服务端的简单应用的更多相关文章

  1. Netty入门系列(1) --使用Netty搭建服务端和客户端

    引言 前面我们介绍了网络一些基本的概念,虽然说这些很难吧,但是至少要做到理解吧.有了之前的基础,我们来正式揭开Netty这神秘的面纱就会简单很多. 服务端 public class PrintServ ...

  2. CAS 5.1.x 的搭建和使用(二)—— 通过Overlay搭建服务端-其它配置说明

    CAS单点登录系列: CAS 5.1.x 的搭建和使用(一)—— 通过Overlay搭建服务端 CAS5.1.x 的搭建和使用(二)—— 通过Overlay搭建服务端-其它配置说明 CAS5.1.x ...

  3. CAS 5.1.x 的搭建和使用(一)—— 通过Overlay搭建服务端

    CAS单点登录系列: CAS 5.1.x 的搭建和使用(一)—— 通过Overlay搭建服务端 CAS5.1.x 的搭建和使用(二)—— 通过Overlay搭建服务端-其它配置说明 CAS5.1.x ...

  4. 原理剖析-Netty之服务端启动工作原理分析(下)

    一.大致介绍 1.由于篇幅过长难以发布,所以本章节接着上一节来的,上一章节为[原理剖析(第 010 篇)Netty之服务端启动工作原理分析(上)]: 2.那么本章节就继续分析Netty的服务端启动,分 ...

  5. 原理剖析-Netty之服务端启动工作原理分析(上)

    一.大致介绍 1.Netty这个词,对于熟悉并发的童鞋一点都不陌生,它是一个异步事件驱动型的网络通信框架: 2.使用Netty不需要我们关注过多NIO的API操作,简简单单的使用即可,非常方便,开发门 ...

  6. Netty实现服务端客户端长连接通讯及心跳检测

    通过netty实现服务端与客户端的长连接通讯,及心跳检测.        基本思路:netty服务端通过一个Map保存所有连接上来的客户端SocketChannel,客户端的Id作为Map的key.每 ...

  7. 使用Apache MINA框架搭建服务端

    使用MINA框架搭建服务端步骤: 1.定义一个启动服务的类MinaServer,并实现接口ServletContextListener 2.定义一个处理业务逻辑的类MinaServerHandler, ...

  8. Netty实现客户端和服务端通信简单例子

    Netty是建立在NIO基础之上,Netty在NIO之上又提供了更高层次的抽象. 在Netty里面,Accept连接可以使用单独的线程池去处理,读写操作又是另外的线程池来处理. Accept连接和读写 ...

  9. 【转】C# client 与java netty 服务端的简单通信,客户端采用Unity

    http://blog.csdn.net/wilsonke/article/details/24721057 近日根据官方提供的通信例子自己写了一个关于Unity(C#)和后台通信的类,拿出来和大家分 ...

随机推荐

  1. C/C++查漏补缺(常更)

    一.#define宏定义 如下程序段,则输出结果为: #define MAX 12 int main(){ cout << "20\0MAX019" << ...

  2. 解决jdk卸载出错2502、2503

    之前装的jdk1.6,后来软件要求用1.8,就卸载了1.6,卸载的时候出现了这个问题.后来又有其他软件用1.8出错,就又要装1.6,脑壳疼.网上建议先卸载1.8再装低版本,结果卸载1.8,又出现错误2 ...

  3. python 列表List - python基础入门(13)

    列表是python开发过程中最常用的数据类型之一,列表俗称:list ,特点如下: 1.列表由一个或者多个数据构成,数据的类型可以不相同也可以相同: 2.列表中的数据需要写在[]中括号内部,数据与数据 ...

  4. TypeScript 高级类型 接口(interface)

    在代码的实现或者调用上能设定一定的限制和规范,就像契约一样.通常,我们把这种契约称为接口. TypeScript的核心原则之一是对值所具有的结构进行类型检查. 有时称为“鸭式辨型法”或“结构性子类型化 ...

  5. java输入输出 -- I/O模型简述

    一.简介 本文向大家介绍五种I/O模型.分别是阻塞I/O.非阻塞I/O.I/O复用.信号驱动式I/O.异步I/O等.内容参考<UNIX网络编程>,大家想进深入学习网络编程,建议去读读这本书 ...

  6. Hystrix(下),使用公共降级类

    使用Hystrix熔断(下) 在一个分布式系统里,一个服务依赖多个服务,可能存在某个服务调用失败,         比如超时.异常等,如何能够保证在一个依赖出问题的情况下,不会导致整体服务失败,   ...

  7. Idea中一个服务按多个端口同时启动

    1.勾选并行启动 2.-Dserver.port=9018

  8. Linux文件删除,但是df -hT之后磁盘空间没有释放

    Linux 磁盘空间总是报警,查到到大文件,删除之后,df看到磁盘空间并没有释放. 查找了下发现系统对rm进行了alias   ,因为Linux对删除操作没有回收站机制,对rm操作进行了自定义,对删除 ...

  9. qt翻译和国际化的探讨。

    这段时间一直都在怼qt的国际化,以前也接触过国际化,但是感觉不是那么的深刻,这次是因为一个项目要做一个国际化的版本,代码里面是不能出现中文的,所以就翻译了一下.qt用的是4.8.6 64位的,IDE( ...

  10. css中字体常用单位px、em、rem和%的区别及用法总结

    一.px.em.rem和%的定义 1.px(像素) px单位的名称为像素,它是一个固定大小的单元,像素的计算是针对(电脑/手机)屏幕的,一个像素(1px)就是(电脑/手机)屏幕上的一个点,即屏幕分辨率 ...