本篇文章主要讲解Java的Mina框架传递对象是什么,并附于代码和图片方便大家理解。

AD:2013大数据全球技术峰会课程PPT下载

接触java的Mina框架已经有很多时间了,在网上也读过了很多的相关文章,发现Mina框架的确是一个值得拿来好好研究的东西,前些日子写了一个山寨QQ项目,其中的通信部分用到了java中自带的InputStream,OutputStream,Writer,Reader等等,感觉其中的很大的一个问题就是难以将事务处理的逻辑层与解析层分离开来,造成整个项目看起来比较臃肿,繁琐,不够模块化,接触Mina后发现mina在这方面做的很是恰到好处。

看到文章标题,你或许会有一些疑惑:

1、Mina框架传递对象是怎么回事

2、Mina传递对象可以用来做什么

3、Mina传递对象是怎么进行的

4、Mina传递对象过程中会遇到什么问题呢

在用原来的java的InputStream,OutputStream,Writer,Reader等进行通信的时候我们会将信息编码转化成字节流等进行信息传递,InputStream,OutputStream是基于字节流的,而Writer,Reader是基于字符的,我们都知道进行通信的服务器和客户端是事先必须定好通信协议,如果我们将你好吗?定义为是一条消息,视频定义为一条视频请求,如果客户端将这条消息和请求发送给了服务器,服务器要想得到消息和请求的真正内容(在这里分别是“你好吗?”和“视频”)并进行处理和应答就必须进行信息的解析,就要一条一条的进行判断:1、如果是信息是……格式的就将其看做是一条消息;2、如果是……格式的就将其看作是一条请求;3、如果是其他形式就将其视为无效信息,不予处理。当然这不失为一种办法可以进行信息的提取,但是我们会发现在这个过程中信息的发送、接受、解析、处理、应答等都是一条一条的,很是零散,比较难以统一,没有实现消息定义和解析处理过程的分离,这样写好了一个程序,如果日后想要进行改正其中的一条信息格式,就要在整个项目中Ctrl+F了,比较繁琐,还容易出错。

这是我们会自然的想到要用一种东西将各个格式的信息进行分类统一起来并方便进行一些必要的信息处理,为符合这些特点,我们会想到类这个东东恰恰满足了这些性质,我们可以将信息的格式中的内容定义为类的属性,而对这些属性的处理就可以用类中的方法来予以解决,这样就对信息进行了很好的包装。

这种思想有了,那就是在通信的时候直接进行形式上的对象传递(实际上在通信的时候都是最终以字节流的方式进行传递的),那么我们就要找一种工具进行这种形式的信息传递,对了,这种工具就是Mina框架,我们只看他其中的一个方法

public void messageReceived(IoSession session, Object message),这是进行消息接收是能够被 触发的一个方法,参数session代表当前的会话对象,参数message代表接收的到的信息,这时您会发现message的类型是Object型,而类 Object 是类层次结构的根类,当然可以用对象型的作为message啦!前面提到通信的时候都是最终以字节流的方式进行传递的,这样就要进行:对象(客户端)->字节流(客户端)->发送->接收->字节流(服务器)->对象(服务器)的过程,呵呵不用担心,这些繁琐的过程,Mina都提供了很好的底层默认实现所以你只需稍稍敲点代码就行了。

光说不练还是不行,先上一个程序实例:

服务器端(1):

Java代码


  1. package Mina.server;
  2. import java.io.IOException;
  3. import java.net.InetSocketAddress;
  4. import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
  5. import org.apache.mina.filter.codec.ProtocolCodecFilter;
  6. import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
  7. import org.apache.mina.transport.socket.SocketAcceptor;
  8. import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
  9. public class MainServer {
  10. private static MainServer mainServer = null;
  11. private SocketAcceptor acceptor = new NioSocketAcceptor();
  12. private DefaultIoFilterChainBuilder chain = acceptor.getFilterChain();
  13. private int bindPort = 8888;
  14. public static MainServer getInstances() {
  15. if (null == mainServer) {
  16. mainServer = new MainServer();
  17. }
  18. return mainServer;
  19. }
  20. private MainServer() {
  21. chain.addLast("myChin", new ProtocolCodecFilter(
  22. new ObjectSerializationCodecFactory()));
  23. acceptor.setHandler(ServerHandler.getInstances());
  24. try {
  25. acceptor.bind(new InetSocketAddress(bindPort));
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. public static void main(String[] args) throws Exception {
  31. MainServer.getInstances();
  32. }
  33. }

服务器端(2):

Java代码


  1. package Mina.server;
  2. import org.apache.mina.core.filterchain.IoFilterAdapter;
  3. import org.apache.mina.core.service.IoHandler;
  4. import org.apache.mina.core.session.IdleStatus;
  5. import org.apache.mina.core.session.IoSession;
  6. import Mina.Object.UserInfo;
  7. public class ServerHandler extends IoFilterAdapter implements IoHandler {
  8. private static ServerHandler samplMinaServerHandler = null;
  9. public static ServerHandler getInstances() {
  10. if (null == samplMinaServerHandler) {
  11. samplMinaServerHandler = new ServerHandler();
  12. }
  13. return samplMinaServerHandler;
  14. }
  15. private ServerHandler() {
  16. }
  17. // 当连接后打开时触发此方法,一般此方法与 sessionCreated 会被同时触发
  18. public void sessionOpened(IoSession session) throws Exception {
  19. }
  20. public void sessionClosed(IoSession session) {
  21. }
  22. public void messageReceived(IoSession session, Object message)
  23. throws Exception {
  24. if (message instanceof UserInfo) {
  25. UserInfo text = (UserInfo) message;
  26. System.out.println("服务器接收到从客户端的姓名:"+text.getName());
  27. System.out.println("服务器接收到从客户端的QQ:"+text.getQQNum());
  28. }
  29. }
  30. public void exceptionCaught(IoSession arg0, Throwable arg1)
  31. throws Exception {
  32. }
  33. // 当消息传送到客户端后触发
  34. public void messageSent(IoSession arg0, Object arg1) throws Exception {
  35. }
  36. // 当一个新客户端连接后触发此方法.
  37. public void sessionCreated(IoSession arg0) throws Exception {
  38. }
  39. // 当连接空闲时触发此方法.
  40. public void sessionIdle(IoSession arg0, IdleStatus arg1) throws Exception {
  41. }
  42. }

客户端(1):

Java代码


  1. package Mina.client;
  2. import java.net.InetSocketAddress;
  3. import org.apache.mina.core.filterchain.DefaultIoFilterChainBuilder;
  4. import org.apache.mina.core.future.ConnectFuture;
  5. import org.apache.mina.filter.codec.ProtocolCodecFilter;
  6. import org.apache.mina.filter.codec.serialization.ObjectSerializationCodecFactory;
  7. import org.apache.mina.transport.socket.nio.NioSocketConnector;
  8. public class MainClient {
  9. private static MainClient mainClient = null;
  10. NioSocketConnector connector = new NioSocketConnector();
  11. DefaultIoFilterChainBuilder chain = connector.getFilterChain();
  12. public static MainClient getInstances() {
  13. if (null == mainClient) {
  14. mainClient = new MainClient();
  15. }
  16. return mainClient;
  17. }
  18. private MainClient() {
  19. chain.addLast("myChin", new ProtocolCodecFilter(
  20. new ObjectSerializationCodecFactory()));
  21. connector.setHandler(ClientHandler.getInstances());
  22. connector.setConnectTimeout(30);
  23. ConnectFuture cf = connector.connect(new InetSocketAddress("localhost",
  24. 8888));
  25. }
  26. public static void main(String args[]) {
  27. MainClient.getInstances();
  28. }
  29. }

客户端(2):

Java代码


  1. package Mina.client;
  2. import org.apache.mina.core.service.IoHandlerAdapter;
  3. import org.apache.mina.core.session.IoSession;
  4. import Mina.Object.UserInfo;
  5. public class ClientHandler extends IoHandlerAdapter {
  6. private static ClientHandler samplMinaClientHandler = null;
  7. public static ClientHandler getInstances() {
  8. if (null == samplMinaClientHandler) {
  9. samplMinaClientHandler = new ClientHandler();
  10. }
  11. return samplMinaClientHandler;
  12. }
  13. private ClientHandler() {
  14. }
  15. public void sessionOpened(IoSession session) throws Exception {
  16. session.write("客户端与服务器的会话打开了……");
  17. UserInfo text=new UserInfo();
  18. text.setName("梅竹寒香");
  19. text.setQQNum("972341215");
  20. session.write(text);
  21. }
  22. public void sessionClosed(IoSession session) {
  23. }
  24. public void messageReceived(IoSession session, Object message)
  25. throws Exception {
  26. }
  27. public void messageSent(IoSession arg0, Object arg1) throws Exception {
  28. System.out.println("客户端已经向服务器发送了:"+(String)arg1);
  29. }
  30. }

公共类:

Java代码


  1. package Mina.Object;
  2. public class UserInfo implements java.io.Serializable{
  3. private String name;
  4. private String QQNum;
  5. public String getName() {
  6. return name;
  7. }
  8. public void setName(String name) {
  9. this.name = name;
  10. }
  11. public String getQQNum() {
  12. return QQNum;
  13. }
  14. public void setQQNum(String qQNum) {
  15. QQNum = qQNum;
  16. }
  17. }

如下建包即可:

以上就是对象的收发的简单示例,如果报错,或许会是一下原因:1、包的引进是否妥当 2、是否引入了mina的第三方包(网上有了很多的相关文章,在此就不在赘述了)

通过程序您会看到对象已经成功传递并进行了相关属性的输出,对于这个简单的程序我稍做些相关说明:

1、进行传递的对象所实例化的类要实现java.io.Serializable序列化接口

2、您会发现实例中的类尤其是相关的IoHandlerAdapter继承类都采用了单实例模式,为什么这样做呢,原因很简单,那就是要在整个通信过程中做到对象session的等实例的单一防止发生“所托非人”的现象

3、服务器接收到message在进行类判断时用了instanceof关键字

如果你看到上面的实例就觉得对象传递的学习已经成功了,那就错了,细心的博友看到这个包结构:

是不是有点问题呢。

例如客户端传了一个userinfo对象到服务器,在服务器端判断如果是userinfo对象后就打印出相关信息,我看源码文档其中有这样的建包方式

其中服务器和客户端共用了中间的Mina.Object包,这样在收到对象后就能通过instanceof关键字判断是不是useinfo对象,我看了一下,这个方法是可行的,现在的问题是,我们如果编写通讯软件的时候,肯定是服务器和客户端是要分开的,所以那个Mina.Object包是不能共享的,所以问题来了(1)、如果将userinfo放到客户端中,那么该怎么用instanceof进行判断是不是userinfo呢(这时你已经不能再引入服务器中的userinfo了)(2)、如果在客户端和服务器中都编写一个类定义一样的userinfo,可是他们这两个类是分属不同的包,所以是两个不同的类了,这样在用instanceof进行判断的时候也是行不通的;那么我们该用什么方法来进行判断接收到的类是不是userinfo对象呢?

这个问题把我纠结了很久,在网上面搜了好久也没有解决,最后想了想那个(2)或许可以改动改动就可以解决,问题的关键在于两个UserInfo分属于两个不同的包,如果可以将包名一致就好了,但是在一个工程里面不能同时建立两个命名一样的包,这样你就会发现何不建立两个工程呢一个是服务器,一个是客户端,这样都可以分别建立名字都是Object的包,这样可不可行呢,经过试验果然可以,这样就就解决了上面的问题工程图如下

好啦,有了这个工具,您会有什么想法呢?对象传递还可以做什么?那就是可以用它来进行图片,文件的传递啦,这个只是个小小的提示具体怎么实现,就要看各位博友怎么发挥啦!呵呵

浅谈Java的Mina框架传递对象的更多相关文章

  1. 浅谈Java的集合框架

    浅谈Java的集合框架 一.    初识集合 重所周知,Java有四大集合框架群,Set.List.Queue和Map.四种集合的关注点不同,Set 关注事物的唯一性,List 关注事物的索引列表,Q ...

  2. 浅谈java类集框架和数据结构(2)

    继续上一篇浅谈java类集框架和数据结构(1)的内容 上一篇博文简介了java类集框架几大常见集合框架,这一篇博文主要分析一些接口特性以及性能优化. 一:List接口 List是最常见的数据结构了,主 ...

  3. 浅谈java类集框架和数据结构(1)

    在另外一篇博客我简单介绍了java类集框架相关代码和理论. 这一篇博客我主要分析一下各个类集框架的原理以及源码分析. 一:先谈谈LinkedList 这是LinkedList源码的开头,我们能看到几点 ...

  4. 浅谈Java反射与框架

    Java反射 1.示例 1.用户类 package com.lf.entity; import com.lf.annotation.SetProperty; import com.lf.annotat ...

  5. 浅谈Java虚拟机内存中的对象创建,内存布局,访问定位

    参考于 深入理解Java虚拟机 这里介绍HotSpot虚拟机(自带的虚拟机) 1.对象的创建 对于程序员来说,创建对象的方法: User user1 = new User(); User user2 ...

  6. 浅谈JAVA集合框架

    浅谈JAVA集合框架 Java提供了数种持有对象的方式,包括语言内置的Array,还有就是utilities中提供的容器类(container classes),又称群集类(collection cl ...

  7. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  8. 浅谈Java中的对象和对象引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  9. 浅谈Java回收对象的标记和对象的二次标记过程_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 一.对象的标记 1.什么是标记?怎么标记? 第一个问题相信大家都知道,标记就是对一些已死的对象打上记号,方便垃圾收集器的 ...

  10. !! 浅谈Java学习方法和后期面试技巧

    浅谈Java学习方法和后期面试技巧 昨天查看3303回复33 部落用户大酋长 下面简单列举一下大家学习java的一个系统知识点的一些介绍 一.java基础部分:java基础的时候,有些知识点是非常重要 ...

随机推荐

  1. 9.5内网横向&代理&隧道

    Socks代理思路: 工具:nps.frp.ngrok.reGeorg.sockscap64.earthworm.proxifier.proxychains 知识点 1.内外网简单知识 2.内网1和内 ...

  2. C#自定义控件—指示灯

    C#用户控件之指示灯 在体现通讯状态.运行状态等用一个靓眼的指示灯如何做? 思路(GDI) 外环用笔绘制(Pen),内圆用画刷(SolidBrush); 两个方法(用笔画圆,用画刷填充圆的内部): 绘 ...

  3. Angular Material 18+ 高级教程 – CDK Portal

    前言 CDK Portal 是 Angular Material 对 Angular Dynamic Component (ViewContainerRef,TemplateRef,createCom ...

  4. CSS & JS Effect – FAQ Accordion & Slide Down

    效果 参考: Youtube – Responsive FAQ accordion dropdown | HTML and CSS Tutorial 几个难点 1. 如何 align left for ...

  5. 非常非常好用的一款账户密码保存工具-KeePass

      非常非常好用的一款账户密码保存工具 下载地址: https://sourceforge.net/projects/keepass/files/KeePass%202.x/2.55/KeePass- ...

  6. go中能比较和不能比较的数据类型

    在 Go 语言中,比较操作符(== 和 !=)可以用于许多数据类型,但也有一些数据类型不支持直接比较.下面详细解释哪些数据类型可以比较,哪些不能比较,以及相关的规则和原因. 可以比较的数据类型 布尔型 ...

  7. USB type-c CC管脚如何做到正反接检测功能

    USB Type-C 连接器的 CC (Configuration Channel) 管脚用于实现插头方向检测和电源管理.具体来说,USB Type-C 连接器具有两个 CC 管脚:CC1 和 CC2 ...

  8. Trace32 simulator调试以及简单实用命令介绍

    目录 Trace32 Simulator debug Trace32工具配置 Trace32命令简介 memory class 常见命令索引 v.v使用实例 不同CPU运行信息查看 Trace32 S ...

  9. 将nii文件CT图像更改窗宽窗位之后保存成nii文件

    因为项目需要把CT图像中骨头更加明确的显示出来,且还需要保存nii文件,所以查了一些资料,在这里做一下笔记,方便以后使用.代码如下: import nibabel as nib import nump ...

  10. LINQ 统计字符频率

    var arr = new string[] {"test","zhulongxu","asdfdgd","yangmi" ...