首页 文章 精选 留言 我的

精选列表

搜索[连接],共10000篇文章
优秀的个人博客,低调大师

反应式微框架 Reactor-Guice 0.12.5, 修复 websocket 连接退出

Reactor-guice 是一个基于 Google Guice 和 Reactor-netty 的 反应式微服务框架 设计为大家喜欢的通过注解来配置路由,性能基于反应式框架的特点,非常的高效。 对于 web 开发常见的 Json, Protobuf, 表单,文件上传,websocket ,都是轻松支持 0.0.3 注册注解 @GET @POST @PUT @DELETE @Products @PATH 支持 Websocket 可作为静态文件服 支持对 URI 做 Filter 处理 0.0.5 静态文件目录后默认输出 index.html 支持自选模板引擎,自带Freemark 和 Thymeleaf 处理类 支持自定义Json引擎,自带 Gson 和jackson 的处理类 添加 ModelMap, 注入到 Controlle 的方法,用户模板的变量代入 可以上传文件了 0.0.8 可以 POST 数组 通过返回 Mono.just("redirect:/...") 实现重定向 支持 API 网关模式 修复头信息错误的 BUG 可选返回跨域头信息 0.10 支持输出 Protobuf BeanParm 可以支持 Form ,Json 或 Protobuf ,将上传的数据自动组织成对象 上传的文件接受类型 byte[] , UploadFile, File 上传文件可以自动保存到指定的目录 0.11 增加自动扫描 Controlle 类和 Service 类 通过扫描完成路由配置和依赖注入,不同手动做额外配置 0.12.1 静态文件的读取塞入到异步中去处理 这个版本是一个稳定的版本 0.12.2 优化 Jar 内读取文件的变量 简化 websocket 的接口 网关模式增加 websocket 0.12.4 增加 Https (0.12.3) 静态文件目录可配置多个 修复上传文件多次后,溢出的情况,补充 FileUpload.release() 修复非 Form POST ,错误的做了 Bytebuf.release() 0.12.5 修复 websocket 长链接 bug 1. 引入 reactor-guice maven <dependency> <groupId>com.doopp</groupId> <artifactId>reactor-guice</artifactId> <version>0.12.5</version> </dependency> gradle compile 'com.doopp:reactor-guice:0.12.5' 2. 创建应用 public static void main(String[] args) throws IOException { // 载入配置 Properties properties = new Properties(); properties.load(new FileInputStream(args[0])); String host = properties.getProperty("server.host"); int port = Integer.valueOf(properties.getProperty("server.port")); // 启动服务 ReactorGuiceServer.create() .bind(host, port) .createInjector( // 方便使用 @Names 来获取配置 binder -> Names.bindProperties(binder, properties), // 数据库 new MyBatisModule() { @Override protected void initialize() { install(JdbcHelper.MySQL); bindDataSourceProviderType(HikariDataSourceProvider.class); bindTransactionFactoryType(JdbcTransactionFactory.class); addMapperClasses("com.doopp.gauss.app.dao"); // addInterceptorClass(PageInterceptor.class); } }, // Redis new RedisModule(), // 自定义的配置 new ApplicationModule() ) // 配置 Json 处理类 .setHttpMessageConverter(new MyGsonHttpMessageConverter()) // 设定自动扫描 Controller 和 Service 的包名,可以配置多个 .basePackages("com.doopp.gauss.app", ...) // 配置多个静态资源 .addResource("/static/", "/static-public/") .addResource("/", "/public/") // https .setHttps(new File(jksFilePath), jksPassword, jksSecret) // 目前仅支持通过 URI 来过滤,可以多次 addFilter .addFilter("/", AppFilter.class) // 错误信息输出 .printError(true) .launch(); } 3. 创建 Controller Controller Example @Controller @Path("/api/admin") public class ExampleController { @GET @Path("/json") @Produces({MediaType.APPLICATION_JSON}) public Mono<Map<String, String>> json() { return Mono .just(new HashMap<String, String>()) .map(m -> { m.put("hi", "five girl"); return m; }); } @GET @Path("/jpeg") @Produces({"image/jpeg"}) public Mono<ByteBuf> jpeg() { return HttpClient.create() .get() .uri("https://static.cnbetacdn.com/article/2019/0402/6398390c491f650.jpg") .responseContent() .aggregate() .map(ByteBuf::retain); } } WebSocket @Path("/kreactor/ws") @Singleton public class WsTestHandle extends AbstractWebSocketServerHandle { @Override public void connected(Channel channel) { System.out.println(channel.id()); super.connected(channel); } @Override public void onTextMessage(TextWebSocketFrame frame, Channel channel) { System.out.println(frame.text()); super.onTextMessage(frame, channel); } } Api Gateway 模式 ReactorGuiceServer.create() .bind(host, port) .setApiGatewayDispatcher(new MyApiGatewayDispatcher()) .addFilter("/", TestFilter.class) .launch(); 混合的 Api Gateway Model ReactorGuiceServer.create() .bind(host, port) .createInjector(module1, module2, ...) .setHttpMessageConverter(new JacksonHttpMessageConverter()) .setApiGatewayDispatcher(new MyApiGatewayDispatcher()) .handlePackages("com.doopp.reactor.guice.test") .addFilter("/", TestFilter.class) .launch(); 表单和文件上传 // Server @POST @Path("/test/post-bean") public Mono<User> testPostBean(@BeanParam User user, @FileParam(value="image", path = "C:\\Users\\koocyton\\Desktop") File[] file) { return Mono.just(user); } // Client Test @Test public void testFileUpload() { String hhe = HttpClient.create() .post() .uri("http://127.0.0.1:8083/kreactor/test/post-bean") .sendForm((req, form) -> form.multipart(true) .attr("id", "123123121312312") .attr("account", "account") .attr("password", "password") .attr("name", "name") .file("image", new File("C:\\Users\\koocyton\\Pictures\\cloud.jpg")) .file("image", new File("C:\\Users\\koocyton\\Pictures\\st.jpg")) ) .responseSingle((res, content) -> content) .map(byteBuf -> byteBuf.toString(CharsetUtil.UTF_8)) .block(); System.out.println(hhe); } Protobuf // Server @POST @Path("/test/proto-post-bean") public Mono<Hello> testPostBean(@BeanParam Hello hello) { return Mono.just(hello); } // Test Client @Test public void testPostProtobufBean() { Hello.Builder builder = Hello.newBuilder(); builder.setId(123); builder.setName("wuyi"); builder.setEmail("wuyi@doopp.com"); ByteBuf buf = Unpooled.wrappedBuffer(builder.build().toByteArray()).retain(); String hhe = HttpClient.create() .headers(headers -> { headers.add(HttpHeaderNames.CONTENT_TYPE, "application/x-protobuf"); }) .post() .uri("http://127.0.0.1:8083/kreactor/test/proto-post-bean") .send(Flux.just(buf.retain())) .responseSingle((res, content) -> content) .map(byteBuf -> byteBuf.toString(CharsetUtil.UTF_8)) .block(); System.out.println(hhe); }

优秀的个人博客,低调大师

使用ABAP(ADBC)和Java(JDBC)连接SAP HANA数据库

在表DBCON里维护一条记录,指向HANA数据库。con_ENV里填入HANA数据库的主机名和端口号。如vmXXXX:30015 DATA: ls_new TYPE DBCON. ls_new-con_name = 'HAN'. ls_new-dbms = 'HDB'. ls_new-user_name = 'system'. ls_new-password = 'Sap12345'. ls_new-con_env = 'vml2018:30015'. CALL FUNCTION 'DBCON_INSERT' EXPORTING DBCON_WORKAREA = ls_new EXCEPTIONS DBCON_KEY_EXISTS = 1 SECURE_STORE_KEY_EXISTS = 2 SECURE_STORE_OTHER = 3 OTHERS = 4 . IF SY-SUBRC = 0. WRITE:/ 'Insert Successfully'. ENDIF. 然后使用ABAP代码创建一个新的table,插入三条entry进行,再读出来,最后删除table. TYPES: BEGIN OF result_t, key TYPE i, value TYPE string, END OF result_t. DATA: connection TYPE dbcon-con_name VALUE 'HAN', stmt_ref TYPE REF TO cl_sql_statement, cx_sql_exception TYPE REF TO cx_sql_exception, lv_text TYPE string, res_ref TYPE REF TO cl_sql_result_set, d_ref TYPE REF TO DATA, result_tab TYPE TABLE OF result_t, result_line TYPE result_t, row_cnt TYPE i, con_ref TYPE REF TO cl_sql_connection. con_ref = cl_sql_connection=>get_connection( connection ). stmt_ref = con_ref->create_statement( ). TRY. stmt_ref->execute_ddl( 'CREATE TABLE I042416_TESTPROC_TAB( key INT PRIMARY KEY, value NVARCHAR(255) )' ). stmt_ref->execute_update( 'INSERT INTO I042416_TESTPROC_TAB VALUES(1, ''First value'' )' ). stmt_ref->execute_update( 'INSERT INTO I042416_TESTPROC_TAB VALUES(2, ''Second value'' )' ). stmt_ref->execute_update( 'INSERT INTO I042416_TESTPROC_TAB VALUES(3, ''Third value'' )' ). res_ref = stmt_ref->execute_query( 'SELECT * FROM I042416_TESTPROC_TAB' ). GET REFERENCE OF result_tab INTO d_ref. res_ref->set_param_table( d_ref ). row_cnt = res_ref->next_package( ). stmt_ref->execute_ddl( 'DROP TABLE I042416_TESTPROC_TAB' ). CATCH cx_sql_exception INTO cx_sql_exception. lv_text = cx_sql_exception->get_text( ). WRITE:/ 'Error:' , lv_text. ENDTRY. LOOP AT result_tab INTO result_line. WRITE:/ 'Key:' , result_line-key, ' Value:', result_line-value. ENDLOOP. Java实现类似: public static void main(String[] args) { try { Class.forName("com.sap.db.jdbc.Driver"); System.out.println("Create a connection..."); con = (com.sap.db.jdbc.trace.Connection) DriverManager .getConnection("jdbc:sap://<HANA数据库主机名>:30015",// , "system", "此处填入登录密码"); cs = (com.sap.db.jdbc.trace.CallableStatement) con.prepareCall("call I042416_two_par(NULL, NULL)"); cs.execute(); int index = 0; do { int rowCount = 0; com.sap.db.jdbc.trace.ResultSet rs = (com.sap.db.jdbc.trace.ResultSet)cs.getResultSet(); ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); while (rs != null && rs.next()) { for (int i = 1; i <= columnCount; i++) { System.out.print(rs.getString(i) + " "); if (i == columnCount) { System.out.println(); } } System.out.println("Current Result Set Index:" + index + " Row Count: " + rowCount++); } System.out.println("Result Set Index: " + index++); } while(cs.getMoreResults()); } console打印结果:数据能够成功通过JDBC从HANA数据库读取出来。 要获取更多Jerry的原创技术文章,请关注公众号"汪子熙"或者扫描下面二维码:

资源下载

更多资源
优质分享App

优质分享App

近一个月的开发和优化,本站点的第一个app全新上线。该app采用极致压缩,本体才4.36MB。系统里面做了大量数据访问、缓存优化。方便用户在手机上查看文章。后续会推出HarmonyOS的适配版本。

腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

用户登录
用户注册