• [编织消息框架][JAVA核心技术]异常应用


    QException是项目业务异常基类 按模块划分子类异常,方便定位那块出错

    有个来源码属性code作用定位某个功能处理出错逻辑,数字类型节省内存空间,同时减少创建子类的子类

    QSocketException 是通信层出错 凡是来自QSocketException 统一认为非法请求,强制关闭socket连接

    QJsonException 是json编解码出错 json很流行种数据格式,跨平台特点,经常处理

    QEnhanceException 是Javassist动态生成java class技术,用于替换jdk 动态代理

     1 public class QException extends RuntimeException {
     2 
     3     private static final long serialVersionUID = -3110633035340065406L;
     4 
     5     private short code;
     6 
     7     public short getCode() {
     8     return code;
     9     }
    10 
    11     public QException(short code, String message, Throwable cause) {
    12     super(message, cause);
    13     this.code = code;
    14     }
    15 
    16     public QException(short code) {
    17     super();
    18     this.code = code;
    19     }
    20 
    21     public QException(short code, String message) {
    22     super(message);
    23     this.code = code;
    24     }
    25 
    26 }
    QException

    接下来应用异常

    首先要找到所有业务调用的主入口,由于用的是netty通信框架,对于服务端来讲要找到接收数据的方法

    ChannelDuplexHandler 是netty提供的业务实现的类,其中channelRead是接收数据的方法

     1 @Sharable
     2 public class QMessageHandler extends ChannelDuplexHandler {
     3 
     4     private QDispenseHandler dispenseHandler;
     5 
     6     public QMessageHandler(QDispenseHandler dispenseHandler) {
     7         this.dispenseHandler = dispenseHandler;
     8     }
     9 
    10     @Override
    11     public void channelActive(ChannelHandlerContext ctx) throws Exception {
    12         dispenseHandler.doConnect(ctx);
    13         super.channelActive(ctx);
    14     }
    15 
    16     @Override
    17     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
    18         dispenseHandler.doReceive(msg, ctx);
    19         super.channelRead(ctx, msg);
    20     }
    21 
    22     @Override
    23     public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    24         dispenseHandler.doClose(ctx);
    25         super.channelInactive(ctx);
    26     }
    27 }

    QDispenseHandler.class 

    当业务处理失败时,响应三种策略

    1.优先处理来自QSocketException强制关闭socket连接

    2.业务边界QException

    3.未知错误Exception

    第一种情况不用返回响应码

    第二三种情况是否返回根据客户端请求状态决定 boolean response = packet.hasStatus(QPacket.MASK_RESPONSE)

     1  public void doReceive(Object msg, ChannelHandlerContext ctx) {
     2     if (msg instanceof QPacket) {
     3         pool.execute(() -> {
     4         doReceive0((QPacket) msg, ctx);
     5         });
     6     }
     7  }
     8 
     9  private void doReceive0(QPacket packet, ChannelHandlerContext ctx) {
    10 
    11     boolean response = packet.hasStatus(QPacket.MASK_RESPONSE);
    12     try {
    13         //doReceive ... 处理省略细节
    14         
    15     } catch (QSocketException e) {
    16         // socket异常 关闭连接
    17         packet.responseCode(e.getCode());
    18         LOGGER.error("QSocketException  msg {} error : {}", QCodeUtil.getDes( e.getCode()), e);
    19         if (response) {
    20         ChannelFuture future = ctx.channel().writeAndFlush(packet);
    21         future.addListener(new GenericFutureListener<Future<? super Void>>() {
    22             @Override
    23             public void operationComplete(Future<? super Void> future) throws Exception {
    24             NettyUtil.closeChannel(CLOSE_SOURCE.SOCKET_ERROR, false, ctx.channel());
    25             }
    26         });
    27         } else {
    28         NettyUtil.closeChannel(CLOSE_SOURCE.SOCKET_ERROR, false, ctx.channel());
    29         }
    30         return;
    31     } catch (QException e) {
    32         // 业务异常 响应失败
    33         packet.responseCode(e.getCode());
    34         LOGGER.error("QException  msg {} error : {}",QCodeUtil.getDes( e.getCode()), e);
    35     } catch (Exception e) {
    36         // 未知异常 响应失败
    37         packet.responseCode(QCode.ERROR_UNKNOWN);
    38         LOGGER.error("UNKNOWNException  error : {}", e);
    39     }
    40     if (response) {
    41         ctx.channel().writeAndFlush(packet);
    42     }
    43  }
  • 相关阅读:
    2016.01.04接触spring一年开始读spring源码
    hibernate 各历史版本下载 spring各历史版本下载
    mongodb 安装使用遇到的问题记录
    EmEditor处理大文本文件
    linux的常用易忘命令
    签名的html
    添加用户-查看用户列表-禁止默认root登陆
    今天领导分享了一个探测端口的命令-linux下提示bash:command not found
    【原创】java 获取十个工作日之前或之后的日期(算当天)-完美解决-费元星
    Oracle 完全理解connect by-详细脚本-可实战
  • 原文地址:https://www.cnblogs.com/solq111/p/6605191.html
Copyright © 2020-2023  润新知