├── .gitignore ├── .idea ├── artifacts │ ├── netty_war.xml │ ├── netty_war3.xml │ └── netty_war_exploded.xml ├── compiler.xml ├── inspectionProfiles │ └── Project_Default.xml ├── kotlinc.xml ├── libraries │ ├── Maven__aopalliance_aopalliance_1_0.xml │ ├── Maven__com_alibaba_druid_1_0_9.xml │ ├── Maven__com_alibaba_fastjson_1_2_3.xml │ ├── Maven__com_aliyun_aliyun_java_sdk_core_2_4_2.xml │ ├── Maven__com_aliyun_aliyun_java_sdk_sms_3_0_0_rc1.xml │ ├── Maven__com_dyuproject_protostuff_protostuff_api_1_0_9.xml │ ├── Maven__com_dyuproject_protostuff_protostuff_collectionschema_1_0_9.xml │ ├── Maven__com_dyuproject_protostuff_protostuff_core_1_0_9.xml │ ├── Maven__com_dyuproject_protostuff_protostuff_runtime_1_0_9.xml │ ├── Maven__com_fasterxml_jackson_core_jackson_annotations_2_5_0.xml │ ├── Maven__com_fasterxml_jackson_core_jackson_core_2_5_0.xml │ ├── Maven__com_fasterxml_jackson_core_jackson_databind_2_5_0.xml │ ├── Maven__com_google_protobuf_protobuf_java_3_2_0.xml │ ├── Maven__commons_codec_commons_codec_1_6.xml │ ├── Maven__commons_fileupload_commons_fileupload_1_3_1.xml │ ├── Maven__commons_io_commons_io_2_2.xml │ ├── Maven__commons_logging_commons_logging_1_1_3.xml │ ├── Maven__commons_net_commons_net_3_3.xml │ ├── Maven__io_netty_netty_all_4_1_6_Final.xml │ ├── Maven__javax_servlet_jsp_api_2_0.xml │ ├── Maven__javax_servlet_servlet_api_2_5.xml │ ├── Maven__javax_transaction_jta_1_1.xml │ ├── Maven__joda_time_joda_time_2_5.xml │ ├── Maven__jstl_jstl_1_2.xml │ ├── Maven__junit_junit_4_12.xml │ ├── Maven__log4j_log4j_1_2_16.xml │ ├── Maven__mysql_mysql_connector_java_5_1_34.xml │ ├── Maven__org_apache_commons_commons_collections4_4_0.xml │ ├── Maven__org_apache_commons_commons_lang3_3_3_2.xml │ ├── Maven__org_apache_commons_commons_pool2_2_3.xml │ ├── Maven__org_apache_httpcomponents_httpclient_4_3_5.xml │ ├── Maven__org_apache_httpcomponents_httpcore_4_3_2.xml │ ├── Maven__org_aspectj_aspectjweaver_1_8_9.xml │ ├── Maven__org_codehaus_jackson_jackson_core_asl_1_9_13.xml │ ├── Maven__org_codehaus_jackson_jackson_mapper_asl_1_9_13.xml │ ├── Maven__org_hamcrest_hamcrest_core_1_3.xml │ ├── Maven__org_mybatis_mybatis_3_2_8.xml │ ├── Maven__org_mybatis_mybatis_spring_1_2_2.xml │ ├── Maven__org_objenesis_objenesis_2_1.xml │ ├── Maven__org_quartz_scheduler_quartz_1_8_5.xml │ ├── Maven__org_slf4j_jcl_over_slf4j_1_7_13.xml │ ├── Maven__org_slf4j_slf4j_api_1_7_13.xml │ ├── Maven__org_slf4j_slf4j_log4j12_1_6_4.xml │ ├── Maven__org_springframework_data_spring_data_redis_1_6_4_RELEASE.xml │ ├── Maven__org_springframework_spring_aop_4_1_9_RELEASE.xml │ ├── Maven__org_springframework_spring_aspects_4_2_6_RELEASE.xml │ ├── Maven__org_springframework_spring_beans_4_2_6_RELEASE.xml │ ├── Maven__org_springframework_spring_context_4_2_6_RELEASE.xml │ ├── Maven__org_springframework_spring_context_support_4_1_9_RELEASE.xml │ ├── Maven__org_springframework_spring_core_4_2_6_RELEASE.xml │ ├── Maven__org_springframework_spring_expression_4_2_6_RELEASE.xml │ ├── Maven__org_springframework_spring_jdbc_4_2_6_RELEASE.xml │ ├── Maven__org_springframework_spring_oxm_4_1_9_RELEASE.xml │ ├── Maven__org_springframework_spring_test_4_2_6_RELEASE.xml │ ├── Maven__org_springframework_spring_tx_4_2_6_RELEASE.xml │ ├── Maven__org_springframework_spring_web_4_2_6_RELEASE.xml │ ├── Maven__org_springframework_spring_webmvc_4_2_6_RELEASE.xml │ └── Maven__redis_clients_jedis_2_8_0.xml ├── misc.xml ├── modules.xml ├── uiDesigner.xml ├── vcs.xml └── workspace.xml ├── README.md ├── how-build-ThreadPool └── README.md ├── how-deploy-druid(integration-springboot) ├── README.md └── druid.png ├── how-deploy-redis_sentinel(window) ├── README.md ├── download.png ├── error_MarkMan.png ├── info_MarkMan.png ├── master_MarkMan.png ├── sentinel.png ├── slave_MarkMan.png ├── switchmaster_MarkMan.png ├── swithMaster_MarkMan.png └── test_MarkMan.png ├── netty.iml ├── picture ├── 1.PNG ├── RPC.png └── horizon.PNG ├── pom.xml ├── src └── main │ ├── java │ └── com │ │ └── haro │ │ └── netty │ │ ├── cache │ │ ├── RedisCache.java │ │ └── RedisClusterCache.java │ │ ├── iot │ │ ├── netty │ │ │ ├── cfg │ │ │ │ └── SpringConfig.java │ │ │ ├── handler │ │ │ │ ├── HeartbeatHandler.java │ │ │ │ ├── KeepAliveHandler.java │ │ │ │ ├── RemoteControlHandler.java │ │ │ │ ├── ServerHandler.java │ │ │ │ └── StringProtocolInitalizer.java │ │ │ └── server │ │ │ │ └── TCPServer.java │ │ ├── staticOfFinal │ │ │ ├── NettyChannelMap.java │ │ │ └── proto │ │ │ │ ├── IOTValue.proto │ │ │ │ ├── IOTValueProto.java │ │ │ │ ├── common │ │ │ │ ├── bean │ │ │ │ │ ├── RpcRequest.java │ │ │ │ │ └── RpcResponse.java │ │ │ │ ├── codec │ │ │ │ │ ├── RpcDecoder.java │ │ │ │ │ └── RpcEncoder.java │ │ │ │ └── util │ │ │ │ │ ├── CollectionUtil.java │ │ │ │ │ ├── SerializationUtil.java │ │ │ │ │ └── StringUtil.java │ │ │ │ └── protocol │ │ │ │ └── HProtocolHeader.java │ │ ├── thread │ │ │ ├── SaveDeviceIccidTask.java │ │ │ ├── SendCommandForLightTask.java │ │ │ └── UpdateDeviceStatusTask.java │ │ └── threadpool │ │ │ ├── ExecutorProcessPool.java │ │ │ └── ExecutorServiceFactory.java │ │ ├── quartz │ │ └── IotQuartz.java │ │ ├── service │ │ ├── DeviceStatusService.java │ │ ├── Impl │ │ │ ├── DeviceStatusServiceImpl.java │ │ │ ├── QueryStatusForLightServiceImpl.java │ │ │ └── StatusDeviceServiceImpl.java │ │ ├── QueryStatusForLightService.java │ │ └── StatusDeviceService.java │ │ ├── test │ │ ├── mapper │ │ │ └── DeviceStatusMapper.java │ │ └── pojo │ │ │ └── DeviceStatus.java │ │ └── util │ │ ├── Base64Utils.java │ │ ├── ByteUtil.java │ │ ├── Charsets.java │ │ ├── ContextHolderUtils.java │ │ ├── DataUtils.java │ │ ├── IpUtil.java │ │ └── SpringUtil.java │ ├── resources │ ├── dbconfig.properties │ ├── log4j.properties │ ├── netty-server.properties │ ├── redis.properties │ ├── spring-mybatis.xml │ ├── spring-quartz.xml │ ├── spring-redis.xml │ └── spring.xml │ └── webapp │ └── WEB-INF │ └── web.xml └── test └── main └── java └── client ├── Client.java ├── ClientHandler.java └── Common.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | # Compiled class file 4 | *.class 5 | 6 | # Log file 7 | *.log 8 | 9 | # BlueJ files 10 | *.ctxt 11 | 12 | # Mobile Tools for Java (J2ME) 13 | .mtj.tmp/ 14 | 15 | # Package Files # 16 | *.jar 17 | *.war 18 | *.ear 19 | *.zip 20 | *.tar.gz 21 | *.rar 22 | 23 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 24 | hs_err_pid* 25 | 26 | -------------------------------------------------------------------------------- /.idea/artifacts/netty_war.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/target 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/artifacts/netty_war3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/out/artifacts/netty_war3 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/artifacts/netty_war_exploded.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | $PROJECT_DIR$/target/netty 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 36 | -------------------------------------------------------------------------------- /.idea/kotlinc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__aopalliance_aopalliance_1_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_alibaba_druid_1_0_9.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_alibaba_fastjson_1_2_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_aliyun_aliyun_java_sdk_core_2_4_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_aliyun_aliyun_java_sdk_sms_3_0_0_rc1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_dyuproject_protostuff_protostuff_api_1_0_9.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_dyuproject_protostuff_protostuff_collectionschema_1_0_9.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_dyuproject_protostuff_protostuff_core_1_0_9.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_dyuproject_protostuff_protostuff_runtime_1_0_9.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_annotations_2_5_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_core_2_5_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_fasterxml_jackson_core_jackson_databind_2_5_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__com_google_protobuf_protobuf_java_3_2_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__commons_codec_commons_codec_1_6.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__commons_fileupload_commons_fileupload_1_3_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__commons_io_commons_io_2_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__commons_logging_commons_logging_1_1_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__commons_net_commons_net_3_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__io_netty_netty_all_4_1_6_Final.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__javax_servlet_jsp_api_2_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__javax_servlet_servlet_api_2_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__javax_transaction_jta_1_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__joda_time_joda_time_2_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__jstl_jstl_1_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__junit_junit_4_12.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__log4j_log4j_1_2_16.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__mysql_mysql_connector_java_5_1_34.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_commons_commons_collections4_4_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_commons_commons_lang3_3_3_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_commons_commons_pool2_2_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_httpcomponents_httpclient_4_3_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_apache_httpcomponents_httpcore_4_3_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_aspectj_aspectjweaver_1_8_9.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_codehaus_jackson_jackson_core_asl_1_9_13.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_codehaus_jackson_jackson_mapper_asl_1_9_13.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_hamcrest_hamcrest_core_1_3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_mybatis_mybatis_3_2_8.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_mybatis_mybatis_spring_1_2_2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_objenesis_objenesis_2_1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_quartz_scheduler_quartz_1_8_5.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_slf4j_jcl_over_slf4j_1_7_13.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_slf4j_slf4j_api_1_7_13.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_slf4j_slf4j_log4j12_1_6_4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_data_spring_data_redis_1_6_4_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_aop_4_1_9_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_aspects_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_beans_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_context_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_context_support_4_1_9_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_core_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_expression_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_jdbc_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_oxm_4_1_9_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_test_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_tx_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_web_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__org_springframework_spring_webmvc_4_2_6_RELEASE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/libraries/Maven__redis_clients_jedis_2_8_0.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

优雅的物联网架构

2 |

horizon

3 | 4 | ## SensIot V2.0 5 | 6 | [新版基于SpringBoot全面升级并拆分模块!](https://github.com/sanshengshui/HCW/tree/springboot) 7 | 8 |

技术选型:

9 | 10 | - [Netty](https://github.com/netty/netty) 11 | - Maven 12 | - Spring 13 | - Mybatis(最少配置方案) 14 | - [Druid(数据源配置 sql防注入 sql性能监控)](https://github.com/sanshengshui/HCW/blob/springboot/how-deploy-druid(integration-springboot)/README.md) 15 | - Google Protobuf解编码框架 Prostostuff:它基于Protobuf序列化框架,面向POJO,无需编写.proto文件。 16 | - Quartz时间调度 17 | - [Redis Sentinel主从高可用方案](https://github.com/sanshengshui/HCW/tree/springboot/how-deploy-redis_sentinel(window)/README.md) 18 | - Redis Cluster集群高可用方案(未整合) 19 | - RPC(远程过程调用) 20 | - ZooKeeper(未实现):提供服务注册与发现功能,开发分布式系统的必备选择,同时它也具备天生的集群能力。 21 | - 持续更新中 @>+++++++<@ 22 |
23 | 24 | RPC,即Remote Proceduce Call(远程过程调用),说的通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样。 25 | 26 | ``` 27 | RPC可基于HTTP或TCP协议,Web Service就是基于HTTP协议的RPC,它具有良好的跨平台性,但其性能却 28 | 不如基于TCP协议的RPC。会2方面会直接影响RPC的性能,一是传输方式,二是序列化。 29 | 众所周知,TCP是传输层协议,HTTP是应用层协议,而传输层较应用层更加底层,在数据传输方面,较底层越 30 | 快,因此,在一般情况下,TCP一定比HTTP快。就序列化而言,Java提供了默认的序列化方式,但在高并发的情况 31 | 下,这种方式将会带来一些性能上的瓶颈,于是市面上出现了一系列优秀的序列化框架,比如:Protobuf,Kryo, 32 | Hession,Jackson等,它们可以取代Java默认的序列化,从而提供更高效的性能。 33 | 为了支持高并发,传统的阻塞式IO显然不太合适,因此我们需要异步的IO,即NIO。Java提供了NIO的解决方案, 34 | Java7也提供了更优秀的NIO.2支持,用Java实现了NIO并不是遥不可及的事情,只是需要我们熟悉NIO的技术细节。 35 | 我们需要将服务器部署在分布式环境下的不同节点上,通过服务注册的方式,让客户端来自动发现当前可用的服务, 36 | 并调用这些服务。这需要一种服务注册表(Service Registry)的组件,让它来注册分布式环境下所有的服务地址( 37 | 包括:主机号与端口号)。 38 | 每台Server上可发布多个Service,这些Service共用一个host与port,在分布式环境下会提供Server共同对外提供 39 | Service。此外,为防止Service Registry出现单点故障,因此需要将其搭建为集群环境。 40 | ``` 41 | 42 | 应用,服务,服务注册表之间的关系见下图: 43 | ![RPC](picture/RPC.png) 44 | 45 | Netty基本功能实现: 46 | 47 | ``` 48 | (1)心跳检测 49 | 基本解释:客户端异常掉线,比如断开网线或者断电等情况下,客户端的channel对象不会自动关闭,所以才引入了心跳的机制, 50 | 也就是服务器端通过监测在心跳期间内(1分钟)是否收到了客户端发过来的消息,来判断是否可以和客户端进行通信, 51 | 如果没有收到任何消息,则视为客户端掉线。心跳机制就是为了解决你说的这个问题的。不光是netty,所有基于socket的通信都有这个问题, 52 | 因为客户端和服务端是基于消息的协议,只有客户端主动发出断开的消息给服务端,服务端才能明确知道客户端断开了连接, 53 | 直接拔掉网线或者断电的情况下,属于底层的异常,客户端程序是根本监测不到的,即使你的客户端程序能够监测到,也没有用, 54 | 因为此时网线已经被拔掉了,根本没法给服务端发送消息。所以服务端才引入了心跳机制来对应这种异常情况,相当于超时机制, 55 | 超过规定时间没有接到消息,就视为客户端掉线了,以释放服务端的资源。 56 | ``` 57 | 58 | Google的[Protobuf](https://github.com/google/protobuf)在业界非常流行 59 | 60 | ``` 61 | (1)在谷歌内部长期使用,产品成熟度高; 62 | (2)跨语言 支持多种语言,包括C++,Java和Python; 63 | (3)编码后的消息更小,更加有利于存储和传输; 64 | (4)编解码的性能非常高; 65 | (5)支持不同协议的前向兼容; 66 | (6)支持定义可选和必选字段。 67 | ``` 68 | 69 |
70 | 71 | [Druid](https://github.com/alibaba/druid)号称是Java语言中最好的数据库连接池 72 | ``` 73 | 1 可以监控数据库访问性能,Druid内置提供了一个功能强大的StatFilter插件,能够详细统计SQL的执行性能,这对于线上分析数据库 74 | 访问性能有帮助。 75 | 2 替换DBCP和C3P0。Druid提供了一个高效,功能强大,可扩展性好的数据库连接池。 76 | 3 数据库密码加密。直接把数据库密码写在配置文件中,这是不好的行为,容易导致安全问题。DruidDruiver和DruidDataSource都支持 77 | PasswordCallback。 78 | 4 SQL执行日志,Druid提供了不同的LogFilter,能够支持Common-Logging,Log4j和JdkLog,你可以按需要选择相应的LogFilter,监控 79 | 你应用的数据库访问情况。 80 | 5 能够提供基于Filter - Chain模式的插件体系 81 | ``` 82 | 下面介绍下如何在项目中集成Druid: 83 |
84 | 1. maven依赖 85 | ``` 86 | 87 | com.alibaba 88 | druid 89 | ${druid.version} 90 | 91 | ``` 92 | 2. 配置web.xml 93 | ``` 94 | 95 | 96 | DruidStatView 97 | com.alibaba.druid.support.http.StatViewServlet 98 | 99 | 100 | DruidStatView 101 | /druid/* 102 | 103 | 104 | 105 | DruidWebStatFilter 106 | com.alibaba.druid.support.http.WebStatFilter 107 | 108 | exclusions 109 | *.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/* 110 | 111 | 112 | 113 | DruidWebStatFilter 114 | /* 115 | 116 | ``` 117 | 118 | 3. spring.xml中配置druid数据源 119 | ``` 120 | 121 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | ``` 137 | **添加之后的效果如下:**
138 | ![Druid Monitor](picture/1.PNG) 139 |
140 | 141 | ## **二、测试**
142 | 143 | ### 单客户端测试以及调试功能(SingleTest) 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 |
frame_headDirCommunicationIDSIMCCIDProduccommdata_lengthdataframe_tail
帧头方向身份码SIM卡编码产品码功能码数据长度数据帧尾
占用长度(字节)4 bytes1 byte13byte20 byte11 byte2 bytes不固定2 bytes
Value(数值)_YD_0x01-------0x030x0A详见如下见第二节##
196 | 197 | #### 测试数据 198 | 199 | ```text 200 | 设备发送心跳包: 201 | 5F 59 44 5F 02 EE 00 00 00 00 AA BB CC 11 22 33 55 00 38 39 38 36 30 36 31 36 30 32 30 30 34 32 36 38 39 35 37 35 03 F5 02 00 0C 00 23 23 202 | 服务器回送心跳包 203 | 5F 59 44 5F 02 06 80 43 00 12 57 33 57 35 33 39 20 00 38 39 38 36 30 36 31 36 30 32 30 30 34 32 36 38 39 35 37 35 03 F6 00 00 23 23 204 | 远程授权: 205 | 5F 59 44 5F 02 06 80 43 00 12 57 33 57 35 33 39 20 00 38 39 38 36 30 36 31 36 30 32 30 30 34 32 36 38 39 35 37 35 03 F2 01 00 01 23 23 206 | 设备回送: 207 | 5F 59 44 5F 02 06 80 43 00 12 57 33 57 35 33 39 20 00 38 39 38 36 30 36 31 36 30 32 30 30 34 32 36 38 39 35 37 35 03 F3 01 00 01 23 23 208 | ``` 209 | 210 | 211 | 212 | ### 多客户端测试以及性能和压力测试 213 | 1. client模块中的`client.Client`类提供了进行压力测试的方法,可以修改启动客户端连接的数量`Client.clientNum`, 214 | 以及每秒向服务器发送的协议的频率`Client.frequency`进行压力测试。
215 | 2. CPU 8核E3-1231v3, 每个服务分配1G的堆内存,启动5000个客户端后(需要一定时间), 216 | 不停给自己发送协议消息,发现auth、logic、gate服务占用的cpu非常低,客户端能够立即收到响应。对应的TPS统计将在后续加入。
-------------------------------------------------------------------------------- /how-build-ThreadPool/README.md: -------------------------------------------------------------------------------- 1 | ## 核心线程池的内部实现 2 | 3 | ```java 4 | 5 | ``` 6 | -------------------------------------------------------------------------------- /how-deploy-druid(integration-springboot)/README.md: -------------------------------------------------------------------------------- 1 | ## 在SpringBoot中使用Druid作为数据源 2 | 3 | ### Druid介绍 4 | Druid号称是Java语言中最好的数据源连接池。 5 | 1. 可以监控数据库访问性能,Druid内置提供了一个功能强大的StatFilter插件,能够详细统计SQL的执行性能,这对于线上分析数据库访问性能有帮助。 6 | 2. 替换DBCP和C3PO。Druid提供了一个高晓,功能强大,可扩张性好的数据库连接池。 7 | 3. 数据库密码加密。直接把数据库密码写在配置文件中,这是不好的行为,容易导致安全问题。DruidDriver和DruidDataSource都支持PasswordCallback. 8 | 4. SQL执行日志,Druid提供了不同的LogFilter,能够支持Common-Logging、Log4j和JdkLog,你可以按需要选择相应的LogFilter,监控你应用的数据库访问情况。 9 | 5. 能够提供基于Filter-Chain模式的插件体系。 10 | ### 下面介绍下如何在SpringBoot项目中集成Druid: 11 | #### 1.maven依赖 12 | 13 | ```xml 14 | 15 | com.alibaba 16 | druid 17 | ${druid-version} 18 | 19 | ``` 20 | #### 2.配置数据源相关信息 21 | - [x] **application.properties** 22 | 23 | ```xml 24 | # 数据库访问配置 25 | # 主数据源,默认的 26 | spring.datasource.type=com.alibaba.druid.pool.DruidDataSource 27 | spring.datasource.driver-class-name=com.mysql.jdbc.Driver 28 | spring.datasource.url=jdbc:mysql://localhost:3306/test 29 | spring.datasource.username=root 30 | spring.datasource.password=123456 31 | 32 | # 下面为连接池的补充设置,应用到上面所有数据源中 33 | # 初始化大小,最小,最大 34 | spring.datasource.initialSize=5 35 | spring.datasource.minIdle=5 36 | spring.datasource.maxActive=20 37 | # 配置获取连接等待超时的时间 38 | spring.datasource.maxWait=60000 39 | # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 40 | spring.datasource.timeBetweenEvictionRunsMillis=60000 41 | # 配置一个连接在池中最小生存的时间,单位是毫秒 42 | spring.datasource.minEvictableIdleTimeMillis=300000 43 | spring.datasource.validationQuery=SELECT 1 FROM DUAL 44 | spring.datasource.testWhileIdle=true 45 | spring.datasource.testOnBorrow=false 46 | spring.datasource.testOnReturn=false 47 | # 打开PSCache,并且指定每个连接上PSCache的大小 48 | spring.datasource.poolPreparedStatements=true 49 | spring.datasource.maxPoolPreparedStatementPerConnectionSize=20 50 | # 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙 51 | spring.datasource.filters=stat,wall,log4j 52 | # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 53 | spring.datasource.connectionProperties=druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000 54 | # 合并多个DruidDataSource的监控数据 55 | #spring.datasource.useGlobalDataSourceStat=true 56 | ``` 57 | - [x] **SpringBoot Druid数据源配置** 58 | ```java 59 | import com.alibaba.druid.pool.DruidDataSource; 60 | import com.alibaba.druid.support.http.StatViewServlet; 61 | import com.alibaba.druid.support.http.WebStatFilter; 62 | import org.slf4j.Logger; 63 | import org.slf4j.LoggerFactory; 64 | import org.springframework.beans.factory.annotation.Value; 65 | import org.springframework.boot.web.servlet.FilterRegistrationBean; 66 | import org.springframework.boot.web.servlet.ServletRegistrationBean; 67 | import org.springframework.context.annotation.Bean; 68 | import org.springframework.context.annotation.Configuration; 69 | 70 | import javax.sql.DataSource; 71 | import java.sql.SQLException; 72 | 73 | /** 74 | * @author穆书伟 75 | * @description SpringBoot Druid数据源配置 76 | * @date 2017年12月7日 下午19:12 77 | */ 78 | @Configuration 79 | public class DruidConfig { 80 | 81 | private Logger logger = LoggerFactory.getLogger(DruidConfig.class); 82 | 83 | @Value("${spring.datasource.url}") 84 | private String dbUrl; 85 | 86 | @Value("${spring.datasource.username}") 87 | private String username; 88 | 89 | @Value("${spring.datasource.password}") 90 | private String password; 91 | 92 | @Value("${spring.datasource.driver-class-name}") 93 | private String driverClassName; 94 | 95 | @Value("${spring.datasource.initialSize}") 96 | private int initialSize; 97 | 98 | @Value("${spring.datasource.minIdle}") 99 | private int minIdle; 100 | 101 | @Value("${spring.datasource.maxActive}") 102 | private int maxActive; 103 | 104 | @Value("${spring.datasource.maxWait}") 105 | private int maxWait; 106 | 107 | @Value("${spring.datasource.timeBetweenEvictionRunsMillis}") 108 | private int timeBetweenEvictionRunsMillis; 109 | 110 | @Value("${spring.datasource.minEvictableIdleTimeMillis}") 111 | private int minEvictableIdleTimeMillis; 112 | 113 | @Value("${spring.datasource.validationQuery}") 114 | private String validationQuery; 115 | 116 | @Value("${spring.datasource.testWhileIdle}") 117 | private boolean testWhileIdle; 118 | 119 | @Value("${spring.datasource.testOnBorrow}") 120 | private boolean testOnBorrow; 121 | 122 | @Value("${spring.datasource.testOnReturn}") 123 | private boolean testOnReturn; 124 | 125 | @Value("${spring.datasource.filters}") 126 | private String filters; 127 | 128 | @Value("${spring.datasource.logSlowSql}") 129 | private String logSlowSql; 130 | 131 | @Bean 132 | public ServletRegistrationBean druidServlet() { 133 | ServletRegistrationBean reg = new ServletRegistrationBean(); 134 | reg.setServlet(new StatViewServlet()); 135 | reg.addUrlMappings("/druid/*"); 136 | reg.addInitParameter("loginUsername", username); 137 | reg.addInitParameter("loginPassword", password); 138 | reg.addInitParameter("logSlowSql", logSlowSql); 139 | return reg; 140 | } 141 | 142 | @Bean 143 | public FilterRegistrationBean filterRegistrationBean() { 144 | FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); 145 | filterRegistrationBean.setFilter(new WebStatFilter()); 146 | filterRegistrationBean.addUrlPatterns("/*"); 147 | filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); 148 | filterRegistrationBean.addInitParameter("profileEnable", "true"); 149 | return filterRegistrationBean; 150 | } 151 | 152 | @Bean 153 | public DataSource druidDataSource() { 154 | DruidDataSource datasource = new DruidDataSource(); 155 | datasource.setUrl(dbUrl); 156 | datasource.setUsername(username); 157 | datasource.setPassword(password); 158 | datasource.setDriverClassName(driverClassName); 159 | datasource.setInitialSize(initialSize); 160 | datasource.setMinIdle(minIdle); 161 | datasource.setMaxActive(maxActive); 162 | datasource.setMaxWait(maxWait); 163 | datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); 164 | datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); 165 | datasource.setValidationQuery(validationQuery); 166 | datasource.setTestWhileIdle(testWhileIdle); 167 | datasource.setTestOnBorrow(testOnBorrow); 168 | datasource.setTestOnReturn(testOnReturn); 169 | try { 170 | datasource.setFilters(filters); 171 | } catch (SQLException e) { 172 | logger.error("druid configuration initialization filter", e); 173 | } 174 | return datasource; 175 | } 176 | 177 | } 178 | ``` 179 | 180 | #### 3.配置监控统计功能 181 | - [x] **配置Servlet** 182 | 183 | ```java 184 | import com.alibaba.druid.support.http.StatViewServlet; 185 | 186 | import javax.servlet.annotation.WebInitParam; 187 | import javax.servlet.annotation.WebServlet; 188 | 189 | @WebServlet(urlPatterns = "/druid/*", 190 | initParams={ 191 | @WebInitParam(name="allow",value="192.168.16.110,127.0.0.1"),// IP白名单 (没有配置或者为空,则允许所有访问) 192 | @WebInitParam(name="deny",value="192.168.16.111"),// IP黑名单 (存在共同时,deny优先于allow) 193 | @WebInitParam(name="loginUsername",value="jamesmsw"),// 用户名 194 | @WebInitParam(name="loginPassword",value="jamesmsw"),// 密码 195 | @WebInitParam(name="resetEnable",value="false")// 禁用HTML页面上的“Reset All”功能 196 | }) 197 | /** 198 | * @author 穆书伟 199 | * @date 2017年11月2日 10:19 200 | * @description Druid数据源连接池Servlet 201 | */ 202 | public class DruidStatViewServlet extends StatViewServlet { 203 | private static final long serialVersionUID = 1L; 204 | 205 | } 206 | 207 | ``` 208 | - [x] **配置Filter** 209 | ```java 210 | import com.alibaba.druid.support.http.WebStatFilter; 211 | 212 | import javax.servlet.annotation.WebFilter; 213 | import javax.servlet.annotation.WebInitParam; 214 | 215 | @WebFilter(filterName="druidWebStatFilter",urlPatterns="/*", 216 | initParams={ 217 | @WebInitParam(name="exclusions",value="*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*")// 忽略资源 218 | } 219 | ) 220 | /** 221 | * @author 穆书伟 222 | * @date 2017年11月2日 10:10 223 | * @description Druid数据连接池过滤器 224 | */ 225 | public class DruidStatFilter extends WebStatFilter { 226 | 227 | } 228 | 229 | ``` 230 | #### 4.使Druid数据源在SpringBoot中生效 231 | - [x] **配置SpringBoot主启动类** 232 | ```java 233 | import org.springframework.boot.SpringApplication; 234 | import org.springframework.boot.autoconfigure.SpringBootApplication; 235 | import org.springframework.boot.builder.SpringApplicationBuilder; 236 | import org.springframework.boot.web.servlet.ServletComponentScan; 237 | import org.springframework.boot.web.support.SpringBootServletInitializer; 238 | 239 | @ServletComponentScan //对就是它-就这一个注释! 240 | @SpringBootApplication 241 | public class WebApplication extends SpringBootServletInitializer { 242 | public WebApplication() { 243 | super(); 244 | setRegisterErrorPageFilter(false); 245 | } 246 | 247 | @Override 248 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 249 | return application.sources(WebApplication.class); 250 | } 251 | 252 | public static void main(String[] args) throws Exception { 253 | SpringApplication.run(WebApplication.class, args); 254 | } 255 | } 256 | ``` 257 | 然后启动项目后访问 http://localhost:port/druid/index.html 即可查看数据源及SQL统计等。
258 | 截图如下: 259 | ![image](druid.png) 260 | 261 | 262 | 263 | -------------------------------------------------------------------------------- /how-deploy-druid(integration-springboot)/druid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanshengshui/HCW/0a49311fad7026978265ac91d221251e985aee8a/how-deploy-druid(integration-springboot)/druid.png -------------------------------------------------------------------------------- /how-deploy-redis_sentinel(window)/README.md: -------------------------------------------------------------------------------- 1 |

redis sentinel部署(Windows下实现)

2 |

一.准备条件

3 | 4 | ``` 5 | 1.操作系统:win10 6 | 2.redis版本:redis-3.2.100 7 | ``` 8 |

二.下载redis并解压

9 | 10 |

1.下载

11 | 由于redis官方并不支持windows操作系统,所以官网上是下不到的,需要到gitlab上下载,下载地址如下:
12 | 13 | ``` 14 | https://github.com/MicrosoftArchive/redis/releases 15 | ``` 16 |

2.解压

17 | 将下载后的zip文件解压到本地磁盘,注意解压到的目录不能有中文和特殊字符,否则会出现很多奇葩的问题。解压后的目录如下:
18 |

download

19 |

三.HA配置

20 | 我们采用一主(master)二从(slave)三sentinel的架构模式来做演示
21 | 22 | ``` 23 | master ip:127.0.0.1 port:6379 24 | slave1 ip:127.0.0.1 port:6380 25 | slave2 ip:127.0.0.1 port:6381 26 | ``` 27 |

四.新建和修改配置文件

28 |

1.修改redis.conf配置文件

29 | 由于我们采用的是一主二从三sentinel的模式,所以我们需要6个配置文件,拷贝2份redis.conf配置文件,分别命名为redis6380.conf
30 | 和redis6381.conf,其中修改redis.conf配置文件的如下几个参数:
31 | 32 | ``` 33 | port 6379 34 | bind 127.0.0.1 35 | ``` 36 | 修改redis6380.conf配置文件的如下几个参数:
37 | 38 | ``` 39 | port 6380 40 | bind 127.0.0.1 41 | slaveof 127.0.0.1 6379 // 设置master服务器为6379 42 | ``` 43 | 同理修改redis6381.conf配置文件
44 |

2.创建并修改sentinel.conf

45 | 该模式使用了3sentinel,所以我们需要复制3份sentinel.conf配置文件,并分别命名为sentinel26479.conf和sentinel26579.conf,
46 | 其中修改sentinel.conf配置文件中的如下几个参数:
47 | 48 | ``` 49 | bind 0.0.0.0 50 | port 26379 // 当前Sentinel服务运行的端口 51 | sentinel monitor mymaster 127.0.0.1 6379 2 52 | sentinel down-after-milliseconds mymaster 5000 53 | sentinel parallel-syncs mymaster 1 54 | sentinel failover-timeout mymaster 15000 55 | ``` 56 | 同理,修改另外的两个配置文件
57 | 配置文件说明:
58 | 59 | ``` 60 | 1. port :当前Sentinel服务运行的端口 61 | 2.sentinel monitor mymaster 127.0.0.1 6379 2:Sentinel去监视一个名为mymaster的主redis实例,这个主实例的IP地址为本机地址 62 | 127.0.0.1,端口号为6379,而将这个主实例判断为失效至少需要2个 Sentinel进程的同意,只要同意Sentinel的数量不达标, 63 | 自动failover就不会执行 64 | 3.sentinel down-after-milliseconds mymaster 5000:指定了Sentinel认为Redis实例已经失效所需的毫秒数。当 实例超过该时间没有 65 | 返回PING,或者直接返回错误,那么Sentinel将这个实例标记为主观下线。只有一个 Sentinel进程将实例标记为主观下线并不一定会引 66 | 起实例的自动故障迁移:只有在足够数量的Sentinel都将一个实例标记为主观下线之后,实例才会被标记为客观下线,这时自动故障 67 | 迁移才会执行 68 | 4.sentinel parallel-syncs mymaster 1:指定了在执行故障转移时,最多可以有多少个从Redis实例在同步新的主实例,在从Redis实例 69 | 较多的情况下这个数字越小,同步的时间越长,完成故障转移所需的时间就越长 70 | 5.sentinel failover-timeout mymaster 15000:如果在该时间(ms)内未能完成failover操作,则认为该failover失败 71 | ``` 72 |

五.启动服务器

73 |

1、分别启动master,slave1,slave2

74 | 75 | 启动命令分别如下: 76 | 77 | ``` 78 | redis-server.exe redis.conf 79 | redis-server.exe redis6380.conf 80 | redis-server.exe redis6381.conf 81 | ``` 82 | 83 |

2、分别启动sentinel1,sentinel2,sentinel3

84 | 85 | 启动命令分别如下: 86 | 87 | ``` 88 | redis-server.exe sentinel.conf --sentinel 89 | redis-server.exe sentinel26479.conf --sentinel 90 | redis-server.exe sentinel26579.conf --sentinel 91 | ``` 92 | 93 | 服务启动成功后,界面显示如下:
94 | 95 | master redis服务器 96 |

download

97 | slaver redis服务器 98 |

download

99 | sentinel redis服务器 100 |

download

101 |

3、查看redis服务器状态

102 |

download

103 |

六、测试服务器

104 | 这里只做简单的测试 105 |

download

106 |

七、redis主从自动failover测试

107 |

1、停止master服务器

108 |

download

109 |

2、查看剩余服务器的状态

110 |

download

111 | 从上图中可以看出来,master的服务器端口从6379变成了6380,也就是说redis自动的实现了主从切换,我们可以在查看下sentinel 112 | 的状态,如下: 113 |

download

114 | 我们发现sentinel监控到127.0.0.1:6379已经无法ping通了,切换master服务器为127.0.0.1:6380 115 | 116 | 117 | -------------------------------------------------------------------------------- /how-deploy-redis_sentinel(window)/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanshengshui/HCW/0a49311fad7026978265ac91d221251e985aee8a/how-deploy-redis_sentinel(window)/download.png -------------------------------------------------------------------------------- /how-deploy-redis_sentinel(window)/error_MarkMan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanshengshui/HCW/0a49311fad7026978265ac91d221251e985aee8a/how-deploy-redis_sentinel(window)/error_MarkMan.png -------------------------------------------------------------------------------- /how-deploy-redis_sentinel(window)/info_MarkMan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanshengshui/HCW/0a49311fad7026978265ac91d221251e985aee8a/how-deploy-redis_sentinel(window)/info_MarkMan.png -------------------------------------------------------------------------------- /how-deploy-redis_sentinel(window)/master_MarkMan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanshengshui/HCW/0a49311fad7026978265ac91d221251e985aee8a/how-deploy-redis_sentinel(window)/master_MarkMan.png -------------------------------------------------------------------------------- /how-deploy-redis_sentinel(window)/sentinel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanshengshui/HCW/0a49311fad7026978265ac91d221251e985aee8a/how-deploy-redis_sentinel(window)/sentinel.png -------------------------------------------------------------------------------- /how-deploy-redis_sentinel(window)/slave_MarkMan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanshengshui/HCW/0a49311fad7026978265ac91d221251e985aee8a/how-deploy-redis_sentinel(window)/slave_MarkMan.png -------------------------------------------------------------------------------- /how-deploy-redis_sentinel(window)/switchmaster_MarkMan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanshengshui/HCW/0a49311fad7026978265ac91d221251e985aee8a/how-deploy-redis_sentinel(window)/switchmaster_MarkMan.png -------------------------------------------------------------------------------- /how-deploy-redis_sentinel(window)/swithMaster_MarkMan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanshengshui/HCW/0a49311fad7026978265ac91d221251e985aee8a/how-deploy-redis_sentinel(window)/swithMaster_MarkMan.png -------------------------------------------------------------------------------- /how-deploy-redis_sentinel(window)/test_MarkMan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanshengshui/HCW/0a49311fad7026978265ac91d221251e985aee8a/how-deploy-redis_sentinel(window)/test_MarkMan.png -------------------------------------------------------------------------------- /netty.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | file://$MODULE_DIR$/src/main/resources/spring.xml 8 | file://$MODULE_DIR$/src/main/resources/spring-mybatis.xml 9 | 10 | 11 | file://$MODULE_DIR$/src/main/resources/spring-quartz.xml 12 | 13 | 14 | file://$MODULE_DIR$/src/main/resources/spring-redis.xml 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /picture/1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanshengshui/HCW/0a49311fad7026978265ac91d221251e985aee8a/picture/1.PNG -------------------------------------------------------------------------------- /picture/RPC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanshengshui/HCW/0a49311fad7026978265ac91d221251e985aee8a/picture/RPC.png -------------------------------------------------------------------------------- /picture/horizon.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sanshengshui/HCW/0a49311fad7026978265ac91d221251e985aee8a/picture/horizon.PNG -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.haro 5 | netty 6 | war 7 | 0.0.1-SNAPSHOT 8 | netty Maven Webapp 9 | http://maven.apache.org 10 | 11 | 4.12 12 | 4.2.6.RELEASE 13 | 3.2.8 14 | 1.2.2 15 | 2.5.0 16 | 5.1.34 17 | 1.6.4 18 | 1.0.9 19 | 4.3.5 20 | 1.2 21 | 2.5 22 | 2.0 23 | 2.5 24 | 3.3.2 25 | 1.4 26 | 3.3 27 | 3.4.2-fix 28 | 0.9.1 29 | 1.3.1 30 | 2.7.2 31 | 4.10.3 32 | 3.2.0 33 | 1.8.5 34 | 3.3.2 35 | 4.0 36 | 1.0.9 37 | 2.1 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | redis.clients 47 | jedis 48 | 2.8.0 49 | 50 | 51 | org.springframework.data 52 | spring-data-redis 53 | 1.6.4.RELEASE 54 | 55 | 56 | 57 | 58 | org.objenesis 59 | objenesis 60 | ${version.objenesis} 61 | 62 | 63 | 64 | com.dyuproject.protostuff 65 | protostuff-core 66 | ${version.protostuff} 67 | 68 | 69 | com.dyuproject.protostuff 70 | protostuff-runtime 71 | ${version.protostuff} 72 | 73 | 74 | 75 | org.apache.commons 76 | commons-lang3 77 | ${version.commons-lang} 78 | 79 | 80 | 81 | org.apache.commons 82 | commons-collections4 83 | ${version.commons-collections} 84 | 85 | 86 | 87 | org.quartz-scheduler 88 | quartz 89 | ${quartz.version} 90 | 91 | 92 | 93 | com.google.protobuf 94 | protobuf-java 95 | ${protobuf.version} 96 | 97 | 98 | 99 | junit 100 | junit 101 | ${junit.version} 102 | test 103 | 104 | 105 | 106 | joda-time 107 | joda-time 108 | ${joda-time.version} 109 | 110 | 111 | 112 | org.apache.commons 113 | commons-lang3 114 | ${commons-lang3.version} 115 | 116 | 117 | commons-net 118 | commons-net 119 | ${commons-net.version} 120 | 121 | 122 | 123 | 124 | org.apache.httpcomponents 125 | httpclient 126 | ${httpclient.version} 127 | 128 | 129 | 130 | org.slf4j 131 | slf4j-log4j12 132 | ${slf4j.version} 133 | 134 | 135 | 136 | org.mybatis 137 | mybatis 138 | ${mybatis.version} 139 | 140 | 141 | 142 | org.mybatis 143 | mybatis-spring 144 | ${mybatis.spring.version} 145 | 146 | 147 | 148 | 149 | mysql 150 | mysql-connector-java 151 | ${mysql.version} 152 | 153 | 154 | 155 | com.alibaba 156 | druid 157 | ${druid.version} 158 | 159 | 160 | 161 | org.springframework 162 | spring-core 163 | ${spring.version} 164 | 165 | 166 | org.springframework 167 | spring-context 168 | ${spring.version} 169 | 170 | 171 | org.springframework 172 | spring-beans 173 | ${spring.version} 174 | 175 | 176 | org.springframework 177 | spring-webmvc 178 | ${spring.version} 179 | 180 | 181 | org.springframework 182 | spring-jdbc 183 | ${spring.version} 184 | 185 | 186 | org.springframework 187 | spring-aspects 188 | ${spring.version} 189 | 190 | 191 | org.springframework 192 | spring-tx 193 | ${spring.version} 194 | 195 | 196 | org.springframework 197 | spring-test 198 | ${spring.version} 199 | test 200 | 201 | 202 | 203 | jstl 204 | jstl 205 | ${jstl.version} 206 | 207 | 208 | javax.servlet 209 | servlet-api 210 | ${servlet-api.version} 211 | provided 212 | 213 | 214 | javax.servlet 215 | jsp-api 216 | ${jsp-api.version} 217 | provided 218 | 219 | 220 | 221 | commons-fileupload 222 | commons-fileupload 223 | ${commons-fileupload.version} 224 | 225 | 226 | 227 | 228 | org.codehaus.jackson 229 | jackson-mapper-asl 230 | 1.9.13 231 | 232 | 233 | 234 | com.alibaba 235 | fastjson 236 | 1.2.3 237 | 238 | 239 | 240 | com.fasterxml.jackson.core 241 | jackson-annotations 242 | ${jackson.version} 243 | 244 | 245 | 246 | com.fasterxml.jackson.core 247 | jackson-core 248 | ${jackson.version} 249 | 250 | 251 | 252 | com.fasterxml.jackson.core 253 | jackson-databind 254 | ${jackson.version} 255 | 256 | 257 | 258 | io.netty 259 | netty-all 260 | 4.1.6.Final 261 | 262 | 263 | 264 | 265 | com.aliyun 266 | aliyun-java-sdk-core 267 | 2.4.2 268 | 269 | 270 | com.aliyun 271 | aliyun-java-sdk-sms 272 | 3.0.0-rc1 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | netty 284 | 285 | 286 | 287 | 288 | org.apache.tomcat.maven 289 | tomcat7-maven-plugin 290 | 2.2 291 | 292 | 8084 293 | / 294 | UTF-8 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | src/main/java 303 | 304 | **/*.xml 305 | **/*.sql 306 | **/*.ftl 307 | 308 | false 309 | 310 | 311 | src/main/resources 312 | 313 | 314 | 315 | 316 | 317 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/cache/RedisCache.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.cache; 2 | 3 | import com.haro.netty.iot.staticOfFinal.proto.common.util.SerializationUtil; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.dao.DataAccessException; 6 | import org.springframework.data.redis.connection.RedisConnection; 7 | import org.springframework.data.redis.core.RedisCallback; 8 | import org.springframework.data.redis.core.RedisTemplate; 9 | import org.springframework.stereotype.Component; 10 | 11 | import java.util.List; 12 | import java.util.Set; 13 | 14 | 15 | 16 | /** 17 | * @author 穆书伟 18 | * @description redis缓存 19 | * @date 2017/6/9 16:09:07 20 | */ 21 | 22 | //@Component 23 | public class RedisCache { 24 | public final static String CACHENAME="cache";//缓存名 25 | public final static int CACHETIME=60;//默认缓存时间 26 | 27 | //@Autowired 28 | private RedisTemplate redisTemplate; 29 | 30 | public boolean putCache(String key, T obj) { 31 | final byte[] bkey = key.getBytes(); 32 | final byte[] bvalue = SerializationUtil.serializeObj(obj); 33 | boolean result = redisTemplate.execute(new RedisCallback() { 34 | 35 | public Boolean doInRedis(RedisConnection connection) throws DataAccessException { 36 | return connection.setNX(bkey, bvalue); 37 | } 38 | }); 39 | return result; 40 | } 41 | 42 | public void putCacheWithExpireTime(String key, T obj, final long expireTime) { 43 | final byte[] bkey = key.getBytes(); 44 | final byte[] bvalue = SerializationUtil.serializeObj(obj); 45 | redisTemplate.execute(new RedisCallback() { 46 | 47 | public Boolean doInRedis(RedisConnection connection) throws DataAccessException { 48 | connection.setEx(bkey, expireTime, bvalue); 49 | return true; 50 | } 51 | }); 52 | } 53 | 54 | public boolean putListCache(String key, List objList) { 55 | final byte[] bkey = key.getBytes(); 56 | final byte[] bvalue = SerializationUtil.serializeList(objList); 57 | boolean result = redisTemplate.execute(new RedisCallback() { 58 | 59 | public Boolean doInRedis(RedisConnection connection) throws DataAccessException { 60 | return connection.setNX(bkey, bvalue); 61 | } 62 | }); 63 | return result; 64 | } 65 | 66 | public boolean putListCacheWithExpireTime(String key, List objList, final long expireTime) { 67 | final byte[] bkey = key.getBytes(); 68 | final byte[] bvalue = SerializationUtil.serializeList(objList); 69 | boolean result = redisTemplate.execute(new RedisCallback() { 70 | 71 | public Boolean doInRedis(RedisConnection connection) throws DataAccessException { 72 | connection.setEx(bkey, expireTime, bvalue); 73 | return true; 74 | } 75 | }); 76 | return result; 77 | } 78 | 79 | public T getCache(final String key, Class targetClass) { 80 | byte[] result = redisTemplate.execute(new RedisCallback() { 81 | 82 | public byte[] doInRedis(RedisConnection connection) throws DataAccessException { 83 | return connection.get(key.getBytes()); 84 | } 85 | }); 86 | if (result == null) { 87 | return null; 88 | } 89 | return SerializationUtil.deserialize(result, targetClass); 90 | } 91 | 92 | public List getListCache(final String key, Class targetClass) { 93 | byte[] result = redisTemplate.execute(new RedisCallback() { 94 | 95 | public byte[] doInRedis(RedisConnection connection) throws DataAccessException { 96 | return connection.get(key.getBytes()); 97 | } 98 | }); 99 | if (result == null) { 100 | return null; 101 | } 102 | return SerializationUtil.deserializeList(result, targetClass); 103 | } 104 | 105 | /** 106 | * 精确删除key 107 | * 108 | * @param key 109 | */ 110 | public void deleteCache(String key) { 111 | redisTemplate.delete(key); 112 | } 113 | 114 | /** 115 | * 模糊删除key 116 | * 117 | * @param pattern 118 | */ 119 | public void deleteCacheWithPattern(String pattern) { 120 | Set keys = redisTemplate.keys(pattern); 121 | redisTemplate.delete(keys); 122 | } 123 | 124 | /** 125 | * 清空所有缓存 126 | */ 127 | public void clearCache() { 128 | deleteCacheWithPattern(RedisCache.CACHENAME+"|*"); 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/cache/RedisClusterCache.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.cache; 2 | 3 | import com.haro.netty.iot.staticOfFinal.proto.common.util.SerializationUtil; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.stereotype.Component; 6 | import redis.clients.jedis.Jedis; 7 | import redis.clients.jedis.JedisCluster; 8 | import redis.clients.jedis.JedisPool; 9 | 10 | import java.util.HashSet; 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.Set; 14 | 15 | /** 16 | * @author 穆书伟 17 | * @description redis缓存 采用Jedis Cluster 18 | * @date 2017/6/9 14:18:24 19 | */ 20 | //@Component 21 | public class RedisClusterCache { 22 | public final static String CACHENAME="cache";//缓存名 23 | public final static int CACHETIME=60;//默认缓存时间 24 | 25 | //@Autowired 26 | private JedisCluster jedisCluster; 27 | 28 | public void putCache(String key,T obj){ 29 | final byte[] bkey = key.getBytes(); 30 | final byte[] bvalue = SerializationUtil.serializeObj(obj); 31 | jedisCluster.set(bkey,bvalue); 32 | 33 | } 34 | public void putCacheWithExpireTime(String key, T obj, int expireTime) { 35 | final byte[] bkey = key.getBytes(); 36 | final byte[] bvalue = SerializationUtil.serializeObj(obj); 37 | jedisCluster.setex(bkey, expireTime, bvalue); 38 | } 39 | 40 | public void putListCache(String key, List objList) { 41 | final byte[] bkey = key.getBytes(); 42 | final byte[] bvalue = SerializationUtil.serializeList(objList); 43 | jedisCluster.set(bkey,bvalue); 44 | } 45 | 46 | public void putListCacheWithExpireTime(String key, List objList, int expireTime) { 47 | final byte[] bkey = key.getBytes(); 48 | final byte[] bvalue = SerializationUtil.serializeList(objList); 49 | jedisCluster.setex(bkey, expireTime, bvalue); 50 | } 51 | 52 | public T getCache(final String key, Class targetClass) { 53 | byte[] result =jedisCluster.get(key.getBytes()); 54 | if (result == null) { 55 | return null; 56 | } 57 | return SerializationUtil.deserializeObj(result, targetClass); 58 | } 59 | 60 | public List getListCache(String key, Class targetClass) { 61 | byte[] result =jedisCluster.get(key.getBytes()); 62 | if (result == null) { 63 | return null; 64 | } 65 | return SerializationUtil.deserializeList(result, targetClass); 66 | } 67 | 68 | /** 69 | * 精确删除key 70 | * 71 | * @param key 72 | */ 73 | public void deleteCache(String key) { 74 | jedisCluster.del(key); 75 | } 76 | 77 | /** 78 | * 模糊删除key 79 | * 80 | * @param pattern 81 | */ 82 | public void deleteCacheWithPattern(String pattern) { 83 | Set keys =this.keys(pattern); 84 | for(String key:keys){ 85 | jedisCluster.del(key); 86 | } 87 | } 88 | 89 | /** 90 | * 清空所有缓存 91 | */ 92 | public void clearCache() { 93 | deleteCacheWithPattern(RedisClusterCache.CACHENAME+"|*"); 94 | } 95 | 96 | /** 97 | * 由于JedisCluster没有提供对keys命令的封装,只能自己实现 98 | * @param pattern 99 | * @return 100 | */ 101 | public Set keys(String pattern){ 102 | Set keys = new HashSet(); 103 | Map clusterNodes = jedisCluster.getClusterNodes(); 104 | for(String k : clusterNodes.keySet()){ 105 | JedisPool jp = clusterNodes.get(k); 106 | Jedis connection = jp.getResource(); 107 | try { 108 | keys.addAll(connection.keys(pattern)); 109 | } catch(Exception e){ 110 | e.printStackTrace(); 111 | } finally{ 112 | //用完一定要close这个链接!!! 113 | connection.close(); 114 | } 115 | } 116 | return keys; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/netty/cfg/SpringConfig.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.netty.cfg; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | import com.haro.netty.service.DeviceStatusService; 9 | import com.haro.netty.service.Impl.DeviceStatusServiceImpl; 10 | import org.mybatis.spring.annotation.MapperScan; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.beans.factory.annotation.Qualifier; 13 | import org.springframework.beans.factory.annotation.Value; 14 | import org.springframework.context.annotation.Bean; 15 | import org.springframework.context.annotation.ComponentScan; 16 | import org.springframework.context.annotation.Configuration; 17 | import org.springframework.context.annotation.PropertySource; 18 | import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; 19 | 20 | import com.haro.netty.iot.netty.handler.StringProtocolInitalizer; 21 | 22 | import io.netty.bootstrap.ServerBootstrap; 23 | import io.netty.channel.ChannelOption; 24 | import io.netty.channel.nio.NioEventLoopGroup; 25 | import io.netty.channel.socket.nio.NioServerSocketChannel; 26 | import io.netty.handler.codec.string.StringDecoder; 27 | import io.netty.handler.codec.string.StringEncoder; 28 | 29 | /** 30 | * This class contains the bean definitions for this netty server. These beans 31 | * are autowired into the respective java classes in org.nerdronix.* packages 32 | * using component scan feature of spring. Properties are injected using the 33 | * PropertySource. For more information look here and here 38 | * 39 | * @author Abraham Menacherry 40 | * 41 | */ 42 | /** 43 | * 44 | * @ClassName: SpringConfig 45 | * @Description: TODO 46 | * @author 穆书伟 47 | * @Email lovewsic@gmail.com 48 | * @Date 2017年4月26日 上午10:29:31 49 | */ 50 | @Configuration 51 | @ComponentScan("com.haro.netty") 52 | @MapperScan(basePackages = {"com.haro.netty.test.mapper"}) 53 | @PropertySource("classpath:netty-server.properties") 54 | public class SpringConfig { 55 | @Value("${boss.thread.count}") 56 | private int bossCount; 57 | 58 | @Value("${worker.thread.count}") 59 | private int workerCount; 60 | 61 | @Value("${tcp.port}") 62 | private int tcpPort; 63 | 64 | @Value("${so.keepalive}") 65 | private boolean keepAlive; 66 | 67 | @Value("${so.backlog}") 68 | private int backlog; 69 | 70 | @Value("${log4j.configuration}") 71 | private String log4jConfiguration; 72 | 73 | @Autowired 74 | @Qualifier("springProtocolInitializer") 75 | private StringProtocolInitalizer protocolInitalizer; 76 | 77 | @SuppressWarnings("unchecked") 78 | @Bean(name = "serverBootstrap") 79 | public ServerBootstrap bootstrap() { 80 | ServerBootstrap b = new ServerBootstrap(); 81 | b.group(bossGroup(), workerGroup()) 82 | .channel(NioServerSocketChannel.class) 83 | .childHandler(protocolInitalizer); 84 | Map, Object> tcpChannelOptions = tcpChannelOptions(); 85 | Set> keySet = tcpChannelOptions.keySet(); 86 | for (@SuppressWarnings("rawtypes") 87 | ChannelOption option : keySet) { 88 | b.option(option, tcpChannelOptions.get(option)); 89 | } 90 | return b; 91 | } 92 | 93 | @Bean(name = "bossGroup", destroyMethod = "shutdownGracefully") 94 | public NioEventLoopGroup bossGroup() { 95 | return new NioEventLoopGroup(bossCount); 96 | } 97 | 98 | @Bean(name = "workerGroup", destroyMethod = "shutdownGracefully") 99 | public NioEventLoopGroup workerGroup() { 100 | return new NioEventLoopGroup(workerCount); 101 | } 102 | 103 | @Bean(name = "tcpSocketAddress") 104 | public InetSocketAddress tcpPort() { 105 | return new InetSocketAddress(tcpPort); 106 | } 107 | 108 | @Bean(name = "tcpChannelOptions") 109 | public Map, Object> tcpChannelOptions() { 110 | Map, Object> options = new HashMap, Object>(); 111 | options.put(ChannelOption.SO_KEEPALIVE, keepAlive); 112 | options.put(ChannelOption.SO_BACKLOG, backlog); 113 | return options; 114 | } 115 | 116 | @Bean(name = "stringEncoder") 117 | public StringEncoder stringEncoder() { 118 | return new StringEncoder(); 119 | } 120 | 121 | @Bean(name = "stringDecoder") 122 | public StringDecoder stringDecoder() { 123 | return new StringDecoder(); 124 | } 125 | 126 | /** 127 | * Necessary to make the Value annotations work. 128 | * 129 | * @return 130 | */ 131 | @Bean 132 | public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() { 133 | return new PropertySourcesPlaceholderConfigurer(); 134 | } 135 | 136 | @Bean 137 | public DeviceStatusService deviceStatusService(){ 138 | return new DeviceStatusServiceImpl(); 139 | } 140 | 141 | 142 | } 143 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/netty/handler/HeartbeatHandler.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.netty.handler; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.handler.timeout.IdleState; 7 | import io.netty.handler.timeout.IdleStateEvent; 8 | import io.netty.handler.timeout.IdleStateHandler; 9 | import io.netty.handler.timeout.ReadTimeoutException; 10 | 11 | /** 12 | * 13 | * @ClassName: HeartbeatHandler 14 | * @Description: TODO netty 心跳包检测机制 15 | * @author 穆书伟 16 | * @Email lovewsic@gmail.com 17 | * @date 2017年1月13日 上午10:51:57 18 | */ 19 | 20 | public class HeartbeatHandler extends IdleStateHandler{ 21 | private boolean closed; 22 | 23 | /** 24 | * Creates a new instance. 25 | * 26 | * @param timeoutSeconds 27 | * read timeout in seconds 28 | */ 29 | public HeartbeatHandler(int timeoutSeconds) { 30 | this(timeoutSeconds, TimeUnit.SECONDS); 31 | } 32 | 33 | /** 34 | * Creates a new instance. 35 | * 36 | * @param timeout 37 | * read timeout 38 | * @param unit 39 | * the {@link TimeUnit} of {@code timeout} 40 | */ 41 | public HeartbeatHandler(long timeout, TimeUnit unit) { 42 | super(timeout, 0, 0, unit); 43 | } 44 | 45 | @Override 46 | protected final void channelIdle(ChannelHandlerContext ctx, IdleStateEvent evt) throws Exception { 47 | assert evt.state() == IdleState.READER_IDLE; 48 | readTimedOut(ctx); 49 | } 50 | 51 | /** 52 | * Is called when a read timeout was detected. 53 | */ 54 | protected void readTimedOut(ChannelHandlerContext ctx) throws Exception { 55 | if (!closed) { 56 | ctx.fireExceptionCaught(ReadTimeoutException.INSTANCE); 57 | ctx.close(); 58 | closed = true; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/netty/handler/KeepAliveHandler.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.netty.handler; 2 | 3 | import com.haro.netty.iot.staticOfFinal.proto.common.bean.RpcRequest; 4 | import com.haro.netty.iot.staticOfFinal.proto.common.bean.RpcResponse; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.channel.ChannelInboundHandlerAdapter; 7 | import io.netty.channel.SimpleChannelInboundHandler; 8 | 9 | /** 10 | * @author 穆书伟 11 | * @description 设备向服务器发送心跳包,20秒发一次心跳,保持TCP/UDP socket连接(心跳包可确保数据链路的实时建立) 12 | * 服务器向设备确认心跳包数据 13 | * @date 2017/6/8 17:22 14 | */ 15 | public class KeepAliveHandler extends SimpleChannelInboundHandler { 16 | @Override 17 | protected void channelRead0(ChannelHandlerContext channelHandlerContext, RpcRequest rpcRequest) throws Exception { 18 | RpcResponse response=new RpcResponse(); 19 | response.setFrame_head("_YD_"); 20 | response.setDir((byte)0x02); 21 | response.setCommunicationID(rpcRequest.getCommunicationID()); 22 | response.setSIMCCID(rpcRequest.getSIMCCID()); 23 | response.setProduc(rpcRequest.getProduc()); 24 | 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/netty/handler/RemoteControlHandler.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.netty.handler; 2 | 3 | import io.netty.channel.ChannelOutboundHandlerAdapter; 4 | 5 | /** 6 | * @author 穆书伟 7 | * @description 远程发送控制命令 设备返回接受控制命令成功 8 | * @date 2017/6/8 17:35 9 | */ 10 | public class RemoteControlHandler extends ChannelOutboundHandlerAdapter{ 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/netty/handler/ServerHandler.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.netty.handler; 2 | 3 | 4 | import com.haro.netty.iot.staticOfFinal.NettyChannelMap; 5 | import com.haro.netty.iot.thread.SaveDeviceIccidTask; 6 | import com.haro.netty.iot.thread.UpdateDeviceStatusTask; 7 | import com.haro.netty.iot.threadpool.ExecutorProcessPool; 8 | import com.haro.netty.service.QueryStatusForLightService; 9 | import com.haro.netty.service.StatusDeviceService; 10 | import com.haro.netty.test.pojo.DeviceStatus; 11 | import com.haro.netty.util.SpringUtil; 12 | import io.netty.channel.socket.SocketChannel; 13 | import org.slf4j.Logger; 14 | import org.slf4j.LoggerFactory; 15 | import org.springframework.beans.factory.annotation.Qualifier; 16 | import org.springframework.stereotype.Component; 17 | import io.netty.buffer.ByteBuf; 18 | import io.netty.channel.ChannelHandler.Sharable; 19 | import io.netty.channel.ChannelHandlerContext; 20 | import io.netty.channel.ChannelInboundHandlerAdapter; 21 | 22 | 23 | import static com.haro.netty.util.ByteUtil.Str2Hex; 24 | import static com.haro.netty.util.ByteUtil.bytesToHexString; 25 | 26 | /** 27 | * 28 | * @ClassName: ServerHandler 29 | * @Description: TODO netty 重要接口 30 | * @author 穆书伟 31 | * @Email lovewsic@gmail.com 32 | * @date 2017年1月13日 上午10:21:42 33 | */ 34 | @Component 35 | @Qualifier("serverHandler") 36 | @Sharable 37 | public class ServerHandler extends ChannelInboundHandlerAdapter { 38 | 39 | 40 | 41 | private static final Logger logger = LoggerFactory.getLogger(ServerHandler.class); 42 | 43 | /** 44 | * 客户的登入 45 | */ 46 | @Override 47 | public void channelRegistered(ChannelHandlerContext ctx) throws Exception { 48 | // TODO Auto-generated method stub 49 | //super.channelRegistered(ctx); 50 | logger.info("client: "+ ctx.channel().remoteAddress()+ "channelRegistered"); 51 | 52 | } 53 | /** 54 | * 客户端退出 55 | */ 56 | @Override 57 | public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { 58 | // TODO Auto-generated method stub 59 | //super.channelUnregistered(ctx); 60 | logger.info("client: "+ctx.channel().remoteAddress()+"channelUnregistered"); 61 | 62 | String commidlovesss=NettyChannelMap.comidMap.get(ctx.channel()).replaceAll(" ",""); 63 | logger.info(commidlovesss); 64 | StatusDeviceService statusDeviceService =(StatusDeviceService) SpringUtil.getApplicationContext().getBean("deviceDeviceStatus"); 65 | DeviceStatus deviceStatus=new DeviceStatus(); 66 | deviceStatus.setEqp_comid(commidlovesss); 67 | statusDeviceService.updateIotDeviceStatus(deviceStatus); 68 | 69 | 70 | 71 | } 72 | /** 73 | * 客户接入 74 | */ 75 | @Override 76 | public void channelActive(ChannelHandlerContext ctx) throws Exception { 77 | // TODO Auto-generated method stub 78 | //super.channelActive(ctx); 79 | 80 | logger.info("client: "+ ctx.channel().remoteAddress()+ "channelInactive"); 81 | 82 | 83 | 84 | 85 | 86 | } 87 | /** 88 | * 客户端断开 89 | */ 90 | @Override 91 | public void channelInactive(ChannelHandlerContext ctx) throws Exception { 92 | // TODO Auto-generated method stub 93 | super.channelInactive(ctx); 94 | logger.info("client: "+ ctx.channel().remoteAddress()+ "channelInactive"); 95 | 96 | 97 | 98 | 99 | } 100 | 101 | 102 | 103 | /** 104 | * 接受到数据 105 | */ 106 | @Override 107 | public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 108 | // TODO Auto-generated method stub 109 | //super.channelRead(ctx, msg); 110 | 111 | 112 | //获取byte数据 113 | ByteBuf in = (ByteBuf) msg; 114 | byte[]req = new byte[in.readableBytes()]; 115 | int ReqLength=req.length; 116 | in.readBytes(req); 117 | 118 | /* 119 | byte a=(0x45); 120 | char c=(char)a; 121 | System.out.println(c); 122 | */ 123 | 124 | 125 | if(req.length==27){ 126 | byte[] reqYaDu=new byte[13]; 127 | char[] buffermu=new char[26]; 128 | for(int i=0;i<26;i++){ 129 | buffermu[i]=(char)req[i]; 130 | } 131 | Str2Hex(buffermu,reqYaDu,26); 132 | String strReqYaDu=bytesToHexString(reqYaDu); 133 | logger.info(strReqYaDu); 134 | 135 | 136 | 137 | byte[] rcDatab=new byte[45]; 138 | rcDatab[0]=(byte)0x5F; 139 | rcDatab[1]=(byte)0x59; 140 | rcDatab[2]=(byte)0x44; 141 | rcDatab[3]=(byte)0x5F; 142 | rcDatab[4]=(byte)0x02; 143 | System.arraycopy(reqYaDu,0,rcDatab,5,13); 144 | byte[] rcD=new byte[]{0x38,0x39,0x38,0x36,0x30,0x36,0x31,0x36,0x30,0x32,0x30,0x30,0x34,0x32,0x36,0x38,0x39,0x35,0x37,0x35}; 145 | System.arraycopy(rcD,0,rcDatab,18,20); 146 | rcDatab[38]=(byte)0x03; 147 | rcDatab[39]=(byte)0xF2; 148 | rcDatab[40]=(byte)0x01; 149 | rcDatab[41]=(byte)0x00; 150 | if(req[ReqLength-1]==(byte)0x31){ 151 | rcDatab[42]=(byte)0x01; 152 | }else if(req[ReqLength-1]==(byte)0x32){ 153 | rcDatab[42]=(byte)0x02; 154 | }else if(req[ReqLength-1]==(byte)0x33){ 155 | rcDatab[42]=(byte)0x03; 156 | }else if(req[ReqLength-1]==(byte)0x34){ 157 | rcDatab[42]=(byte)0x04; 158 | } 159 | rcDatab[43]=(byte)0x23; 160 | rcDatab[44]=(byte)0x23; 161 | ByteBuf encodedw=ctx.alloc().buffer(45); 162 | encodedw.writeBytes(rcDatab); 163 | NettyChannelMap.channelMap.get(strReqYaDu).write(encodedw); 164 | NettyChannelMap.channelMap.get(strReqYaDu).flush(); 165 | 166 | 167 | 168 | 169 | 170 | } 171 | 172 | 173 | 174 | 175 | 176 | if(req[0]==(byte)0x5F && req[1]==(byte)0x59 && req[2]==(byte)0x44 &&req[3]==(byte)0x5F && req[39]==(byte)0xF5 && req[ReqLength-1]==(byte)0x23 && req[ReqLength-2]==(byte)0x23){ 177 | 178 | /** 179 | * 添加控制灯的指令 180 | */ 181 | 182 | 183 | 184 | 185 | byte[] reqDataTs=new byte[1]; 186 | System.arraycopy(req,42,reqDataTs,0,1); 187 | String reqDataTss=bytesToHexString(reqDataTs); 188 | logger.info(reqDataTss); 189 | 190 | ExecutorProcessPool pool =ExecutorProcessPool.getInstance(); 191 | pool.execute(new SaveDeviceIccidTask(req)); 192 | 193 | byte[] reqData=new byte[44]; 194 | byte[] reqmsw = new byte[45]; 195 | byte[] reqmsw1 = new byte[45]; 196 | 197 | reqData[0]=(byte)0x5F; 198 | reqData[1]=(byte)0x59; 199 | reqData[2]=(byte)0x44; 200 | reqData[3]=(byte)0x5F; 201 | reqData[4]=(byte)0x02; 202 | 203 | reqmsw[0]=(byte)0x5F; 204 | reqmsw[1]=(byte)0x59; 205 | reqmsw[2]=(byte)0x44; 206 | reqmsw[3]=(byte)0x5F; 207 | reqmsw[4]=(byte)0x02; 208 | 209 | reqmsw1[0]=(byte)0x5F; 210 | reqmsw1[1]=(byte)0x59; 211 | reqmsw1[2]=(byte)0x44; 212 | reqmsw1[3]=(byte)0x5F; 213 | reqmsw1[4]=(byte)0x02; 214 | 215 | System.arraycopy(req,5,reqData,5,13); 216 | System.arraycopy(req,18,reqData,18,20); 217 | 218 | System.arraycopy(req,5,reqmsw,5,13); 219 | System.arraycopy(req,18,reqmsw,18,20); 220 | 221 | System.arraycopy(req,5,reqData,5,13); 222 | System.arraycopy(req,18,reqData,18,20); 223 | 224 | System.arraycopy(req,5,reqmsw1,5,13); 225 | System.arraycopy(req,18,reqmsw1,18,20); 226 | 227 | reqData[38]=(byte)0x03; 228 | reqData[39]=(byte)0xF6; 229 | reqData[40]=(byte)0x00; 230 | reqData[41]=(byte)0x00; 231 | reqData[42]=(byte)0x23; 232 | reqData[43]=(byte)0x23; 233 | 234 | reqmsw[38]=(byte)0x03; 235 | reqmsw[39]=(byte)0xF9; 236 | reqmsw[40]=(byte)0x01; 237 | reqmsw[41]=(byte)0x00; 238 | reqmsw[42]=(byte)0x01; 239 | reqmsw[43]=(byte)0x23; 240 | reqmsw[44]=(byte)0x23; 241 | 242 | reqmsw1[38]=(byte)0x03; 243 | reqmsw1[39]=(byte)0xF9; 244 | reqmsw1[40]=(byte)0x01; 245 | reqmsw1[41]=(byte)0x00; 246 | reqmsw1[42]=(byte)0x02; 247 | reqmsw1[43]=(byte)0x23; 248 | reqmsw1[44]=(byte)0x23; 249 | 250 | 251 | 252 | 253 | byte[] reqDataT=new byte[13]; 254 | System.arraycopy(req,5,reqDataT,0,13); 255 | String reqDataTe=bytesToHexString(reqDataT); 256 | String reqDateTeModify=reqDataTe.replace(" ",""); 257 | 258 | 259 | 260 | NettyChannelMap.channelMap.put(reqDataTe,(SocketChannel) ctx.channel()); 261 | NettyChannelMap.comidMap.put((SocketChannel)ctx.channel(),reqDataTe); 262 | 263 | 264 | 265 | logger.info(reqDataTe); 266 | logger.info(reqDateTeModify); 267 | 268 | 269 | 270 | 271 | 272 | QueryStatusForLightService queryStatusForLightService=(QueryStatusForLightService) SpringUtil.getApplicationContext().getBean("deviceDeviceForLight"); 273 | int jamesmsw=queryStatusForLightService.SendCommandForLight(reqDateTeModify); 274 | String Strjamesmsw=String.valueOf(jamesmsw); 275 | logger.info(Strjamesmsw); 276 | 277 | 278 | 279 | 280 | 281 | if(jamesmsw==3){ 282 | ByteBuf enjamesmsw=ctx.alloc().buffer(45); 283 | enjamesmsw.writeBytes(reqmsw); 284 | ctx.write(enjamesmsw); 285 | ctx.flush(); 286 | }else if(jamesmsw ==4){ 287 | ByteBuf enjamesmsw=ctx.alloc().buffer(45); 288 | enjamesmsw.writeBytes(reqmsw); 289 | ctx.write(enjamesmsw); 290 | ctx.flush(); 291 | 292 | }else{ 293 | ByteBuf enjamesmsw=ctx.alloc().buffer(45); 294 | enjamesmsw.writeBytes(reqmsw1); 295 | ctx.write(enjamesmsw); 296 | ctx.flush(); 297 | } 298 | 299 | 300 | 301 | 302 | if(req[38]==(byte)0x03){ 303 | } 304 | if(req[39]==(byte)0xF3){ 305 | }else if(req[39]==(byte)0xF5){ 306 | ByteBuf encoded=ctx.alloc().buffer(44); 307 | encoded.writeBytes(reqData); 308 | ctx.write(encoded); 309 | ctx.flush(); 310 | String stringReq=bytesToHexString(req); 311 | logger.info(stringReq); 312 | String reqdata=bytesToHexString(reqData); 313 | logger.info(reqdata); 314 | }else if(req[39]==(byte)0xF1){ 315 | } 316 | } 317 | 318 | } 319 | /** 320 | * ctx.write(Object)方法不会使消息写入到通道上, 321 | * 他被缓冲在了内部,你需要调用ctx.flush()方法来把缓冲区中数据强行输出。 322 | * 或者你可以在channelRead方法中用更简洁的cxt.writeAndFlush(msg)以达到同样的目的 323 | * @param ctx 324 | * @throws Exception 325 | */ 326 | @Override 327 | public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 328 | // TODO Auto-generated method stub 329 | //super.channelReadComplete(ctx); 330 | ctx.flush(); 331 | } 332 | 333 | @Override 334 | public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { 335 | // TODO Auto-generated method stub 336 | super.userEventTriggered(ctx, evt); 337 | } 338 | 339 | @Override 340 | public void channelWritabilityChanged(ChannelHandlerContext ctx) throws Exception { 341 | // TODO Auto-generated method stub 342 | super.channelWritabilityChanged(ctx); 343 | } 344 | 345 | @Override 346 | public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { 347 | // TODO Auto-generated method stub 348 | super.exceptionCaught(ctx, cause); 349 | } 350 | 351 | 352 | 353 | } 354 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/netty/handler/StringProtocolInitalizer.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.netty.handler; 2 | 3 | import io.netty.handler.timeout.IdleStateHandler; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.annotation.Qualifier; 6 | import org.springframework.stereotype.Component; 7 | 8 | import io.netty.channel.ChannelInitializer; 9 | import io.netty.channel.ChannelPipeline; 10 | import io.netty.channel.socket.SocketChannel; 11 | import io.netty.handler.codec.string.StringDecoder; 12 | import io.netty.handler.codec.string.StringEncoder; 13 | 14 | 15 | import java.io.IOException; 16 | import java.sql.*; 17 | import java.util.concurrent.TimeUnit; 18 | 19 | 20 | /** 21 | * 22 | * @ClassName: StringProtocolInitalizer 23 | * @Description: TODO Just a dummy protocol mainly to show the ServerBootstrap being initialized. 24 | * @author 穆书伟 25 | * @Email lovewsic@gmail.com 26 | * @date 2017年1月13日 上午10:27:24 27 | */ 28 | @Component 29 | @Qualifier("springProtocolInitializer") 30 | public class StringProtocolInitalizer extends ChannelInitializer{ 31 | 32 | 33 | 34 | 35 | @Autowired 36 | StringDecoder stringDecoder; 37 | 38 | @Autowired 39 | StringEncoder stringEncoder; 40 | 41 | @Autowired 42 | ServerHandler serverHandler; 43 | 44 | 45 | @Override 46 | protected void initChannel(SocketChannel ch) throws Exception { 47 | ChannelPipeline pipeline = ch.pipeline(); 48 | pipeline.addLast("heartbeatHandler",new HeartbeatHandler(25)); 49 | pipeline.addLast("handler", serverHandler); 50 | 51 | 52 | 53 | 54 | 55 | 56 | } 57 | 58 | 59 | 60 | public StringDecoder getStringDecoder() { 61 | return stringDecoder; 62 | } 63 | 64 | public void setStringDecoder(StringDecoder stringDecoder) { 65 | this.stringDecoder = stringDecoder; 66 | } 67 | 68 | public StringEncoder getStringEncoder() { 69 | return stringEncoder; 70 | } 71 | 72 | public void setStringEncoder(StringEncoder stringEncoder) { 73 | this.stringEncoder = stringEncoder; 74 | } 75 | 76 | public ServerHandler getServerHandler() { 77 | return serverHandler; 78 | } 79 | 80 | public void setServerHandler(ServerHandler serverHandler) { 81 | this.serverHandler = serverHandler; 82 | } 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/netty/server/TCPServer.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.netty.server; 2 | 3 | import java.net.InetSocketAddress; 4 | 5 | import javax.annotation.PostConstruct; 6 | import javax.annotation.PreDestroy; 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.beans.factory.annotation.Qualifier; 10 | import org.springframework.stereotype.Component; 11 | 12 | import io.netty.bootstrap.ServerBootstrap; 13 | import io.netty.channel.ChannelFuture; 14 | 15 | /** 16 | * @author 穆书伟 17 | * @description TCP 服务器 18 | * @date 2017/5/22 18:44 19 | */ 20 | 21 | @Component 22 | 23 | 24 | public class TCPServer { 25 | 26 | @Autowired 27 | @Qualifier("serverBootstrap") 28 | private ServerBootstrap b; 29 | 30 | @Autowired 31 | @Qualifier("tcpSocketAddress") 32 | private InetSocketAddress tcpPort; 33 | 34 | private ChannelFuture serverChannelFuture; 35 | 36 | @PostConstruct 37 | public void start() throws Exception { 38 | System.out.println("Starting server at " + tcpPort); 39 | serverChannelFuture = b.bind(tcpPort).sync(); 40 | } 41 | 42 | @PreDestroy 43 | public void stop() throws Exception { 44 | serverChannelFuture.channel().closeFuture().sync(); 45 | } 46 | 47 | public ServerBootstrap getB() { 48 | return b; 49 | } 50 | 51 | public void setB(ServerBootstrap b) { 52 | this.b = b; 53 | } 54 | 55 | public InetSocketAddress getTcpPort() { 56 | return tcpPort; 57 | } 58 | 59 | public void setTcpPort(InetSocketAddress tcpPort) { 60 | this.tcpPort = tcpPort; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/staticOfFinal/NettyChannelMap.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.staticOfFinal; 2 | 3 | 4 | import io.netty.channel.socket.SocketChannel; 5 | import java.util.concurrent.ConcurrentHashMap; 6 | import java.util.Map; 7 | 8 | /** 9 | * @author 穆书伟 10 | * @description 将设备的mac地址和socket绑定到一起 利用此socket向设备发送数据 11 | * @date 2017/5/22 18:43 12 | */ 13 | public class NettyChannelMap { 14 | public static Map channelMap=new ConcurrentHashMap(); 15 | 16 | public static Map comidMap=new ConcurrentHashMap(); 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/staticOfFinal/proto/IOTValue.proto: -------------------------------------------------------------------------------- 1 | syntax="proto3"; 2 | option java_package="com.haro.netty.iot.staticOfFinal.proto"; 3 | option java_outer_classname="IOTValueProto"; 4 | 5 | 6 | message IOTValue{ 7 | bytes frame_head=1; 8 | bytes dir=2; 9 | bytes CommunicationID=3; 10 | bytes SIMCCID=4; 11 | bytes Produc=5; 12 | bytes comm=6; 13 | bytes data_length=7; 14 | bytes data=8; 15 | bytes frame_tail=9; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/staticOfFinal/proto/common/bean/RpcRequest.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.staticOfFinal.proto.common.bean; 2 | 3 | /** 4 | * @author 穆书伟 5 | * @description 封装RPC请求 6 | * @date 2017/6/5 17:33 7 | */ 8 | public class RpcRequest { 9 | //帧头 10 | private String frame_head; 11 | //方向 12 | private String Dir; 13 | //身份码 14 | private String CommunicationID; 15 | //SIM卡编码 16 | private String SIMCCID; 17 | //产品码 18 | private String Produc; 19 | //功能码 20 | private String comm; 21 | //数据长度 22 | private String data_length; 23 | //数据 24 | private String data; 25 | //帧尾 26 | private String frame_tail; 27 | 28 | public String getFrame_head() { 29 | return frame_head; 30 | } 31 | 32 | public void setFrame_head(String frame_head) { 33 | this.frame_head = frame_head; 34 | } 35 | 36 | public String getDir() { 37 | return Dir; 38 | } 39 | 40 | public void setDir(String dir) { 41 | Dir = dir; 42 | } 43 | 44 | public String getCommunicationID() { 45 | return CommunicationID; 46 | } 47 | 48 | public void setCommunicationID(String communicationID) { 49 | CommunicationID = communicationID; 50 | } 51 | 52 | public String getSIMCCID() { 53 | return SIMCCID; 54 | } 55 | 56 | public void setSIMCCID(String SIMCCID) { 57 | this.SIMCCID = SIMCCID; 58 | } 59 | 60 | public String getProduc() { 61 | return Produc; 62 | } 63 | 64 | public void setProduc(String produc) { 65 | Produc = produc; 66 | } 67 | 68 | public String getComm() { 69 | return comm; 70 | } 71 | 72 | public void setComm(String comm) { 73 | this.comm = comm; 74 | } 75 | 76 | public String getData_length() { 77 | return data_length; 78 | } 79 | 80 | public void setData_length(String data_length) { 81 | this.data_length = data_length; 82 | } 83 | 84 | public String getData() { 85 | return data; 86 | } 87 | 88 | public void setData(String data) { 89 | this.data = data; 90 | } 91 | 92 | public String getFrame_tail() { 93 | return frame_tail; 94 | } 95 | 96 | public void setFrame_tail(String frame_tail) { 97 | this.frame_tail = frame_tail; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/staticOfFinal/proto/common/bean/RpcResponse.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.staticOfFinal.proto.common.bean; 2 | 3 | /** 4 | * @author 穆书伟 5 | * @description 封装RPC响应 6 | * @date 2017/6/5 17:33 7 | */ 8 | public class RpcResponse { 9 | //帧头 10 | private String frame_head; 11 | //方向 12 | private byte Dir; 13 | //身份码 14 | private String CommunicationID; 15 | //SIM卡编码 16 | private String SIMCCID; 17 | //产品码 18 | private String Produc; 19 | //功能码 20 | private String comm; 21 | //数据长度 22 | private String data_length; 23 | //数据 24 | private String data; 25 | //帧尾 26 | private String frame_tail; 27 | 28 | public String getFrame_head() { 29 | return frame_head; 30 | } 31 | 32 | public void setFrame_head(String frame_head) { 33 | this.frame_head = frame_head; 34 | } 35 | 36 | public byte getDir() { 37 | return Dir; 38 | } 39 | 40 | public void setDir(byte dir) { 41 | Dir = dir; 42 | } 43 | 44 | public String getCommunicationID() { 45 | return CommunicationID; 46 | } 47 | 48 | public void setCommunicationID(String communicationID) { 49 | CommunicationID = communicationID; 50 | } 51 | 52 | public String getSIMCCID() { 53 | return SIMCCID; 54 | } 55 | 56 | public void setSIMCCID(String SIMCCID) { 57 | this.SIMCCID = SIMCCID; 58 | } 59 | 60 | public String getProduc() { 61 | return Produc; 62 | } 63 | 64 | public void setProduc(String produc) { 65 | Produc = produc; 66 | } 67 | 68 | public String getComm() { 69 | return comm; 70 | } 71 | 72 | public void setComm(String comm) { 73 | this.comm = comm; 74 | } 75 | 76 | public String getData_length() { 77 | return data_length; 78 | } 79 | 80 | public void setData_length(String data_length) { 81 | this.data_length = data_length; 82 | } 83 | 84 | public String getData() { 85 | return data; 86 | } 87 | 88 | public void setData(String data) { 89 | this.data = data; 90 | } 91 | 92 | public String getFrame_tail() { 93 | return frame_tail; 94 | } 95 | 96 | public void setFrame_tail(String frame_tail) { 97 | this.frame_tail = frame_tail; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/staticOfFinal/proto/common/codec/RpcDecoder.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.staticOfFinal.proto.common.codec; 2 | 3 | import com.haro.netty.iot.staticOfFinal.proto.common.util.SerializationUtil; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.handler.codec.ByteToMessageDecoder; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author 穆书伟 12 | * @description RPC 解码器 13 | * @date 2017/6/5 12:51 14 | */ 15 | public class RpcDecoder extends ByteToMessageDecoder{ 16 | 17 | private Class genericClass; 18 | 19 | public RpcDecoder(Class genericClass){ 20 | this.genericClass=genericClass; 21 | } 22 | 23 | @Override 24 | protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List list) throws Exception { 25 | if(byteBuf.readableBytes() < 4){ 26 | return; 27 | } 28 | byteBuf.markReaderIndex(); 29 | int dataLength = byteBuf.readInt(); 30 | if(byteBuf.readableBytes() < dataLength){ 31 | byteBuf.resetReaderIndex(); 32 | return; 33 | } 34 | byte[] data = new byte[dataLength]; 35 | byteBuf.readBytes(data); 36 | list.add(SerializationUtil.deserialize(data,genericClass)); 37 | 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/staticOfFinal/proto/common/codec/RpcEncoder.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.staticOfFinal.proto.common.codec; 2 | 3 | import com.haro.netty.iot.staticOfFinal.proto.common.util.SerializationUtil; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.handler.codec.MessageToByteEncoder; 7 | 8 | /** 9 | * @author 穆书伟 10 | * @description 编码器 11 | * @date 2017/6/5 12:41 12 | */ 13 | public class RpcEncoder extends MessageToByteEncoder{ 14 | private Class genericClass; 15 | 16 | public RpcEncoder(Class genericClass){ 17 | this.genericClass=genericClass; 18 | } 19 | 20 | @Override 21 | protected void encode(ChannelHandlerContext channelHandlerContext, Object o, ByteBuf byteBuf) throws Exception { 22 | if(genericClass.isInstance(o)){ 23 | byte[] data= SerializationUtil.serialize(o); 24 | byteBuf.writeInt(data.length); 25 | byteBuf.writeBytes(data); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/staticOfFinal/proto/common/util/CollectionUtil.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.staticOfFinal.proto.common.util; 2 | 3 | import org.apache.commons.collections4.CollectionUtils; 4 | import org.apache.commons.collections4.MapUtils; 5 | 6 | import java.util.Collection; 7 | import java.util.Map; 8 | 9 | /** 10 | * @author 穆书伟 11 | * @description 集合工具类 12 | * @date 2017/6/5 0:16 13 | */ 14 | public class CollectionUtil { 15 | /** 16 | * 判断Collection 是否为空 17 | */ 18 | public static boolean isEmpty(Collection collection){ 19 | return CollectionUtils.isEmpty(collection); 20 | } 21 | 22 | /** 23 | * 判断Collection是否非空 24 | */ 25 | public static boolean isNotEmpty(Collection collection){ 26 | return !isEmpty(collection); 27 | } 28 | 29 | /** 30 | * 判断Map是否为空 31 | */ 32 | public static boolean isEmpty(Map map){ 33 | return MapUtils.isEmpty(map); 34 | } 35 | 36 | /** 37 | * 判断Map 是否非空 38 | */ 39 | public static boolean isNotEmpty(Map map){ 40 | return !isEmpty(map); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/staticOfFinal/proto/common/util/SerializationUtil.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.staticOfFinal.proto.common.util; 2 | 3 | import com.dyuproject.protostuff.LinkedBuffer; 4 | import com.dyuproject.protostuff.ProtostuffIOUtil; 5 | import com.dyuproject.protostuff.Schema; 6 | import com.dyuproject.protostuff.runtime.RuntimeSchema; 7 | import org.objenesis.Objenesis; 8 | import org.objenesis.ObjenesisStd; 9 | 10 | import java.io.ByteArrayInputStream; 11 | import java.io.ByteArrayOutputStream; 12 | import java.io.IOException; 13 | import java.util.List; 14 | import java.util.Map; 15 | import java.util.concurrent.ConcurrentHashMap; 16 | 17 | 18 | 19 | /** 20 | * @author 穆书伟 21 | * @description 序列化工具类(基于Protostuff实现) 22 | * @date 2017/6/5 0:35 23 | * 24 | */ 25 | public class SerializationUtil { 26 | 27 | private static Map,Schema> cachedSchema = new ConcurrentHashMap, Schema>(); 28 | 29 | private static Objenesis objenesis = new ObjenesisStd(true); 30 | 31 | private SerializationUtil(){ 32 | 33 | } 34 | 35 | 36 | /** 37 | * 序列化 (对象 -> 字节数组) 38 | */ 39 | @SuppressWarnings("unchecked") 40 | public static byte[] serialize(T obj){ 41 | Class cls =(Class) obj.getClass(); 42 | LinkedBuffer buffer =LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE); 43 | try { 44 | Schema schema = getSchema(cls); 45 | return ProtostuffIOUtil.toByteArray(obj, schema, buffer); 46 | }catch (Exception e){ 47 | throw new IllegalStateException(e.getMessage(),e); 48 | }finally { 49 | buffer.clear(); 50 | } 51 | } 52 | 53 | /** 54 | * 反序列化(字节数组 -> 对象) 55 | */ 56 | public static T deserialize(byte[] data,Class cls){ 57 | try{ 58 | T message =objenesis.newInstance(cls); 59 | Schema schema=getSchema(cls); 60 | ProtostuffIOUtil.mergeFrom(data,message,schema); 61 | return message; 62 | }catch (Exception e){ 63 | throw new IllegalStateException(e.getMessage(),e); 64 | } 65 | } 66 | 67 | @SuppressWarnings("unchecked") 68 | private static Schema getSchema(Class cls){ 69 | Schema schema=(Schema) cachedSchema.get(cls); 70 | if(schema ==null){ 71 | schema = RuntimeSchema.createFrom(cls); 72 | cachedSchema.put(cls,schema); 73 | } 74 | return schema; 75 | } 76 | 77 | /** 78 | * 序列化对象 79 | * @param obj 80 | * @return 81 | */ 82 | public static byte[] serializeObj(T obj){ 83 | if(obj == null){ 84 | throw new RuntimeException("序列化对象(" + obj + ")!"); 85 | } 86 | @SuppressWarnings("unchecked") 87 | Schema schema=(Schema) RuntimeSchema.getSchema(obj.getClass()); 88 | LinkedBuffer buffer = LinkedBuffer.allocate(1024 * 1024); 89 | byte[] protostuff= null; 90 | try{ 91 | protostuff = ProtostuffIOUtil.toByteArray(obj,schema,buffer); 92 | }catch (Exception e){ 93 | throw new RuntimeException("序列化(" +obj.getClass()+ ")对象("+ obj + ")发生异常!",e); 94 | }finally { 95 | buffer.clear(); 96 | } 97 | return protostuff; 98 | } 99 | 100 | /** 101 | * 反序列化对象 102 | * @param paramArrayOfByte 103 | * @param targetClass 104 | * @return 105 | */ 106 | 107 | public static T deserializeObj(byte[] paramArrayOfByte, Class targetClass){ 108 | if(paramArrayOfByte ==null || paramArrayOfByte.length ==0){ 109 | throw new RuntimeException("反序列化对象发生异常,byte序列为空!"); 110 | } 111 | T instance = null; 112 | 113 | try { 114 | instance = targetClass.newInstance(); 115 | } catch (InstantiationException e) { 116 | e.printStackTrace(); 117 | } catch (IllegalAccessException e) { 118 | e.printStackTrace(); 119 | } 120 | 121 | Schema schema= RuntimeSchema.getSchema(targetClass); 122 | ProtostuffIOUtil.mergeFrom(paramArrayOfByte,instance,schema); 123 | return instance; 124 | 125 | } 126 | 127 | /** 128 | * 序列化列表 129 | * @param objList 130 | * @param 131 | * @return 132 | */ 133 | 134 | public static byte[] serializeList(List objList){ 135 | if(objList ==null ||objList.isEmpty()){ 136 | throw new RuntimeException("序列化对象列表("+ objList +")参数异常!"); 137 | } 138 | @SuppressWarnings("uncheckd") 139 | Schema schema =(Schema) RuntimeSchema.getSchema(objList.get(0).getClass()); 140 | LinkedBuffer buffer= LinkedBuffer.allocate(1024 * 1024); 141 | byte[] protostuff =null; 142 | ByteArrayOutputStream bos=null; 143 | try { 144 | bos = new ByteArrayOutputStream(); 145 | ProtostuffIOUtil.writeListTo(bos,objList,schema,buffer); 146 | protostuff = bos.toByteArray(); 147 | }catch (Exception e){ 148 | throw new RuntimeException("序列化对象列表(" + objList + ")发生异常!", e); 149 | }finally { 150 | buffer.clear(); 151 | try{ 152 | if(bos !=null){ 153 | bos.close(); 154 | } 155 | }catch (IOException e){ 156 | e.printStackTrace(); 157 | } 158 | } 159 | return protostuff; 160 | } 161 | 162 | /** 163 | * 反序列化列表 164 | * @param paramArrayOfByte 165 | * @param targetClass 166 | * @param 167 | * @return 168 | */ 169 | 170 | public static List deserializeList(byte[] paramArrayOfByte, Class targetClass){ 171 | if(paramArrayOfByte == null || paramArrayOfByte.length ==0){ 172 | throw new RuntimeException("反序列化对象发生异常,byte序列为空!"); 173 | } 174 | Schema schema = RuntimeSchema.getSchema(targetClass); 175 | List result =null; 176 | 177 | try { 178 | result = ProtostuffIOUtil.parseListFrom(new ByteArrayInputStream(paramArrayOfByte),schema); 179 | } catch (IOException e) { 180 | throw new RuntimeException("反序列化对象列表发生异常!",e); 181 | } 182 | return result; 183 | 184 | } 185 | 186 | } 187 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/staticOfFinal/proto/common/util/StringUtil.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.staticOfFinal.proto.common.util; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | 5 | /** 6 | * @author 穆书伟 7 | * @description 字符串工具类 8 | * @date 2017/6/5 0:04 9 | */ 10 | public class StringUtil { 11 | /** 12 | * 判断字符串是否为空 13 | */ 14 | public static boolean isEmpty(String str){ 15 | if(str !=null){ 16 | str=str.trim(); 17 | } 18 | return StringUtils.isEmpty(str); 19 | } 20 | 21 | /** 22 | * 判断字符串是否非空 23 | */ 24 | public static boolean isNotEmpty(String str){ 25 | return !isEmpty(str); 26 | } 27 | 28 | /** 29 | * 分割固定格式的字符串 30 | */ 31 | public static String[] split(String str,String separator){ 32 | return StringUtils.splitByWholeSeparator(str,separator); 33 | } 34 | 35 | /** 36 | * 字符串取偶位数 37 | * @param str 38 | * @return 39 | */ 40 | 41 | public static String queryEven(String str){ 42 | char[] chars=str.toCharArray(); 43 | StringBuffer sb=new StringBuffer(); 44 | for (int i=1;i>>>>>>" + threadMax); 21 | executor = ExecutorServiceFactory.getInstance().createFixedThreadPool(threadMax); 22 | } 23 | private ExecutorProcessPool() { 24 | System.out.println("threadMax>>>>>>>" + threadMax); 25 | executor = ExecutorServiceFactory.getInstance().createFixedThreadPool(threadMax); 26 | } 27 | 28 | public static ExecutorProcessPool getInstance() { 29 | return pool; 30 | } 31 | 32 | /** 33 | * 关闭线程池,这里要说明的是:调用关闭线程池方法后,线程池会执行完队列中的所有任务才退出 34 | * 35 | * @author SHANHY 36 | * @date 2015年12月4日 37 | */ 38 | @PreDestroy 39 | public void shutdown(){ 40 | executor.shutdown(); 41 | } 42 | 43 | /** 44 | * 提交任务到线程池,可以接收线程返回值 45 | * 46 | * @param task 47 | * @return 48 | * @author SHANHY 49 | * @date 2015年12月4日 50 | */ 51 | public Future submit(Runnable task) { 52 | return executor.submit(task); 53 | } 54 | 55 | /** 56 | * 提交任务到线程池,可以接收线程返回值 57 | * 58 | * @param task 59 | * @return 60 | * @author SHANHY 61 | * @date 2015年12月4日 62 | */ 63 | public Future submit(Callable task) { 64 | return executor.submit(task); 65 | } 66 | 67 | /** 68 | * 直接提交任务到线程池,无返回值 69 | * 70 | * @param task 71 | * @author SHANHY 72 | * @date 2015年12月4日 73 | */ 74 | public void execute(Runnable task){ 75 | executor.execute(task); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/iot/threadpool/ExecutorServiceFactory.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.iot.threadpool; 2 | 3 | import java.util.concurrent.ExecutorService; 4 | import java.util.concurrent.Executors; 5 | import java.util.concurrent.ThreadFactory; 6 | import java.util.concurrent.atomic.AtomicInteger; 7 | 8 | /** 9 | * 10 | * @ClassName: ExecutorServiceFactory 11 | * @Description: TODO 线程池构造工厂 12 | * @author 穆书伟 13 | * @Email lovewsic@gmail.com 14 | * @date 2017年4月18日 下午14:14:30 15 | */ 16 | 17 | 18 | public class ExecutorServiceFactory { 19 | private static ExecutorServiceFactory executorFactory = new ExecutorServiceFactory(); 20 | /** 21 | * 定时任务线程池 22 | */ 23 | private ExecutorService executors; 24 | 25 | private ExecutorServiceFactory() { 26 | } 27 | 28 | /** 29 | * 获取ExecutorServiceFactory 30 | * 31 | * @return 32 | */ 33 | public static ExecutorServiceFactory getInstance() { 34 | return executorFactory; 35 | } 36 | 37 | /** 38 | * 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。 39 | * 40 | * @return 41 | */ 42 | public ExecutorService createScheduledThreadPool() { 43 | // CPU个数 44 | int availableProcessors = Runtime.getRuntime().availableProcessors(); 45 | // 创建 46 | executors = Executors.newScheduledThreadPool(availableProcessors * 10, getThreadFactory()); 47 | return executors; 48 | } 49 | 50 | /** 51 | * 创建一个使用单个 worker 线程的 52 | * Executor,以无界队列方式来运行该线程。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程, 53 | * 那么如果需要,一个新线程将代替它执行后续的任务)。可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。与其他等效的 54 | * newFixedThreadPool(1) 不同,可保证无需重新配置此方法所返回的执行程序即可使用其他的线程。 55 | * 56 | * @return 57 | */ 58 | public ExecutorService createSingleThreadExecutor() { 59 | // 创建 60 | executors = Executors.newSingleThreadExecutor(getThreadFactory()); 61 | return executors; 62 | } 63 | 64 | /** 65 | * 创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 66 | * execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 67 | * 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。注意,可以使用 ThreadPoolExecutor 68 | * 构造方法创建具有类似属性但细节不同(例如超时参数)的线程池。 69 | * 70 | * @return 71 | */ 72 | public ExecutorService createCachedThreadPool() { 73 | // 创建 74 | executors = Executors.newCachedThreadPool(getThreadFactory()); 75 | return executors; 76 | } 77 | 78 | /** 79 | * 创建一个可重用固定线程数的线程池,以共享的无界队列方式来运行这些线程。在任意点,在大多数 nThreads 80 | * 线程会处于处理任务的活动状态。如果在所有线程处于活动状态时提交附加任务 81 | * ,则在有可用线程之前,附加任务将在队列中等待。如果在关闭前的执行期间由于失败而导致任何线程终止 82 | * ,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在。 83 | * 84 | * @return 85 | */ 86 | public ExecutorService createFixedThreadPool(int count) { 87 | // 创建 88 | executors = Executors.newFixedThreadPool(count, getThreadFactory()); 89 | return executors; 90 | } 91 | 92 | 93 | /** 94 | * 获取线程池工厂 95 | * 96 | * @return 97 | */ 98 | private ThreadFactory getThreadFactory() { 99 | return new ThreadFactory() { 100 | AtomicInteger sn = new AtomicInteger(); 101 | public Thread newThread(Runnable r) { 102 | SecurityManager s = System.getSecurityManager(); 103 | ThreadGroup group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(); 104 | Thread t = new Thread(group, r); 105 | t.setName("任务线程 - " + sn.incrementAndGet()); 106 | return t; 107 | } 108 | }; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/quartz/IotQuartz.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.quartz; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | /** 7 | * @author 穆书伟 8 | * @description 添加时间调度 9 | * @date 2017/5/31 15:18 10 | */ 11 | public class IotQuartz { 12 | private final Logger LOG= LoggerFactory.getLogger(this.getClass()); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/service/DeviceStatusService.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.service; 2 | 3 | import com.haro.netty.test.pojo.DeviceStatus; 4 | 5 | /** 6 | * @author 穆书伟 7 | * @descriptin 服务接口Service 8 | * @date 2017/5/22 18:37 9 | */ 10 | public interface DeviceStatusService { 11 | void updateIotDeviceIccid(DeviceStatus deviceBasicInfo); 12 | 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/service/Impl/DeviceStatusServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.service.Impl; 2 | 3 | import com.haro.netty.service.DeviceStatusService; 4 | import com.haro.netty.test.mapper.DeviceStatusMapper; 5 | import com.haro.netty.test.pojo.DeviceStatus; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | import org.springframework.transaction.annotation.Transactional; 9 | 10 | /** 11 | * @author 穆书伟 12 | * @descriptin 服务接口实现类Impl 13 | * @date 2017/5/22 18:37 14 | */ 15 | @Service("deviceDeviceIccid") 16 | @Transactional 17 | public class DeviceStatusServiceImpl implements DeviceStatusService { 18 | 19 | @Autowired 20 | private DeviceStatusMapper deviceStatusMapper; 21 | 22 | public void setDeviceStatusMapper(DeviceStatusMapper deviceStatusMapper) { 23 | this.deviceStatusMapper = deviceStatusMapper; 24 | } 25 | 26 | public void updateIotDeviceIccid(DeviceStatus deviceBasicInfo) { 27 | deviceStatusMapper.updateIotDeviceIccid(deviceBasicInfo); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/service/Impl/QueryStatusForLightServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.service.Impl; 2 | 3 | import com.haro.netty.service.QueryStatusForLightService; 4 | import com.haro.netty.test.mapper.DeviceStatusMapper; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.stereotype.Service; 7 | import org.springframework.transaction.annotation.Transactional; 8 | 9 | /** 10 | * @ClassName QueryStatusForLightServiceImpl 11 | * @author 穆书伟 12 | * @description 设备状态灯变化实现类 13 | * @date 2017/6/19 12:44 14 | */ 15 | @Service("deviceDeviceForLight") 16 | @Transactional 17 | public class QueryStatusForLightServiceImpl implements QueryStatusForLightService{ 18 | @Autowired 19 | private DeviceStatusMapper deviceStatusMapper; 20 | 21 | public void setDeviceStatusMapper(DeviceStatusMapper deviceStatusMapper) { 22 | this.deviceStatusMapper = deviceStatusMapper; 23 | } 24 | 25 | public int SendCommandForLight(String eqp_comid) { 26 | return deviceStatusMapper.SendCommandForLight(eqp_comid); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/service/Impl/StatusDeviceServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.service.Impl; 2 | 3 | import com.haro.netty.service.StatusDeviceService; 4 | import com.haro.netty.test.mapper.DeviceStatusMapper; 5 | import com.haro.netty.test.pojo.DeviceStatus; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Service; 8 | import org.springframework.transaction.annotation.Transactional; 9 | 10 | /** 11 | * @author 穆书伟 12 | * @descriptin 服务接口实现类Impl 13 | * @date 2017/5/22 18:37 14 | */ 15 | @Service("deviceDeviceStatus") 16 | @Transactional 17 | public class StatusDeviceServiceImpl implements StatusDeviceService { 18 | @Autowired 19 | private DeviceStatusMapper deviceStatusMapper; 20 | 21 | public void setDeviceStatusMapper(DeviceStatusMapper deviceStatusMapper) { 22 | this.deviceStatusMapper = deviceStatusMapper; 23 | } 24 | 25 | public void updateIotDeviceStatus(DeviceStatus deviceStatus) { 26 | deviceStatusMapper.updateIotDeviceStatus(deviceStatus); 27 | 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/service/QueryStatusForLightService.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.service; 2 | 3 | /** 4 | * @ClassName QueryStatusForLightService 5 | * @author 穆书伟 6 | * @description 设备状态灯变化接口 7 | * @date 2017/6/19 12:43 8 | */ 9 | public interface QueryStatusForLightService { 10 | int SendCommandForLight(String eqp_comid); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/service/StatusDeviceService.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.service; 2 | 3 | import com.haro.netty.test.pojo.DeviceStatus; 4 | 5 | /** 6 | * @author 穆书伟 7 | * @descriptin 服务接口Service 8 | * @date 2017/5/22 18:37 9 | */ 10 | public interface StatusDeviceService { 11 | void updateIotDeviceStatus(DeviceStatus deviceStatus); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/test/mapper/DeviceStatusMapper.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.test.mapper; 2 | 3 | import com.haro.netty.test.pojo.DeviceStatus; 4 | import org.apache.ibatis.annotations.Select; 5 | import org.apache.ibatis.annotations.Update; 6 | 7 | /** 8 | * @author 穆书伟 9 | * @description 利用mybatis注释sql映射到数据库 10 | * @date 2017-5-22 17:56 11 | * @comment updateIotDeviceIccid 把设备的设备通讯码保存到数据库中 12 | * updateIotDeviceStatus 实时更新设备状态 13 | */ 14 | public interface DeviceStatusMapper { 15 | 16 | @Update(" UPDATE eqp_basicinfo\n" + 17 | " SET iccid=#{iccid}, status_id=#{status_id} \n" + 18 | " " + 19 | " WHERE eqp_comid=#{eqp_comid} AND status_id !=3 AND status_id !=4") 20 | void updateIotDeviceIccid(DeviceStatus deviceBasicInfo); 21 | 22 | @Update(" UPDATE eqp_basicinfo \n" + 23 | " SET status_id=5 \n" + 24 | " WHERE eqp_comid=#{eqp_comid} AND status_id!=2") 25 | void updateIotDeviceStatus(DeviceStatus deviceStatus); 26 | 27 | @Select(" SELECT status_id \n " + 28 | " FROM eqp_basicinfo \n" + 29 | " where eqp_comid=#{eqp_comid AND deleted=0") 30 | int SendCommandForLight(String eqp_comid); 31 | } -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/test/pojo/DeviceStatus.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.test.pojo; 2 | 3 | import java.util.Date; 4 | 5 | /** 6 | * @author 穆书伟 7 | * @description domain类 8 | * @date 2017/5/22 18:35 9 | */ 10 | public class DeviceStatus { 11 | 12 | private int eqp_id; 13 | 14 | private Date create_time; 15 | 16 | private int deleted; 17 | 18 | private String eqp_comid; 19 | 20 | private int location_id; 21 | 22 | private String eqp_location; 23 | 24 | private int brand_id; 25 | 26 | private int eqptype_id; 27 | 28 | private int card_reader; 29 | 30 | private Date install_time; 31 | 32 | private String iccid; 33 | 34 | private int status_id; 35 | 36 | private int check_status; 37 | 38 | private int statuscy_id; 39 | 40 | public int getStatuscy_id() { 41 | return statuscy_id; 42 | } 43 | 44 | public void setStatuscy_id(int statuscy_id) { 45 | this.statuscy_id = statuscy_id; 46 | } 47 | 48 | public int getEqp_id() { 49 | return eqp_id; 50 | } 51 | 52 | public void setEqp_id(int eqp_id) { 53 | this.eqp_id = eqp_id; 54 | } 55 | 56 | public Date getCreate_time() { 57 | return create_time; 58 | } 59 | 60 | public void setCreate_time(Date create_time) { 61 | this.create_time = create_time; 62 | } 63 | 64 | public int getDeleted() { 65 | return deleted; 66 | } 67 | 68 | public void setDeleted(int deleted) { 69 | this.deleted = deleted; 70 | } 71 | 72 | public String getEqp_comid() { 73 | return eqp_comid; 74 | } 75 | 76 | public void setEqp_comid(String eqp_comid) { 77 | this.eqp_comid = eqp_comid; 78 | } 79 | 80 | public int getLocation_id() { 81 | return location_id; 82 | } 83 | 84 | public void setLocation_id(int location_id) { 85 | this.location_id = location_id; 86 | } 87 | 88 | public String getEqp_location() { 89 | return eqp_location; 90 | } 91 | 92 | public void setEqp_location(String eqp_location) { 93 | this.eqp_location = eqp_location; 94 | } 95 | 96 | public int getBrand_id() { 97 | return brand_id; 98 | } 99 | 100 | public void setBrand_id(int brand_id) { 101 | this.brand_id = brand_id; 102 | } 103 | 104 | public int getEqptype_id() { 105 | return eqptype_id; 106 | } 107 | 108 | public void setEqptype_id(int eqptype_id) { 109 | this.eqptype_id = eqptype_id; 110 | } 111 | 112 | public int getCard_reader() { 113 | return card_reader; 114 | } 115 | 116 | public void setCard_reader(int card_reader) { 117 | this.card_reader = card_reader; 118 | } 119 | 120 | public Date getInstall_time() { 121 | return install_time; 122 | } 123 | 124 | public void setInstall_time(Date install_time) { 125 | this.install_time = install_time; 126 | } 127 | 128 | public String getIccid() { 129 | return iccid; 130 | } 131 | 132 | public void setIccid(String iccid) { 133 | this.iccid = iccid; 134 | } 135 | 136 | public int getStatus_id() { 137 | return status_id; 138 | } 139 | 140 | public void setStatus_id(int status_id) { 141 | this.status_id = status_id; 142 | } 143 | 144 | public int getCheck_status() { 145 | return check_status; 146 | } 147 | 148 | public void setCheck_status(int check_status) { 149 | this.check_status = check_status; 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/util/Base64Utils.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.util; 2 | 3 | import javax.xml.bind.DatatypeConverter; 4 | import java.nio.charset.Charset; 5 | 6 | /** 7 | * JDK6之后 Base64工具 8 | * 9 | * 参考:http://www.importnew.com/14961.html 10 | */ 11 | public class Base64Utils { 12 | private Base64Utils() {} 13 | 14 | /** 15 | * 编码 16 | * @param value byte数组 17 | * @return {String} 18 | */ 19 | public static String encode(byte[] value) { 20 | return DatatypeConverter.printBase64Binary(value); 21 | } 22 | 23 | /** 24 | * 编码 25 | * @param value 字符串 26 | * @return {String} 27 | */ 28 | public static String encode(String value) { 29 | byte[] val = value.getBytes(Charsets.UTF_8); 30 | return Base64Utils.encode(val); 31 | } 32 | 33 | /** 34 | * 编码 35 | * @param value 字符串 36 | * @param charsetName charSet 37 | * @return {String} 38 | */ 39 | public static String encode(String value, String charsetName) { 40 | byte[] val = value.getBytes(Charset.forName(charsetName)); 41 | return Base64Utils.encode(val); 42 | } 43 | 44 | /** 45 | * 解码 46 | * @param value 字符串 47 | * @return {byte[]} 48 | */ 49 | public static byte[] decodeBase64(String value) { 50 | return DatatypeConverter.parseBase64Binary(value); 51 | } 52 | 53 | /** 54 | * 解码 55 | * @param value 字符串 56 | * @return {String} 57 | */ 58 | public static String decode(String value) { 59 | byte[] decodedValue = Base64Utils.decodeBase64(value); 60 | return new String(decodedValue, Charsets.UTF_8); 61 | } 62 | 63 | /** 64 | * 解码 65 | * @param value 字符串 66 | * @param charsetName 字符集 67 | * @return {String} 68 | */ 69 | public static String decode(String value, String charsetName) { 70 | byte[] decodedValue = Base64Utils.decodeBase64(value); 71 | return new String(decodedValue, Charset.forName(charsetName)); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/util/ByteUtil.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.util; 2 | 3 | import java.util.zip.Inflater; 4 | 5 | /** 6 | * 7 | * @ClassName: ByteUtil 8 | * @Description: TODO Byte 数组管理 9 | * @author 穆书伟 10 | * @Email lovewsic@gmail.com 11 | * @date 2017年1月18日 下午3:45:16 12 | */ 13 | public class ByteUtil { 14 | /** 15 | * @Title:byteToChar 16 | * @Description:TODO byte类型转换成Char 17 | */ 18 | public static void Str2Hex(char[] sSrc,byte[] sDest,int nSrcLen){ 19 | for(int i=0;i='0'&& hex_ch <= '9') 34 | { 35 | 36 | return hex_ch-'0'; 37 | 38 | } 39 | if (hex_ch >= 'a' && hex_ch <= 'f') 40 | { 41 | return hex_ch - 'a' + 10; 42 | 43 | 44 | } 45 | 46 | if (hex_ch >= 'A' && hex_ch <= 'F') 47 | { 48 | return hex_ch - 'A' + 10; 49 | } 50 | return 0x00; 51 | 52 | } 53 | 54 | /** 55 | * 56 | * @Title: ByteToInt 57 | * @Description: TODO Byte 转成 Int 58 | * @param @param readbuf 59 | * @param @return 参数 60 | * @return int 返回类型 61 | * @throws 62 | */ 63 | public static int ByteToInt(byte[]readbuf){ 64 | String str = ""; 65 | for(int i = 0; i< readbuf.length ; i++){ 66 | if(readbuf[i]==0){ 67 | str += "00"; 68 | }else if(readbuf[i] >= 1 && readbuf[i] <= 9){ 69 | str += "0" + Byte.toString(readbuf[i]); 70 | }else { 71 | str +=Byte.toString(readbuf[i]); 72 | } 73 | } 74 | int s =Integer.parseInt(str); 75 | return s; 76 | } 77 | public static int ByteToInt(byte[]readbuf,int start,int end){ 78 | String str = ""; 79 | for(int i = start; i<= end ; i++){ 80 | if(readbuf[i]==0){ 81 | str += "00"; 82 | }else if(readbuf[i] >= 1 && readbuf[i] <= 9){ 83 | str += "0" + Byte.toString(readbuf[i]); 84 | }else { 85 | str +=Byte.toString(readbuf[i]); 86 | } 87 | } 88 | int s =Integer.parseInt(str); 89 | return s; 90 | } 91 | /** 92 | * 93 | * @Title: ByteToString 94 | * @Description: TODO 95 | * @param @param readBuf 96 | * @param @return 参数 97 | * @return String 返回类型 98 | * @throws 99 | */ 100 | public static String ByteToString(byte[]readBuf){ 101 | String str = ""; 102 | for(int i = 0; i< readBuf.length ; i++){ 103 | if(readBuf[i]==0){ 104 | str += "00"; 105 | }else if(readBuf[i] >= 1 && readBuf[i] <= 9){ 106 | str += "0" + Byte.toString(readBuf[i]); 107 | }else { 108 | str +=Byte.toString(readBuf[i]); 109 | } 110 | } 111 | return str; 112 | } 113 | public static String ByteToString(byte[]readBuf,int start,int end){ 114 | String str = ""; 115 | if(start > end || start < 0 || end < 0 || start >readBuf.length || end > readBuf.length ){ 116 | return null; 117 | } 118 | for(int i = start; i<= end ; i++){ 119 | if(readBuf[i]==0){ 120 | str += "00"; 121 | }else if(readBuf[i] >= 1 && readBuf[i] <= 9){ 122 | str += "0" + Byte.toString(readBuf[i]); 123 | }else { 124 | str +=Byte.toString(readBuf[i]); 125 | } 126 | } 127 | return str; 128 | } 129 | /** 130 | * 将字节数组转换为十六进制字符串 131 | * 132 | * @param src 133 | * 字节数组 134 | * @return 135 | */ 136 | public static String bytesToHexString(byte[] src) { 137 | StringBuilder stringBuilder = new StringBuilder(""); 138 | if (src == null || src.length <= 0) { 139 | return null; 140 | } 141 | for (int i = 0; i < src.length; i++) { 142 | int v = src[i] & 0xFF; 143 | String hv = Integer.toHexString(v); 144 | if (hv.length() < 2) { 145 | stringBuilder.append(0); 146 | } 147 | stringBuilder.append(hv); 148 | stringBuilder.append(' '); 149 | } 150 | String str= stringBuilder.toString(); 151 | return str.toUpperCase(); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/util/Charsets.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.util; 2 | 3 | import java.nio.charset.Charset; 4 | 5 | public class Charsets { 6 | // 字符集GBK 7 | public static final Charset GBK = Charset.forName("GBK"); 8 | // 字符集ISO-8859-1 9 | public static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); 10 | // 字符集utf-8 11 | public static final Charset UTF_8 = Charset.forName("UTF-8"); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/util/ContextHolderUtils.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.util; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | import javax.servlet.http.HttpSession; 5 | 6 | import org.springframework.web.context.request.RequestContextHolder; 7 | import org.springframework.web.context.request.ServletRequestAttributes; 8 | /** 9 | * @ClassName: ContextHolderUtils 10 | * @Description: TODO(上下文工具类) 11 | * @author 穆书伟 12 | * @date 2017-5-23 下午18:12 13 | * 14 | */ 15 | public class ContextHolderUtils { 16 | /** 17 | * SpringMvc下获取request 18 | * 19 | * @return 20 | */ 21 | public static HttpServletRequest getRequest() { 22 | HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); 23 | return request; 24 | 25 | } 26 | /** 27 | * SpringMvc下获取session 28 | * 29 | * @return 30 | */ 31 | public static HttpSession getSession() { 32 | HttpSession session = getRequest().getSession(); 33 | return session; 34 | 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/util/IpUtil.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.util; 2 | 3 | import javax.servlet.http.HttpServletRequest; 4 | 5 | public class IpUtil { 6 | /** 7 | * 获取登录用户IP地址 8 | * 9 | * @param request 10 | * @return 11 | */ 12 | public static String getIpAddr(HttpServletRequest request) { 13 | String ip = request.getHeader("x-forwarded-for"); 14 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 15 | ip = request.getHeader("Proxy-Client-IP"); 16 | } 17 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 18 | ip = request.getHeader("WL-Proxy-Client-IP"); 19 | } 20 | if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { 21 | ip = request.getRemoteAddr(); 22 | } 23 | if (ip.equals("0:0:0:0:0:0:0:1")) { 24 | ip = "本地"; 25 | } 26 | return ip; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/haro/netty/util/SpringUtil.java: -------------------------------------------------------------------------------- 1 | package com.haro.netty.util; 2 | 3 | import org.springframework.beans.BeansException; 4 | import org.springframework.context.ApplicationContext; 5 | import org.springframework.context.ApplicationContextAware; 6 | 7 | public class SpringUtil implements ApplicationContextAware{ 8 | private static ApplicationContext applicationContext; 9 | 10 | public static ApplicationContext getApplicationContext() { 11 | return applicationContext; 12 | } 13 | 14 | public void setApplicationContext(ApplicationContext applicationContext)throws BeansException { 15 | SpringUtil.applicationContext = applicationContext; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/resources/dbconfig.properties: -------------------------------------------------------------------------------- 1 | driverClassName= 2 | jdbc_url= 3 | jdbc_username= 4 | jdbc_password= 5 | 6 | druid.pool.size.max=50 7 | druid.pool.size.min=3 8 | druid.pool.size.init=3 9 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | ### set log levels ### 2 | log4j.rootLogger = INFO , C , D , E 3 | 4 | ### console ### 5 | log4j.appender.C = org.apache.log4j.ConsoleAppender 6 | log4j.appender.C.Target = System.out 7 | log4j.appender.C.layout = org.apache.log4j.PatternLayout 8 | log4j.appender.C.layout.ConversionPattern = [mylog-console][%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C.%M(%L) | %m%n 9 | 10 | ### log file ### 11 | log4j.appender.D = org.apache.log4j.DailyRollingFileAppender 12 | log4j.appender.D.File = logs/info/mylog-info.log 13 | log4j.appender.D.Append = true 14 | log4j.appender.D.Threshold = INFO 15 | log4j.appender.D.layout = org.apache.log4j.PatternLayout 16 | log4j.appender.D.layout.ConversionPattern = [mylog-info][%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C.%M(%L) | %m%n 17 | 18 | ### exception ### 19 | log4j.appender.E = org.apache.log4j.DailyRollingFileAppender 20 | log4j.appender.E.File = logs/error/error.log 21 | log4j.appender.E.Append = true 22 | log4j.appender.E.Threshold = ERROR 23 | log4j.appender.E.layout = org.apache.log4j.PatternLayout 24 | log4j.appender.E.layout.ConversionPattern = [mylog-error][%p] [%-d{yyyy-MM-dd HH:mm:ss}] %C.%M(%L) | %m%n -------------------------------------------------------------------------------- /src/main/resources/netty-server.properties: -------------------------------------------------------------------------------- 1 | tcp.port=8090 2 | boss.thread.count=2 3 | worker.thread.count=2 4 | so.keepalive=true 5 | so.backlog=100 6 | log4j.configuration=SpringNettyLog4j.properties -------------------------------------------------------------------------------- /src/main/resources/redis.properties: -------------------------------------------------------------------------------- 1 | #redis config 2 | redis.pass=jamesmsw 3 | redis.pool.maxTotal=105 4 | redis.pool.maxIdle=10 5 | redis.pool.maxWaitMillis=5000 6 | redis.pool.testOnBorrow=true 7 | 8 | #redis 9 | redis.ip=115.159.58.92 10 | redis.port=6379 -------------------------------------------------------------------------------- /src/main/resources/spring-mybatis.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/main/resources/spring-quartz.xml: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main/resources/spring-redis.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 57 | 58 | 59 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /src/main/resources/spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/main/webapp/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | Archetype Created Web Application 7 | 8 | 9 | contextConfigLocation 10 | classpath:spring.xml,classpath:spring-mybatis.xml 11 | 12 | 13 | 14 | encodingFilter 15 | org.springframework.web.filter.CharacterEncodingFilter 16 | 17 | encoding 18 | utf-8 19 | 20 | 21 | forceEncoding 22 | true 23 | 24 | 25 | 26 | encodingFilter 27 | /* 28 | 29 | 30 | org.springframework.web.context.ContextLoaderListener 31 | 32 | 33 | 34 | org.springframework.web.util.IntrospectorCleanupListener 35 | 36 | 37 | 38 | DruidStatView 39 | com.alibaba.druid.support.http.StatViewServlet 40 | 41 | 42 | DruidStatView 43 | /druid/* 44 | 45 | 46 | 47 | DruidWebStatFilter 48 | com.alibaba.druid.support.http.WebStatFilter 49 | 50 | exclusions 51 | *.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/* 52 | 53 | 54 | 55 | DruidWebStatFilter 56 | /* 57 | 58 | 59 | 60 | 61 | 62 | 30 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /test/main/java/client/Client.java: -------------------------------------------------------------------------------- 1 | package client; 2 | 3 | import io.netty.bootstrap.Bootstrap; 4 | import io.netty.channel.*; 5 | import io.netty.channel.nio.NioEventLoopGroup; 6 | import io.netty.channel.socket.SocketChannel; 7 | import io.netty.channel.socket.nio.NioSocketChannel; 8 | import io.netty.handler.codec.DatagramPacketDecoder; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | /** 13 | * @author 穆书伟 14 | * @description Simple client for module test 15 | * @date 2017/6/13 下午16:05:22 16 | */ 17 | public class Client { 18 | static final String HOST = System.getProperty("host", "127.0.0.1"); 19 | static final int PORT = Integer.parseInt(System.getProperty("port", "8090")); 20 | public static final int clientNum = Integer.parseInt(System.getProperty("size", "10")); 21 | public static final int frequency = 100; //ms 22 | 23 | public static void main(String[] args) throws Exception{ 24 | beginPressTest(); 25 | } 26 | 27 | private static final Logger logger = LoggerFactory.getLogger(Client.class); 28 | 29 | public static void beginPressTest() throws InterruptedException{ 30 | EventLoopGroup group = new NioEventLoopGroup(); 31 | Bootstrap b = new Bootstrap(); 32 | b.group(group) 33 | .channel(NioSocketChannel.class) 34 | .option(ChannelOption.TCP_NODELAY,true) 35 | .handler(new ChannelInitializer() { 36 | @Override 37 | protected void initChannel(SocketChannel socketChannel) throws Exception { 38 | ChannelPipeline p=socketChannel.pipeline(); 39 | // 40 | 41 | 42 | 43 | } 44 | }); 45 | // Start the client 46 | 47 | for (int i=1;i