netty使用
今天使用netty搭建了个架子。具体请看代码。
引入jar包 :netty-all-4.1.0.Final.jar
package grp.pb.branch.shanxijs.netty; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; /** * * Netty中,通讯的双方建立连接后,会把数据按照ByteBuf的方式进行传输, * 例如http协议中,就是通过HttpRequestDecoder对ByteBuf数据流进行处理,转换成http的对象。 * */ public class SimpleServer { private int port; private ChannelInboundHandlerAdapter adapter; public SimpleServer(int port , ChannelInboundHandlerAdapter adapter) { this.port = port; this.adapter = adapter; } public void run() throws Exception { //EventLoopGroup是用来处理IO操作的多线程事件循环器 //bossGroup 用来接收进来的连接 EventLoopGroup bossGroup = new NioEventLoopGroup(); //workerGroup 用来处理已经被接收的连接 EventLoopGroup workerGroup = new NioEventLoopGroup(); try { //启动 NIO 服务的辅助启动类 ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) //配置 Channel .channel(NioServerSocketChannel.class) .childHandler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) throws Exception { // 注册handler ch.pipeline().addLast(adapter); } }) .option(ChannelOption.SO_BACKLOG, 128) .childOption(ChannelOption.SO_KEEPALIVE, true); // 绑定端口,开始接收进来的连接 ChannelFuture f = b.bind(port).sync(); // 等待服务器 socket 关闭 。 f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); bossGroup.shutdownGracefully(); } } }
package grp.pb.branch.shanxijs.netty; import grp.pb.branch.shanxijs.header.ss.impl.ISelfSignService; import grp.pt.pb.ss.ISelfCounterService; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import java.io.ByteArrayInputStream; import org.apache.log4j.Logger; @Sharable public class SimpleServerHandler extends ChannelInboundHandlerAdapter { private static Logger log = Logger.getLogger(SimpleServerHandler.class); private ISelfSignService selfSignService = null; private static String CHAR_SET = "gbk"; public SimpleServerHandler(ISelfSignService selfCounterService){ super(); this.selfSignService = selfCounterService; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("SimpleServerHandler.channelRead"); ByteBuf result = (ByteBuf) msg; byte[] result1 = new byte[result.readableBytes()]; // msg中存储的是ByteBuf类型的数据,把数据读取到byte[]中 result.readBytes(result1); // 接收并打印客户端的信息 log.info("接收报文:" + new String(result1,CHAR_SET)); // 释放资源,这行很关键 result.release(); // 向客户端发送消息 //执行自助柜面的操作 byte[] response = selfSignService.doTask(new ByteArrayInputStream(result1)); log.info("发送报文:" + new String(response,CHAR_SET)); // 在当前场景下,发送的数据必须转换成ByteBuf数组 ByteBuf encoded = ctx.alloc().buffer(response.length); encoded.writeBytes(response); ctx.write(encoded); ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // 当出现异常就关闭连接 cause.printStackTrace(); ctx.close(); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } }
package grp.pb.branch.shanxijs.ss.job; import grp.pb.branch.shanxijs.header.ss.impl.ISelfSignService; import grp.pb.branch.shanxijs.netty.SimpleServer; import grp.pb.branch.shanxijs.netty.SimpleServerHandler; import grp.pt.pb.common.AutoJobAdapter; import grp.pt.pb.exception.PbException; import grp.pt.pb.job.SelfCounterAutoTaskJob; import grp.pt.pb.ss.ISelfCounterService; import grp.pt.pb.trans.util.SocketUtil; import grp.pt.pb.util.PropertiesHander; import grp.pt.pb.util.StaticApplication; import grp.pt.util.exception.CommonException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import org.apache.log4j.Logger; /** * 与自助柜面衔接的自动任务 使用netty进行传输 * @author lth * */ public class JSSignServerNettyJob extends AutoJobAdapter { private static Logger log = Logger.getLogger(SelfCounterAutoTaskJob.class); /** * 服务端socket */ private static SimpleServer serverSocket = null; private static ISelfSignService selfSignService = null; @Override public void executeJob() { init(); try { serverSocket.run(); } catch (Exception e) { log.error("自助柜面自动任务处理失败", e); } } private void init() { if (selfSignService == null) { selfSignService = (ISelfSignService) StaticApplication.getBean("jsSelfSignServiceImpl"); } try { if(serverSocket == null){ int port = Integer.valueOf(PropertiesHander.getValue("trans", "selfCounterPort")); SimpleServerHandler adapter = new SimpleServerHandler(selfSignService); serverSocket = new SimpleServer(port,adapter); } } catch (Exception e) { log.error(e.getMessage(),e); throw new PbException("创建端口为:" + PropertiesHander.getValue("trans", "selfCounterPort") + "的服务端Socket失败!"); } log.info("自助柜面服务已启动,监听端口为:"+PropertiesHander.getValue("trans", "selfCounterPort")); } }
package grp.pb.branch.shanxijs.header.ss.impl; import grp.pt.pb.exception.PbException; import grp.pt.pb.ss.model.TransResultDTO; import grp.pt.pb.ss.util.SsConstant; import grp.pt.pb.trans.model.TransReturnDTO; import grp.pt.pb.trans.util.SocketUtil; import grp.pt.pb.trans.util.TransUtil; import grp.pt.pb.util.XmlUtils; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.UnsupportedEncodingException; import org.apache.log4j.Logger; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.DocumentHelper; /** * 处理 晋商银行自助柜面与柜面衔接业务 的 报文拼装解析工具类 * */ public class JSSelfSignServiceImpl implements ISelfSignService { private static Logger logger = Logger.getLogger(JSSelfSignServiceImpl.class); //业务处理类 private JSSelfCounterBusinessServiceImpl jsSelfCounterBusinessServiceImpl = null; public JSSelfCounterBusinessServiceImpl getJsSelfCounterBusinessServiceImpl() { return jsSelfCounterBusinessServiceImpl; } public void setJsSelfCounterBusinessServiceImpl( JSSelfCounterBusinessServiceImpl jsSelfCounterBusinessServiceImpl) { this.jsSelfCounterBusinessServiceImpl = jsSelfCounterBusinessServiceImpl; } @Override public byte[] doTask(ByteArrayInputStream in) throws UnsupportedEncodingException { TransResultDTO resultDto = null; byte[] resMsgByte = null; JSSelfCounterMsgBody msgBody = null; try { // 解析 msgBody = this.doParser(in); // 调用自助柜面业务层接口 resultDto = this.doBusiness(msgBody); // 生成成功的响应报文 resMsgByte = this.doResponse(msgBody.getMsgHead().getTransCode(),resultDto, msgBody); } catch (Exception e) { logger.error("交易失败", e); resMsgByte = this.errorResponse(e.getMessage(),msgBody.getMsgHead().getTransCode()); } return resMsgByte; } /** * 解析请求报文 * @param in * @return * @throws Exception */ private JSSelfCounterMsgBody doParser(InputStream in) throws Exception { //1.解析报文头 byte[] reqMsgHead = SocketUtil.read(in, JSSelfCounterConstant.CTJ_REQ_HEAD_LEN + 6); JSSelfCounterMsgHead reqHead = this.parsToMsgHead(reqMsgHead); //2.解析报文体 byte[] reqMsgBody = SocketUtil.read(in, reqHead.getMsgLen() - JSSelfCounterConstant.CTJ_REQ_HEAD_LEN); logger.info("交易码是:"+reqHead.getTransCode()); JSSelfCounterMsgBody reqBody = this.parseToMsgBody(reqMsgBody,reqHead.getTransCode()); reqBody.setMsgHead(reqHead); return reqBody; } /** * 解析报文头 * * @param headBytes * @return */ private JSSelfCounterMsgHead parsToMsgHead(byte[] headBytes) { // 6位报文长度 int msgLen = Integer.valueOf(new String(headBytes, 0, 6).trim()); // 4位交易码 String trans_code = new String(headBytes, 6, 4); JSSelfCounterMsgHead reqHead = new JSSelfCounterMsgHead(msgLen, trans_code); return reqHead; } /** * 解析请求报文体 * @return * @throws UnsupportedEncodingException * @throws DocumentException * @throws Exception */ private JSSelfCounterMsgBody parseToMsgBody(byte[] reqMsgBody, String transCode) throws UnsupportedEncodingException, DocumentException { JSSelfCounterMsgBody msgBody = new JSSelfCounterMsgBody(); String msg = new String(reqMsgBody,JSSelfCounterConstant.CHAR_SET); Document document=DocumentHelper.parseText(msg); //签约接口 if(JSSelfCounterConstant.SIGN.equalsIgnoreCase(transCode)){ getMsgBody4Sign(msgBody, document); //修改客户信息 }else if(JSSelfCounterConstant.UPDATE_CUSTOMER_INFO.equalsIgnoreCase(transCode)){ getMsgBody4UpdateCustomerInfo(msgBody, document); //注销客户 }else if(JSSelfCounterConstant.CANCEL_CUSTOMER.equalsIgnoreCase(transCode)){ getMsgBody4CancelCustomer(msgBody, document); //更新操作员 }else if(JSSelfCounterConstant.UPDATE_OPERATOR_INFO.equalsIgnoreCase(transCode)){ getMsgBody4UpdateOperatorInfo(msgBody, document); //更新ukey信息 }else if(JSSelfCounterConstant.UPDATE_UKEY_INFO.equalsIgnoreCase(transCode)){ getMsgBody4UpdateUkeyInfo(msgBody, document); //重置密码信息 }else if(JSSelfCounterConstant.RESET_OPERATOR_PASSWORD.equalsIgnoreCase(transCode)){ getMsgBody4ResetOperatorPassword(msgBody, document); //注销操作员 }else if(JSSelfCounterConstant.CANCEL_OPERATOR.equalsIgnoreCase(transCode)){ getMsgBody4CancelOperator(msgBody, document); }else{ throw new PbException("您输入的交易码"+transCode+"有误!"); } return msgBody; } /** * 注销操作员 */ private void getMsgBody4CancelOperator(JSSelfCounterMsgBody msgBody, Document document) { //签约账号 String acctNo = document.selectSingleNode("/root/acctNo").getText(); msgBody.setAccountcode(acctNo); //客户号 String customNo = document.selectSingleNode("/root/customNo").getText(); msgBody.setCustomno(customNo); //经办人(柜员)姓名 String signName = document.selectSingleNode("/root/signName").getText(); msgBody.setSignname(signName); //经办人(柜员)证件类型 String signCardType = document.selectSingleNode("/root/signCardType").getText(); msgBody.setSigncardtype(signCardType); //经办人(柜员)证件号码 String signCardNo = document.selectSingleNode("/root/signCardNo").getText(); msgBody.setSigncardno(signCardNo); //经办人(柜员)电话 String signTel = document.selectSingleNode("/root/signTel").getText(); msgBody.setSigntel(signTel); //预算单位操作员编码 String userCode = document.selectSingleNode("/root/userCode").getText(); msgBody.setUser_code(userCode); } /** * 重置操作员密码 */ private void getMsgBody4ResetOperatorPassword(JSSelfCounterMsgBody msgBody, Document document) { //签约账号 String acctNo = document.selectSingleNode("/root/acctNo").getText(); msgBody.setAccountcode(acctNo); //客户号 String customNo = document.selectSingleNode("/root/customNo").getText(); msgBody.setCustomno(customNo); //经办人(柜员)姓名 String signName = document.selectSingleNode("/root/signName").getText(); msgBody.setSignname(signName); //经办人(柜员)证件类型 String signCardType = document.selectSingleNode("/root/signCardType").getText(); msgBody.setSigncardtype(signCardType); //经办人(柜员)证件号码 String signCardNo = document.selectSingleNode("/root/signCardNo").getText(); msgBody.setSigncardno(signCardNo); //经办人(柜员)电话 String signTel = document.selectSingleNode("/root/signTel").getText(); msgBody.setSigntel(signTel); //预算单位操作员登录密码 BASE64加密 默认密码base64(123456) String userPwd = document.selectSingleNode("/root/userPwd").getText(); msgBody.setUser_password(userPwd); //预算单位操作员编码 String userCode = document.selectSingleNode("/root/userCode").getText(); msgBody.setUser_code(userCode); } /** * 更新ukey信息 */ private void getMsgBody4UpdateUkeyInfo(JSSelfCounterMsgBody msgBody, Document document) { getMsgBody4CancelOperator(msgBody, document); //Ukey编码 String ukeyCode = document.selectSingleNode("/root/ukeyCode").getText(); msgBody.setUkey_code(ukeyCode); } /** * 更新操作员 */ private void getMsgBody4UpdateOperatorInfo(JSSelfCounterMsgBody msgBody, Document document) { //签约账号 String acctNo = document.selectSingleNode("/root/acctNo").getText(); msgBody.setAccountcode(acctNo); //客户号 String customNo = document.selectSingleNode("/root/customNo").getText(); msgBody.setCustomno(customNo); //预算单位操作员编码 String userCode = document.selectSingleNode("/root/userCode").getText(); msgBody.setUser_code(userCode); //预算单位操作员姓名 String userName = document.selectSingleNode("/root/userName").getText(); msgBody.setUser_name(userName); //预算单位操作员证件类型 String userCardType = document.selectSingleNode("/root/userCardType").getText(); msgBody.setUser_card_type(userCardType); //预算单位操作员证件号码 String userCardNo = document.selectSingleNode("/root/userCardNo").getText(); msgBody.setUser_card_no(userCardNo); //操作员电话号码 String operTel = document.selectSingleNode("/root/operTel").getText(); msgBody.setOperTel(operTel); //经办人(柜员)姓名 String signName = document.selectSingleNode("/root/signName").getText(); msgBody.setSignname(signName); //经办人(柜员)证件类型 String signCardType = document.selectSingleNode("/root/signCardType").getText(); msgBody.setSigncardtype(signCardType); //经办人(柜员)证件号码 String signCardNo = document.selectSingleNode("/root/signCardNo").getText(); msgBody.setAccountcode(signCardNo); //经办人(柜员)电话 String signTel = document.selectSingleNode("/root/signTel").getText(); msgBody.setSigntel(signTel); } /** * 注销客户 */ private void getMsgBody4CancelCustomer(JSSelfCounterMsgBody msgBody, Document document) { //签约账号 String acctNo = document.selectSingleNode("/root/acctNo").getText(); msgBody.setAccountcode(acctNo); //客户号 String customNo = document.selectSingleNode("/root/customNo").getText(); msgBody.setCustomno(customNo); //经办人(柜员)姓名 String signName = document.selectSingleNode("/root/signName").getText(); msgBody.setSignname(signName); //经办人(柜员)证件类型 String signCardType = document.selectSingleNode("/root/signCardType").getText(); msgBody.setSigncardtype(signCardType); //经办人(柜员)证件号码 String signCardNo = document.selectSingleNode("/root/signCardNo").getText(); msgBody.setSigncardno(signCardNo); //经办人(柜员)电话 String signTel = document.selectSingleNode("/root/signTel").getText(); msgBody.setSigntel(signTel); } /** * 修改客户信息 */ private void getMsgBody4UpdateCustomerInfo(JSSelfCounterMsgBody msgBody, Document document) { //签约账号 String acctNo = document.selectSingleNode("/root/acctNo").getText(); msgBody.setAccountcode(acctNo); //账户名称 String acctName = document.selectSingleNode("/root/acctName").getText(); msgBody.setAccountname(acctName); //账户开户行编码 String acctBankCode = document.selectSingleNode("/root/acctBankCode").getText(); msgBody.setBankcode(acctBankCode); //客户号 String customNo = document.selectSingleNode("/root/customNo").getText(); msgBody.setCustomno(customNo); //客户名称 String customName = document.selectSingleNode("/root/customName").getText(); msgBody.setCustomname(customName); //所属机构 String belongOrg = document.selectSingleNode("/root/belongOrg").getText(); msgBody.setBelongorg(belongOrg); //营业执照号码 String liNo = document.selectSingleNode("/root/liNo").getText(); msgBody.setLi_no(liNo); //企业组织机构代码 String orgCode = document.selectSingleNode("/root/orgCode").getText(); msgBody.setOrg_code(orgCode); //法人代表名称 String loaderName = document.selectSingleNode("/root/loaderName").getText(); msgBody.setLoadername(loaderName); //法人证件类型 String idType = document.selectSingleNode("/root/idType").getText(); msgBody.setIdtype(idType); //法人证件号码 String idNo = document.selectSingleNode("/root/idNo").getText(); msgBody.setIdno(idNo); //企业联系人 String contact = document.selectSingleNode("/root/contact").getText(); msgBody.setContact(contact); //企业联系人电话 String tel = document.selectSingleNode("/root/tel").getText(); msgBody.setTelephoneno(tel); //企业联系人邮箱 String email = document.selectSingleNode("/root/email").getText(); msgBody.setEmail(email); //企业联系人地址 String address = document.selectSingleNode("/root/address").getText(); msgBody.setAddress(address); //经办人(柜员)姓名 String signName = document.selectSingleNode("/root/signName").getText(); msgBody.setSignname(signName); //经办人(柜员)证件类型 String signCardType = document.selectSingleNode("/root/signCardType").getText(); msgBody.setSigncardtype(signCardType); //经办人(柜员)证件号码 String signCardNo = document.selectSingleNode("/root/signCardNo").getText(); msgBody.setSigncardno(signCardNo); //经办人(柜员)电话 String signTel = document.selectSingleNode("/root/signTel").getText(); msgBody.setSigntel(signTel); } /** * 解析签约接口 */ private void getMsgBody4Sign(JSSelfCounterMsgBody msgBody, Document document) { getMsgBody4UpdateCustomerInfo(msgBody, document); //预算单位操作员编码 String userCode = document.selectSingleNode("/root/userCode").getText(); msgBody.setUser_code(userCode); //预算单位操作员登录密码(BASE64加密)(默认密码base64(123456)) String userPwd = document.selectSingleNode("/root/userPwd").getText(); msgBody.setUser_password(userPwd); //预算单位操作员姓名 String userName = document.selectSingleNode("/root/userName").getText(); msgBody.setUser_name(userName); //预算单位操作员证件类型 String userCardType = document.selectSingleNode("/root/userCardType").getText(); msgBody.setUser_card_type(userCardType); //预算单位操作员证件号码 String userCardNo = document.selectSingleNode("/root/userCardNo").getText(); msgBody.setUser_card_no(userCardNo); //Ukey编码 String ukeyCode = document.selectSingleNode("/root/ukeyCode").getText(); msgBody.setUkey_code(ukeyCode); //操作员电话号码 String operTel = document.selectSingleNode("/root/operTel").getText(); msgBody.setOperTel(operTel); } /** * 业务处理 * * @param transCode * @param body */ private TransResultDTO doBusiness(JSSelfCounterMsgBody msgBody) throws Exception { //交易码 String transCode = msgBody.getMsgHead().getTransCode(); TransResultDTO resultDto = null; // 请求条件信息 if(JSSelfCounterConstant.SIGN.equalsIgnoreCase(transCode)){ resultDto = jsSelfCounterBusinessServiceImpl.sign(msgBody); }else if(JSSelfCounterConstant.UPDATE_CUSTOMER_INFO.equalsIgnoreCase(transCode)){ resultDto = jsSelfCounterBusinessServiceImpl.updateCustomerInfo(msgBody); }else if(JSSelfCounterConstant.CANCEL_CUSTOMER.equalsIgnoreCase(transCode)){ resultDto = jsSelfCounterBusinessServiceImpl.cancelCustomer(msgBody); }else if(JSSelfCounterConstant.UPDATE_OPERATOR_INFO.equalsIgnoreCase(transCode)){ resultDto = jsSelfCounterBusinessServiceImpl.updateOperatorInfo(msgBody); }else if(JSSelfCounterConstant.UPDATE_UKEY_INFO.equalsIgnoreCase(transCode)){ resultDto = jsSelfCounterBusinessServiceImpl.updateUkeyInfo(msgBody); }else if(JSSelfCounterConstant.RESET_OPERATOR_PASSWORD.equalsIgnoreCase(transCode)){ resultDto = jsSelfCounterBusinessServiceImpl.resetOperatorPassword(msgBody); }else if(JSSelfCounterConstant.CANCEL_OPERATOR.equalsIgnoreCase(transCode)){ resultDto = jsSelfCounterBusinessServiceImpl.cancelOperator(msgBody); }else{ throw new PbException("请添加方法!"); } return resultDto; } /** * 生成成功响应报文 * * @param transCode * @param resultDto * @param msgBody * @return * @throws Exception */ private byte[] doResponse(String transCode, TransResultDTO resultDto, JSSelfCounterMsgBody msgBody) throws Exception { String resMsgHead = transCode;//报文头包括6位报文长度+4为交易码 //开始拼装报文体 Document document = DocumentHelper.createDocument(); document.setXMLEncoding(JSSelfCounterConstant.CHAR_SET); String resp_code = ""; if (resultDto.getResStatus() == TransReturnDTO.SUCESS) { //成功返回0000 resp_code = SsConstant.CTJ_SUCCUSS_CODE; } else { //失败返回0001 resp_code = SsConstant.CTJ_FAILURE_CODE; } XmlUtils.createXMLByXPath(document, "/root/resCode",resp_code);//结果码 XmlUtils.createXMLByXPath(document, "/root/resDes",resultDto.getResMsg());//结果信息 String resMsgBody = document.asXML(); //长度放到报文头中 int length = resMsgHead.getBytes(JSSelfCounterConstant.CHAR_SET).length + resMsgBody.getBytes(JSSelfCounterConstant.CHAR_SET).length; resMsgHead = TransUtil.getFixlenStrByAddZero(String.valueOf(length), 6)+resMsgHead; return (resMsgHead + resMsgBody).getBytes(JSSelfCounterConstant.CHAR_SET); } /** * 生成失败响应报文 */ private byte[] errorResponse(String errorMsg, String transCode) throws UnsupportedEncodingException { if(errorMsg == null){ errorMsg = "交易返回信息为空,请检查柜面日志"; } //开始拼装报文体 Document document = DocumentHelper.createDocument(); document.setXMLEncoding(JSSelfCounterConstant.CHAR_SET); String resp_code = ""; //失败返回0001 resp_code = SsConstant.CTJ_FAILURE_CODE; XmlUtils.createXMLByXPath(document, "/root/resCode",resp_code);//结果码 XmlUtils.createXMLByXPath(document, "/root/resDes",errorMsg);//结果信息 String resMsgBody = document.asXML(); //长度放到报文头中 int length = transCode.getBytes(JSSelfCounterConstant.CHAR_SET).length + resMsgBody.getBytes(JSSelfCounterConstant.CHAR_SET).length; String resMsgHead = TransUtil.getFixlenStrByAddZero(String.valueOf(length), 6)+transCode; return (resMsgHead + resMsgBody).getBytes(JSSelfCounterConstant.CHAR_SET); } }
我曾七次鄙视自己的灵魂:
第一次,当它本可进取时,却故作谦卑;
第二次,当它空虚时,用爱欲来填充;
第三次,在困难和容易之间,它选择了容易;
第四次,它犯了错,却借由别人也会犯错来宽慰自己;
第五次,它自由软弱,却把它认为是生命的坚韧;
第六次,当它鄙夷一张丑恶的嘴脸时,却不知那正是自己面具中的一副;
第七次,它侧身于生活的污泥中虽不甘心,却又畏首畏尾。