# nettyServer **Repository Path**: mhe/nettyServer ## Basic Information - **Project Name**: nettyServer - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2017-12-13 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ##A server baseed on netty add sping IOC without XML > netty同时处理HTTP和Websocket,并将HTTP请求路由到相应Action中;使用ehcache实现Session;spring IOC做管理容器,mybatis 做sql数据库ORM;spring data mongoDB做mongo的ORM;HikariCP做sql数据库连接池;Gson用于json解析和生成;logback日志处理。 ####netty处理HTTP和websocket - smart.core.netty.HttpHandler:是一个自定义的ChannelHandler用于处理HTTP 和Websocket请求 - Handler分别处理HTTP和Websocket ```java public void messageReceived(ChannelHandlerContext ctx, Object msg) { if (msg instanceof FullHttpRequest) {//如果是HTTP请求,进行HTTP操作 handleHttpRequest(ctx, (FullHttpRequest) msg); } else if (msg instanceof WebSocketFrame) {//如果是Websocket请求,则进行websocket操作 handleWebSocketFrame(ctx, (WebSocketFrame) msg); } } ``` - 由于websocket也是基于HTTP的,需要判断是websocket后,将HTTP升级为Websocket ```java private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) { logger.warn("uri:" + req.uri()); if (req.uri().startsWith("/ws/join")) {//如果urL开头为/ws/join则升级为websocket mac = wsBeforeHandler(ctx, req); if (mac == null || mac.length() < 1) { RespTools.paraErrorBack(ctx,req,null); return; } WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory( getWebSocketLocation(req), null, true); handshaker = wsFactory.newHandshaker(req); if (handshaker == null) { WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel()); } else { handshaker.handshake(ctx.channel(), req); } } else {//是HTTP请求则路由到Action RouteResult routeResult = rs.getRouter().route(req.method(), req.uri()); Action action = routeResult.target(); action.act(ctx, req); } } ``` - websocket请求处理,这里是从websocket请求中获取客户端传来的json字符串,并将字符串转为javabean ```java private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) { // Check for closing frame if (frame instanceof CloseWebSocketFrame) { handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame.retain()); return; } if (frame instanceof PingWebSocketFrame) { ctx.write(new PongWebSocketFrame(frame.content().retain())); return; } if (frame instanceof TextWebSocketFrame) { devicePool.join(ctx.channel(), mac); String json = ((TextWebSocketFrame) frame).text(); Logic.ReqRespType data= JsonTools.read(json,Logic.ReqRespType.class); //... return; } } ``` - 如果是HTTP则需在RouterSetting中配置路由. 比如r.POST("api/get_verify_code", getVerifyCodeAct): 将url为"api/get_verify_code"的POST请求路由到LoginAct中 ```java public class RouterSetting { @Autowired private Router router; @Autowired private GetVerifyCodeAct getVerifyCodeAct;//w @Autowired private LoginAct loginAct; @Autowired private RegisterAct registerAcc; public Router getRouter() { routerConfig(this.router); return this.router; } private void routerConfig(Router r) { r.POST("api/get_verify_code", getVerifyCodeAct); r.ANY("api/login", loginAct); r.GET("api/register", registerAcc); } } ``` - Action处理HTTP请求并返回 ```java @Controller public class LoginAct implements Action { private static final Logger logger = LoggerFactory.getLogger(LoginAct.class); @Override public void act(ChannelHandlerContext ctx, FullHttpRequest req) { String ip = HttpTools.getIp(req); String body = Convert.buf2Str(req.content()); Get.Login get = JsonTools.read(body, Get.Login.class);//1.得到HTTP传来的json数据解析为javabean Sub.Register back;//构建返回给客户端的javabean的实例 //... HttpTools.sendCorrectResp(ctx, req, back);//返回给客户端HTTP Response } } ``` - 添加Session(依靠ehcache) ```java private void addSession(long userId, String ip) { Logic.DeviceSession session = new Logic.DeviceSession(ip, ""); Cache.add(userId + "", session, "6mn");//设置session的缓存时间为6分钟 //debugSession(userId); } ``` - 从HTTP请求中获取IP地址 ``` String ip = HttpTools.getIp(req); ``` ####netty参数设置 ``` port=8090 netty.boss.thread.count=2 netty.worker.thread.count=1 netty.so.keepalive=true netty.so.backlog=100 ``` ####项目依赖 ```groovy //---------------------单元测试---------------------------- testCompile group: 'junit', name: 'junit', version: '4.11' //--------------------数据库驱动---------------------------- compile 'org.mongodb:mongodb-driver:3.2.2' compile 'mysql:mysql-connector-java:5.1.38' //-------------------数据库连接池--------------------------- compile 'com.zaxxer:HikariCP:2.4.5' //----------------------ORM------------------------------ compile group: 'org.mybatis', name: 'mybatis', version:mybatisVersion compile group: 'org.mybatis', name: 'mybatis-spring', version:mybatisSpringVersion //-----------------------缓存---------------------------- compile group: 'net.sf.ehcache', name: 'ehcache', version:ehcacheVersion //----------------------工具包---------------------------- compile 'commons-httpclient:commons-httpclient:3.1-rc1' compile 'org.javassist:javassist:3.20.0-GA' //---------------------日志处理---------------------------- compile 'org.slf4j:slf4j-api:1.7.21' compile 'ch.qos.logback:logback-core:1.1.7' compile 'ch.qos.logback:logback-classic:1.1.7' //---------------------json处理--------------------------- compile 'com.google.code.gson:gson:2.6.2' //---------------------netty----------------------------- compile group: 'io.netty', name: 'netty-all', version:nettyVersion //---------------------spring---------------------------- compile group: 'org.springframework', name: 'spring-test', version:springVersion compile group: 'org.springframework', name: 'spring-jdbc', version:springVersion compile(group: 'org.springframework', name: 'spring-context', version:springVersion) { exclude(module: 'commons-logging') } ```