大云梦

大云梦 查看完整档案

北京编辑北京工业大学  |  计算机 编辑  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

大云梦 发布了文章 · 9月14日

代理类生成到本地小妙招

背景

使用动态代理生成的实例,我们一般是没办法看到的,如果我们想研究动态代理的原理的话,还是要看一下这个动态代理实例的代码的,我们可以这样做,直接上代码

// 代理类
IBuyHouse instance = new IntermediaryProxy().instance(new Homeowner());
try {
    
    // 将代理类转化成字节码数组,然后输出到本地 ,通过jad反编译class文件 (或者直接通过idea 打开class文件)
 byte[] bytes = ProxyGenerator.generateProxyClass(instance.getClass().getSimpleName(), instance.getClass().getInterfaces());
 FileOutputStream fileOutputStream = new FileOutputStream("C:UsersDesktopproxy$Proxy0.class");
 fileOutputStream.write(bytes);
 fileOutputStream.flush();
 fileOutputStream.close();
}catch (Exception e){
    e.printStackTrace();
}

jad反编译工具下载地址:jad

查看原文

赞 0 收藏 0 评论 0

大云梦 发布了文章 · 9月14日

java创建对象的五中方式

一:创建一个测试实体

public class Hello implements Cloneable, Serializable {
    public Hello() {
    }
    public void hello() {
        System.out.println("hello world");
 }
} 

二:创建对象

// 方式一:通过new创建

Hello hello1 = new Hello();
hello1.hello();

//方式二:通过class类的newInstance 方式创建
try {
    Class<?> aClass = Class.forName("com.albb.test.entity.Hello");
 Hello hello2 = (Hello) aClass.newInstance();
 hello2.hello();
} catch (Exception e) {
    e.printStackTrace();
}

// 方式三:通过constructor newInstance方式创建
try {
    Class<?> aClass1 = Class.forName("com.albb.test.entity.Hello");
 Constructor<?> constructor = aClass1.getConstructor();
 Hello hello3 = (Hello) constructor.newInstance();
 hello3.hello();
} catch (Exception e) {
    e.printStackTrace();
}

// 方式四:通过clone创建
try {
    Hello h1 = new Hello();
 Hello h2 = (Hello)h1.clone();
 h2.hello();
} catch (Exception e) {
    e.printStackTrace();
}
// 方式五: 通过序列化创建

//把内存中对象的状态转换为字节码的形式
//把字节码通过IO输出流,写到磁盘上
//永久保存下来,持久化
//反序列化
//将持久化的字节码内容,通过IO输入流读到内存中来
//转化成一个Java对象

Hello hello = new Hello();
File file = new File("hello-serializable");
try {
    FileOutputStream fileOutputStream = new FileOutputStream(file);
 ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);
 FileInputStream fileInputStream = new FileInputStream(file);
 ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);
 objectOutputStream.writeObject(hello);
 Hello h = (Hello) objectInputStream.readObject();
 h.hello();
} catch (Exception e) {
    e.printStackTrace();
}
查看原文

赞 0 收藏 0 评论 0

大云梦 发布了文章 · 9月13日

设计模式-代理模式

代理模式定义

代理模式 是指为其他对象提供一种代理,以控制对这个对象的访问

静态代理模式

demo:大部分的房主会把房子交给中介去出租,那么这个场景就是房主是真实类,中介是代理类(帮助房主出租房子),直接上代码

顶层接口

public interface IBuyHouse {

void renting();  

}

房主

public class Homeowner implements IBuyHouse {  
    @Override  
 public void renting() {  
        System.out.println("customer: i want to buy house");  
 }  
}

中介

public class IntermediaryProxy implements IBuyHouse {  
  
    private IBuyHouse iBuyHouse;  
  
 public IntermediaryProxy(IBuyHouse iBuyHouse) {  
        this.iBuyHouse = iBuyHouse;  
 }  
  
    @Override  
 public void renting() {  
        before();  
        iBuyHouse.renting();  
        after();  
 }  
  
    private void before() {  
        System.out.println("中介和客户沟通 ,要找一个什么样的房子");  
  
 }  
    private void after() {  
        System.out.println("达成协议,交定金");  
 }  
}

测试

public static void main(String[] args) {  
    IBuyHouse iBuyHouse = new IntermediaryProxy(new Homeowner());  
 iBuyHouse.renting();  
}

这样就完成了一个代理类的调用
接下来我们,我们看看如何实现动态代理

动态代理(java)

中介(代理类)

public class IntermediaryProxy implements InvocationHandler {  
  
    private IBuyHouse target;  
 public IBuyHouse instance(IBuyHouse target){  
        this.target = target;  
 Class<? extends IBuyHouse> aClass = target.getClass();  
 return (IBuyHouse) Proxy.newProxyInstance(aClass.getClassLoader(), aClass.getInterfaces(), this);  
 }  
  
    @Override  
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
        before();  
 Object invoke = method.invoke(this.target, args);  
 after();  
 return invoke;  
 }  
  
    private void before() {  
        System.out.println("中介和客户沟通 ,要找一个什么样的房子");  
  
 }  
  
    private void after() {  
        System.out.println("达成协议,交定金");  
 }  
  
}
// 调用
public static void main(String[] args) {  
    IBuyHouse instance = new IntermediaryProxy().instance(new Homeowner());  
 instance.renting();  
}

通过Proxy.newProxyInstance(...)创建一个代理类,然后调用重写的invoke方法去实现逻辑。
以上是jdk提供的一种方法,接下来我们用Cglib实现一下

cglib实现动态代理

public class IntermediaryProxy implements MethodInterceptor {  
  
    public Object instance(Class<?> clazz){  
        Enhancer enhancer = new Enhancer();  
 enhancer.setSuperclass(clazz);  
 enhancer.setCallback(this);  
 return enhancer.create();  
 }  
  
    @Override  
 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {  
        before();  
 methodProxy.invokeSuper(o, objects);  
 after();  
 return null; }  
  
    private void before() {  
        System.out.println("中介和客户沟通 ,要找一个什么样的房子");  
  
 }  
  
    private void after() {  
        System.out.println("达成协议,交定金");  
 }  
  
}
// 调用
public static void main(String[] args) {  
    Homeowner homeowner = (Homeowner) new IntermediaryProxy().instance(Homeowner.class);  
 homeowner.renting();  
 homeowner.getMoney();  
}

用cglib实现动态代理是不需要通过接口的 也就是之前的IBuyHouse 是不需要创建的,cglib代理类是直接继承真实类去实现代理的。

查看原文

赞 0 收藏 0 评论 0

大云梦 发布了文章 · 8月31日

springboot 手写maven依赖的demo

1:创建一个配置类

@Configuration
@EnableConfigurationProperties(RedissonConfig.class)
@ConditionalOnClass(Redisson.class)
public class RedissonAutoConfiguration {


    @Bean
    RedissonClient redissonClient(RedissonConfig redissonConfig) {
        Config config = new Config();
        String prefix = "redis://";
        if (redissonConfig.isSsl()) {
            prefix = "rediss://";
        }
        config.useSingleServer().setAddress(prefix + redissonConfig.getHost() + ":" + redissonConfig.getPort()).setConnectTimeout(redissonConfig.getTimeOut());
        return Redisson.create(config);
    }


}

这段代码向ioc容量里面注入了一个redissonClient 类型的bean。然后我们需要把这个项目install/deplay 到本地/远程maven仓库里面,供其他项目使用,但是其他项目又不知道这个配置类的路径 ,无法进行bean的装载,所以需要将类路径写到spring规定的文件下,请看第二步

2:定义配置类的路径

在resources/META-INF/spring.factories 文件下加入以下代码

# Auto config
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.chinadaas.platform.configuration.RedissonAutoConfiguration
# key值必须是
# org.springframework.boot.autoconfigure.EnableAutoConfiguration

3:完善依赖

如果需要注解提示,还需要添加以下依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <version>2.3.3.RELEASE</version>
            <optional>false</optional>
        </dependency>

4:给配置项添加提示

在/resources/META-INF/additional-spring-configuration-metadata.json 文件下添加如下内容

{
  "properties": [
    {
      "name": "chinadaas.redisson.host",
      "type": "java.lang.String",
      "description": "ip地址",
      "defaultValue": "127.0.0.1"
    },
    {
      "name": "chinadaas.redisson.port",
      "type": "java.lang.Integer",
      "description": "端口号",
      "defaultValue": "6379"
    },
    {
      "name": "chinadaas.redisson.timeOut",
      "type": "java.lang.Integer",
      "description": "超时事件",
      "defaultValue": "2000"
    }
  ]
}

然后将这个maven项目打成依赖添加到maven仓库里面,这样在其他项目引用的时候,就能直接从ioc容器里面取到RedissonClient 实例,并且可以在yaml里面配置自己的redisson的信息。

查看原文

赞 1 收藏 1 评论 0

大云梦 赞了文章 · 8月18日

访问/apisix/dashboard 时,出现错误:failed to match any routes

近期看到新闻:官宣!APISIX 毕业成为 Apache 软件基金会顶级项目,才开始了解到这个API网关,正值周末,就想着了解和学习安装使用,不过按照github的指导教程一路走下来,却一直出现标题的错误,搜索了很久也没找到答案,后来通过使用旧版本解决了(貌似根本就不算解决办法),为了避免后续还有出现这种问题,特此记录下,希望能帮到同样踩坑的伙伴。

本文只针对当前官方安装教程版本:https://github.com/apache/incubator-apisix/releases/download/1.4/apisix-1.4-0.el7.noarch.rpm,其他版本可能不存在这种问题。

先说原因:来自github项目的issues:
[Question] How to connect this dashboard to a dev apisix process?
image.png

大概意思是:当前版本(1.4)的APISIX 其dashboard 功能已经是一个独立的服务部署,而非原先放在APISIX 里面使用端口9080……
就我个人感觉:这种做法是比较科学的,本身dashboard 与APISIX核心功能关系不大,是封装了相关接口调用,做成了可视化,这样拆分后,使得dashboard 更方便拓展,而原先APISIX 的安装包也可以减小。
不过,既然之前都是集成在一起的,那这样做了区分后,可以在文档上说明一下,提到之前版本是怎样的,目前网上大多数的使用介绍和简单教程都还是旧版本,新旧结合的时候,就会出现这种问题……当然,这种问题是使用者的锅。 image.png

解决办法
解决办法有两种:
1、
安装低版本的APISIX(不建议,新版本存在更多特性,可以去了解下~):

# 安装 APISIX
$ yum install -y https://github.com/apache/incubator-apisix/releases/download/1.2/apisix-1.2-0.el7.noarch.rpm
 
# 启动APISIX 
$ apisix start

2、额外部署dashboard,参考:incubator-apisix-dashboard

查看原文

赞 1 收藏 0 评论 0

大云梦 发布了文章 · 8月11日

netty通过websocket实现服务器与客户端的长连接

server端代码
import com.chinadaas.bio.chinadaasbio.webSocket.handler.ServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
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.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.stream.ChunkedWriteHandler;

public class Server {

    public static void main(String[] args) throws Exception {
        NioEventLoopGroup boosGroup = new NioEventLoopGroup(1);
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(boosGroup, workerGroup);
            serverBootstrap.channel(NioServerSocketChannel.class);
            serverBootstrap.option(ChannelOption.SO_BACKLOG, 128);
            serverBootstrap.option(ChannelOption.SO_KEEPALIVE, true);
            serverBootstrap.handler(new LoggingHandler(LogLevel.INFO));
            serverBootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                    ChannelPipeline pipeline = socketChannel.pipeline();
                    // 因为是基于http的 所以使用http的编码和解析器
                    pipeline.addLast(new HttpServerCodec());
                    // 是以块方式写,添加ChunkWriteHandler() 处理器
                    pipeline.addLast(new ChunkedWriteHandler());
                    // http在传输过程中是分段的,这就是为什么当浏览器发送大量数据的时候,会发出多次http请求
                    pipeline.addLast(new HttpObjectAggregator(8192));
                    // 1:对应websocket 他的数据是以帧的形式传递
                    // 2: WebSocketServerProtocolHandler 功能是将http协议升级为ws协议,保持一个长连接
                    pipeline.addLast(new WebSocketServerProtocolHandler("/hello"));
                    // 添加自定义的handler
                    pipeline.addLast(new ServerHandler());
                }
            });
            ChannelFuture channelFuture = serverBootstrap.bind(8886).sync();
            channelFuture.channel().closeFuture().sync();

        } finally {
            boosGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

}
ServerHandler 代码
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;

import java.time.LocalDateTime;

public class ServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, TextWebSocketFrame textWebSocketFrame) throws Exception {

        System.out.println("服务器收到消息:" + textWebSocketFrame.text());
        channelHandlerContext.channel().writeAndFlush(new TextWebSocketFrame("服务器时间" + LocalDateTime.now() + " " + textWebSocketFrame.text()));

    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println(ctx.channel().remoteAddress()+"断开了连接");


    }
}
websocket html 代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>
    var socket;
    if (window.WebSocket) {
        socket = new WebSocket("ws://localhost:8886/hello")
        socket.onmessage = function (ev) {
            var rt = document.getElementById("responseText")
            rt.value = rt.value + "\n" + ev.data;
        }
        socket.onopen = function (ev) {
            var rt = document.getElementById("responseText")
            rt.value = "连接开启了...";
        }
        socket.onclose = function (ev) {
            var rt = document.getElementById("responseText")
            rt.value = rt.value + "\n" + "连接关闭了";
        }

    } else {
        alert("当前浏览器不支持websocket")
    }

    function send(message) {
        if (!window.socket) {
            return;
        }
        if (socket.readyState == WebSocket.OPEN) {
            socket.send(message);
        } else {
            alert("连接没有开启...")
        }
    }


</script>
<form onsubmit="return false">
    <textarea name="message" style="height: 300px; width: 300px"></textarea>
    <input type="button" value="发送消息" onclick="send(this.form.message.value)"/>
    <textarea id="responseText" style="height: 300px; width: 300px"></textarea>
    <input type="button" value="清空内容" onclick="document.getElementById('responseText').value=''"/>
</form>

</body>
</html>

欢迎大家前来讨论

查看原文

赞 0 收藏 0 评论 0

大云梦 发布了文章 · 8月10日

基于netty实现一个简单的群聊系统

server 端代码
import com.chinadaas.bio.chinadaasbio.groupChart.handler.ServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class Server {

    private Integer PORT;

    public Server(Integer PORT) {
        this.PORT = PORT;
    }

    public void run() {
        NioEventLoopGroup boosGroup = new NioEventLoopGroup(1);
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(boosGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            // 加入解码器
                            pipeline.addLast("myDecoder", new StringDecoder());
                            // 加入编码器
                            pipeline.addLast("myEncoder", new StringEncoder());
                            pipeline.addLast(new ServerHandler());
                        }
                    });
            ChannelFuture channelFuture = serverBootstrap.bind(PORT).sync();
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            boosGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        Server server = new Server(8886);
        server.run();
    }


}
client端代码
import com.chinadaas.bio.chinadaasbio.groupChart.handler.ClientHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.util.Scanner;

public class Client {

    private final String HOST;
    private final Integer PORT;

    public Client(String host, Integer port) {
        this.HOST = host;
        this.PORT = port;
    }
    public void run() {
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(workerGroup)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            // 解码器
                            pipeline.addLast("myDecoder", new StringDecoder());
                            // 编码器
                            pipeline.addLast("myEncoder", new StringEncoder());
                            pipeline.addLast(new ClientHandler());
                        }
                    });
            ChannelFuture channelFuture = bootstrap.connect(HOST, PORT).sync();
            Channel channel = channelFuture.channel();
            Scanner scanner = new Scanner(System.in);
            while (scanner.hasNextLine()) {
                String msg = scanner.nextLine();
                channel.writeAndFlush(msg + "\r\n");
            }
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            workerGroup.shutdownGracefully();
        }
    }
    public static void main(String[] args) {
        Client client = new Client("127.0.0.1", 8886);
        client.run();
    }
}
ServerHandler 代码
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;

public class ServerHandler extends SimpleChannelInboundHandler<String> {

    /**
     * GlobalEventExecutor.INSTANCE 全局事件执行器
     * */
    private static final ChannelGroup CHANNEL_GROUP = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println(ctx.channel() + "上线了");

    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println(ctx.channel() + "离线了");
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        CHANNEL_GROUP.writeAndFlush("[客户端]" + channel.remoteAddress() + "加入群聊");
        CHANNEL_GROUP.add(channel);
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        CHANNEL_GROUP.writeAndFlush("[客户端]" + channel.remoteAddress() + "离开群聊");
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
        // 获取消息并转发到群聊中其他的人
        Channel channel = channelHandlerContext.channel();
        CHANNEL_GROUP.forEach(ch -> {
            if (ch != channel) {
                ch.writeAndFlush("[客户" + channel.remoteAddress() + "]说:" + s + "\n");
            } else {
                ch.writeAndFlush("我说:" + s + "\n");
            }
        });
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}
ClientHandler 代码
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public class ClientHandler extends SimpleChannelInboundHandler<String> {


    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
        System.out.println(s.trim());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}

后面还有优化,当前只是大致实现以下

查看原文

赞 1 收藏 1 评论 0

大云梦 发布了文章 · 8月7日

基于netty的基础小案例

server端代码
import com.chinadaas.bio.chinadaasbio.netty.handler.ServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class Server {


    public static void main(String[] args) throws InterruptedException {
        NioEventLoopGroup boosGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            // 定义服务端启动类
            ServerBootstrap start = new ServerBootstrap()
                    .group(boosGroup, workerGroup) //设置两个线程组
                    .channel(NioServerSocketChannel.class) // 使用nioServer
                    .option(ChannelOption.SO_BACKLOG, 128) // 设置线程队列得到的链接个数
                    .childOption(ChannelOption.SO_KEEPALIVE, true) // 设置保持活动连接状态
                    .childHandler(new ChannelInitializer<SocketChannel>() {  // 创建一个通道测试对象(匿名对象)
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new ServerHandler());
                        }
                    });

            System.out.println("服务器 is ready");
            // 绑定一个端口 并且同步生成一个ChannelFuture
            // 启动服务器(并绑定端口)
            ChannelFuture channelFuture = start.bind(8886).sync();
            // 对关闭通道进行监听
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            boosGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
client端代码

import com.chinadaas.bio.chinadaasbio.netty.handler.ClientHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

public class Client {


    public static void main(String[] args) {

        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap()
                    .group(workerGroup)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new ClientHandler());
                        }
                    });

            System.out.println("客户端 is ready");
            ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 8886).sync();
            // 关闭通道进行监听
            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            workerGroup.shutdownGracefully();
        }
    }
}
serverHandler 代码
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;


public class ServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("有异常");
        ctx.close();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        System.out.println("服务器收到的消息:" + byteBuf.toString(CharsetUtil.UTF_8));
        System.out.println("客戶端的地址:" + ctx.channel().remoteAddress());
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello 客户端", CharsetUtil.UTF_8));
    }
}
clientHandler 代码
public class ClientHandler extends ChannelInboundHandlerAdapter {

    /**
     * 通道就绪后所触发的方法
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello 服务器", CharsetUtil.UTF_8));
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        System.out.println("客户端收到消息:" + byteBuf.toString(CharsetUtil.UTF_8));
        System.out.println("服务器的地址:" + ctx.channel().remoteAddress());
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {

    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }

}
查看原文

赞 0 收藏 0 评论 0

大云梦 发布了文章 · 8月4日

基于NIO实现一个简单的群聊系统

server端代码

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Set;

public class Server {

    private static ServerSocketChannel serverSocketChannel;
    private static Selector selector;
    private static final Integer PORT = 8888;

    public Server() {
        try {
            serverSocketChannel = ServerSocketChannel.open().bind(new InetSocketAddress(PORT));
            selector = Selector.open();
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void listen() {
        try {
            while (true) {
                int select = selector.select(3000);
                if (select <= 0) {
//                    System.out.println("无监听事件,继续下一次监听");
                    continue;
                }
                Set<SelectionKey> selectionKeys = selector.selectedKeys();
                for (SelectionKey selectionKey : selectionKeys) {
                    if (selectionKey.isAcceptable()) {
                        SocketChannel socketChannel = serverSocketChannel.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.register(selector, SelectionKey.OP_READ);
                        System.out.println(socketChannel.getRemoteAddress().toString() + "已经上线了");
                    }
                    if (selectionKey.isReadable()) {
                        SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                        ByteBuffer buffer = ByteBuffer.allocate(1024);
                        int read = 0;
                        try {
                            read = socketChannel.read(buffer);
                        }catch (Exception e){
                            System.out.println(socketChannel.getRemoteAddress() + "客戶端:离线了");
                            selectionKey.cancel();
                            socketChannel.close();
                            continue;
                        }
                        String msg = null;
                        if (read > 0) {
                            msg = new String(buffer.array());
                            System.out.println(socketChannel.getRemoteAddress() + "客户端:" + msg);
                        }
                        // 群发给其他的人
                        if (null != msg) {
                            sendInfoOtherPeople(msg, socketChannel);
                        }
                    }
                    // 防止重复消费
                    selectionKeys.remove(selectionKey);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    private void sendInfoOtherPeople(String msg, SocketChannel self) {
        try {
            Set<SelectionKey> keys = selector.keys();
            for (SelectionKey key : keys) {
                Channel socketChannel = key.channel();
                if (socketChannel instanceof SocketChannel && socketChannel != self) {
                    SocketChannel targetChannel = (SocketChannel) socketChannel;
                    targetChannel.write(ByteBuffer.wrap(msg.getBytes()));
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
        Server server = new Server();
        server.listen();
    }

}

client端代码

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Scanner;
import java.util.Set;

public class Client {

    private SocketChannel socketChannel;
    private static final String HOST = "127.0.0.1";
    private static final Integer PORT = 8888;
    private Selector selector;
    private static java.lang.String userName;

    public Client() {
        try {
            socketChannel = socketChannel.open(new InetSocketAddress(HOST, PORT));
            socketChannel.configureBlocking(false);
            selector = Selector.open();
            socketChannel.register(selector, SelectionKey.OP_READ);
            userName = socketChannel.getLocalAddress().toString().substring(1);

        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    private void listen() {
        try {
            int select = selector.select(3000);
            if (select <= 0) {
                return;
            }
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            for (SelectionKey selectionKey : selectionKeys) {
                if (selectionKey.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int read = socketChannel.read(buffer);
                    if (read > 0) {
                        System.out.println(new String(buffer.array()));
                    }
                }
                selectionKeys.remove(selectionKey);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void sendInfo(String msg) {
        try {
            socketChannel.write(ByteBuffer.wrap(msg.getBytes()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Client client = new Client();
        new Thread(new Runnable() {
            @Override
            public void run() {
                while (true) {
                    client.listen();
                }
            }
        }).start();

        // 发送数据
        Scanner scanner = new Scanner(System.in);

        while (scanner.hasNextLine()) {
            String msg = scanner.next();
            client.sendInfo(msg);
        }

    }

}

总结:代码实现的比较简单,欢迎大家前来补充指正。

查看原文

赞 0 收藏 0 评论 0

大云梦 赞了文章 · 7月2日

Spring Boot中增强对MongoDB的配置(连接池等)

之前转载了一篇关于《如何在Spring Boot中是配置MongoDB的连接数》的文章,相信关注我博客的朋友们肯定也看过了。这篇文章的作者主要重写了MongoDbFactory的构建来完成,整体实现的过程还是比较复杂的。本文就来具体说说如何更简单的来实现对MongoDB的更多配置定制。

spring-boot-starter-mongodb-plus

几周之后就在spring4all的github上创建了这个项目,主要就是想扩展一下官方spring boot starter对mongodb的支持,提供更多配置属性,比如:连接数的配置等。

先来看看如果使用这个扩展,是否要比之前那样自己定制要方便的多:

如何使用

1. 在使用了spring-boot-starter-data-mongodb的项目中,增加以下依赖
<dependency>
    <groupId>com.spring4all</groupId>
    <artifactId>mongodb-plus-spring-boot-starter</artifactId>
    <version>1.0.0.RELEASE</version>
</dependency>
2. 在应用主类上增加@EnableMongoPlus注解,比如:
@EnableMongoPlus
@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

可用配置参数

可配置参数如下:

spring.data.mongodb.option.min-connection-per-host=0
spring.data.mongodb.option.max-connection-per-host=100
spring.data.mongodb.option.threads-allowed-to-block-for-connection-multiplier=5
spring.data.mongodb.option.server-selection-timeout=30000
spring.data.mongodb.option.max-wait-time=120000
spring.data.mongodb.option.max-connection-idle-time=0
spring.data.mongodb.option.max-connection-life-time=0
spring.data.mongodb.option.connect-timeout=10000
spring.data.mongodb.option.socket-timeout=0

spring.data.mongodb.option.socket-keep-alive=false
spring.data.mongodb.option.ssl-enabled=false
spring.data.mongodb.option.ssl-invalid-host-name-allowed=false
spring.data.mongodb.option.always-use-m-beans=false

spring.data.mongodb.option.heartbeat-socket-timeout=20000
spring.data.mongodb.option.heartbeat-connect-timeout=20000
spring.data.mongodb.option.min-heartbeat-frequency=500
spring.data.mongodb.option.heartbeat-frequency=10000
spring.data.mongodb.option.local-threshold=15

上述配置值均为默认值

后记

如果您觉得该项目对您有用,欢迎给予Star支持:https://github.com/SpringForA...

同时也欢迎关注我的:

查看原文

赞 3 收藏 1 评论 0

认证与成就

  • 获得 2 次点赞
  • 获得 1 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 1 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2019-08-18
个人主页被 108 人浏览