### Spymemcached Full Configuration Example Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-data/solon-cache-spymemcached/README.md Provides a complete configuration example for Solon's cache with Spymemcached, including driver type, key header, default expiration, and server details. ```yaml #完整配置示例 solon.cache1: driverType: "memcached" keyHeader: "demo" #默认为 ${solon.app.name} ,可不配置 defSeconds: 30 #默认为 30,可不配置 server: "localhost:11211" user: "" #默认为空,可不配置 password: "" #默认为空,可不配置 #简配示例 solon.cache2: server: "localhost:11211" ``` -------------------------------- ### Solon Application Start Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-docs/solon-openapi2-knife4j/README.md Basic Solon application startup code. ```java public class App { public static void main(String[] args) { Solon.start(App.class, args); } } ``` -------------------------------- ### SolonMain Annotation Example Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-tool/solon-gradle-plugin/README.md Demonstrates how to use the @SolonMain annotation to mark the entry point of your Solon application, especially when multiple main methods exist. ```java package org.noear.solon.annotation; import java.lang.annotation.*; /** * Solon 主类(入口类) * *
{@code
 * @SolonMain
 * public class App{
 *     public static void main(String[] args){
 *         Solon.start(App.class, args);
 *     }
 * }
 * }
* * @author noear * @since 2.2 * */ @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SolonMain { } // 启动类上添加 @SolonMain public class App { public static void main(String[] args) { Solon.start(App.class, args); } } ``` -------------------------------- ### Solon-Flow WorkflowService Task Handling Source: https://github.com/opensolon/solon/blob/main/UPDATE_LOG.md Shows how to initialize and use WorkflowService for getting and posting tasks in Solon-flow. ```java WorkflowService workflow = WorkflowService.of(engine, WorkflowDriver.builder() .stateController(new ActorStateController()) .stateRepository(new InMemoryStateRepository()) .build()); //1. 取出任务 Task task = workflow.getTask(graph, context); //2. 提交任务 workflow.postTask(task.getNode(), TaskAction.FORWARD, context); ``` -------------------------------- ### Code-based Documentation Build Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-docs/solon-docs/README.md Define documentation configurations programmatically using Java. This approach allows for dynamic setup of API documentation groups, including global response types, security headers, and API base packages. ```java @Configuration public class DocConfig { @Inject OpenApiExtensionResolver openApiExtensionResolver; /** * 基于代码构建 */ @Managed("appApi") public DocDocket appApi() { //根据情况增加 "knife4j.setting" (可选) return new DocDocket() .vendorExtensions(openApiExtensionResolver.getExtension()) .groupName("app端接口") .schemes(Scheme.HTTP) .globalResult(Result.class) .globalResponseInData(true) .apis("com.swagger.demo.controller.app") .securityDefinitionInHeader("token"); } @Managed("adminApi") public DocDocket adminApi() { return new DocDocket() .groupName("admin端接口") .info(new ApiInfo().title("在线文档") .description("在线API文档") .termsOfService("https://gitee.com/noear/solon") .contact(new Contact().name("demo") .url("https://gitee.com/noear/solon") .email("demo@foxmail.com")) .version("1.0")) .schemes(Scheme.HTTP, Scheme.HTTPS) .globalResponseInData(true) .globalResult(Result.class) .apis("com.swagger.demo.controller.admin") .securityDefinitionInHeader("token"); } } ``` -------------------------------- ### Solon ScopeLocal Example Source: https://github.com/opensolon/solon/blob/main/UPDATE_LOG.md Demonstrates the usage of ScopeLocal for managing thread-local scoped variables in Solon. ```java public class Demo { static ScopeLocal LOCAL = ScopeLocal.newInstance(); public void test(){ LOCAL.with("test", ()->{ System.out.println(LOCAL.get()); }); } } ``` -------------------------------- ### Implement Server-Side Web Service Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-web/solon-web-webservices/README.md Define a Java class annotated with @WebService to expose a service. Ensure Solon is started. ```java public class ServerTest { public static void main(String[] args) { Solon.start(ServerTest.class, args); } @WebService(serviceName = "HelloService", targetNamespace = "http://demo.solon.io") public static class HelloServiceImpl { public String hello(String name) { return "hello " + name; } } } ``` -------------------------------- ### JavaScript WebSocket Stomp Client Setup Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-net/solon-net-stomp/src/test/resources/static/user1.html Initializes and configures the Stomp.js client for WebSocket communication. Includes connection headers, debug logging, reconnection settings, and event handlers for connection and disconnection. ```javascript var stompClient = null; function setConnected(connected) { document.getElementById('connect').disabled = connected; document.getElementById('disconnect').disabled = !connected; document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden'; $('#response').html(); } function connect() { //https://stomp-js.github.io/api-docs/latest/classes/Client.html var stompConfig = { connectHeaders: { 'connectedCallUri': 'www.baidu.com?test=123', 'disconnectedCallUri': 'www.baidu.com?test=321', "resource": "pc-web", "name": "web测试" }, disconnectHeaders: {}, debug: function (str) { console.log(str); }, //等于0则不自动重连 reconnectDelay: 5000, heartbeatIncoming: 0, heartbeatOutgoing: 0, stompVersions: { protocolVersions: function () { return []; }, supportedVersions: function(){ return []; } }, onConnect: function (frame) { setConnected(true); console.info('Connected', frame); stompClient.subscribe('/topic/todoTask1/\*', function (response) { showResponse(response.body); //response.ack({"message-id": response.headers["message-id"]}); }); stompClient.subscribe('/app/todoTask1/\*', function (response) { showResponse(response.body); //response.ack({"message-id": response.headers["message-id"]}); }); stompClient.subscribe('/user/app/errors', function (response) { showResponse(response.body); //response.ack({"message-id": response.headers["message-id"]}); }); var subscription = stompClient.subscribe('/topic/todoTask2/\*', function (response) { }); subscription.unsubscribe(); }, onWebSocketClose: function (frame) { console.error("onWebSocketClose", frame); setConnected(false); } } var wsurl = $('#wsurl').val(); console.error("stompConfig", stompConfig); stompClient = new StompJs.Client($.extend({ brokerURL: wsurl }, stompConfig)); stompClient.activate(); } function disconnect(frame) { if (stompClient != null) { stompClient.deactivate(); } stompClient = null; setConnected(false); } ``` -------------------------------- ### Advanced JSON Formatting Customization Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-serialization/solon-serialization-snack4/README.md Customize JSON serialization by adding converters for specific data types. This example shows how to format Date, LocalDate, and LocalDateTime objects before they are serialized. ```java public class DemoApp { public static void main(String[] args){ Solon.start(DemoApp.class, args, app->{ initMvcJsonCustom(); }); } /** * 初始化json定制(需要在插件运行前定制) */ private static void initMvcJsonCustom() { //通过转换器,做简单类型的定制 SnackRenderFactory.global .addConvertor(Date.class, s -> s.getTime()); SnackRenderFactory.global .addConvertor(LocalDate.class, s -> s.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); SnackRenderFactory.global .addConvertor(LocalDateTime.class, s -> s.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))); SnackRenderFactory.global.add } } ``` -------------------------------- ### Create Nami Client with Builder (Path and Upstream) Source: https://github.com/opensolon/solon/blob/main/__release/nami-bundle/README.md Configure a Nami client using the builder by providing the path and an upstream provider. This allows for more flexible endpoint configuration. ```java public class Demo3{ IComplexModelService service = Nami.builder() .encoder(SnackTypeEncoder.instance) .path("/ComplexModelService/") .upstream(()->"http://localhost:8080") .create(IComplexModelService.class); public void test(){ ComplexModel tmp = service.read(1); service.save(tmp); } } ``` -------------------------------- ### Configure SSL Keystore via Command Line Source: https://github.com/opensolon/solon/blob/main/__hatch/solon-server-nettyhttp/README.md Set SSL keystore and password configurations directly through Java system properties during application startup. This method is useful for overriding file configurations or for dynamic environments. ```shell java -Dserver.ssl.keyStore=/demo.jks -Dserver.ssl.keyPassword=demo -jar demo.jar ``` -------------------------------- ### Create Nami Client with Builder (URL) Source: https://github.com/opensolon/solon/blob/main/__release/nami-bundle/README.md Instantiate a Nami client using the builder pattern, specifying the full URL and encoder. This is useful for direct endpoint configuration. ```java public class Demo2{ IComplexModelService service = Nami.builder() .encoder(SnackTypeEncoder.instance) .url("http://localhost:8080/ComplexModelService/") .create(IComplexModelService.class); public void test(){ ComplexModel tmp = service.read(1); service.save(tmp); } } ``` -------------------------------- ### Programmatically Add Static File Mappings in Java Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-web/solon-web-staticfiles/README.md Add static file mappings using Java code within the Solon application startup. This allows for dynamic configuration of static resource locations. ```java public class App { public static void main(String[] args) { Solon.start(App.class, args, app -> { //添加静态目录映射 //1.添加扩展目录:${solon.extend}/static/ StaticMappings.add("/", new ExtendStaticRepository()); //2.添加本地绝对目录 StaticMappings.add("/", new FileStaticRepository("/data/sss/water/water_ext/")); //3.添加资源路径 StaticMappings.add("/", new ClassPathStaticRepository("user")); }); } } ``` -------------------------------- ### Configure Logging Appenders and Levels Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-logging/solon-logging/README.md Set up different logging appenders (console, cloud, file) and their respective levels (TRACE, INFO). ```yaml solon.logging.appender: console: level: TRACE enable: true cloud: level: INFO enable: true file: class: org.xxx.xxx.LogFileAppender level: INFO ``` -------------------------------- ### Build and Package with Solon Gradle Plugin Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-tool/solon-gradle-plugin/README.md Execute Gradle tasks to build and package your Solon application as a JAR or WAR file. ```bash gradle solonJar gradle solonWar ``` -------------------------------- ### Configuration-based Documentation Build Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-docs/solon-docs/README.md Configure documentation discovery, routes, and authentication using YAML. This method is useful for defining remote and local API documentation endpoints, including security settings and API information. ```yaml solon.docs: discover: #(发现配置,需要引入 solon cloud 发现服务插件),可选 enabled: true syncStatus: true #同步上下线状态 uriPattern: "swagger/v2?group={service}" #上游路径模式(要么带变量 {service},要么用统一固定值) contextPathPattern: "/{service}" basicAuth: admin: "123456" user: "654321" excludedServices: #排除服务名 - "user-api" includedServices: #包函服务名 - "order-api" routes: - id: appApi #(远程接口文档,即分布式服务或微服务),配置风格 groupName: "app端接口" upstream: target: "lb://app-api" contextPath: "/app" uri: "/xxx" - id: adminApi #(本地接口文档),配置风格 groupName: "admin端接口" globalResponseInData: true basicAuth: admin: "123456" user: "654321" apis: - basePackage: "com.swagger.demo.controller.admin" info: #可选 title: "在线文档" description: "在线API文档" termsOfService: "https://gitee.com/noear/solon" version: 1.0 contact: #可选 name: "demo" email: "demo@qq.com" license: #可选 name: "demo" url: "https://gitee.com/noear/solon/blob/master/LICENSE" ``` -------------------------------- ### Enable Documentation in Solon App Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-docs/solon-swagger2-knife4j/README.md Enables API documentation based on debug or file modes. This is the entry point for activating the documentation feature. ```java public class App { public static void main(String[] args) { Solon.start(App.class, args, app -> { //开发模式,或调试模式下才开启文档(或者自己定义配置控制)//或者一直开着(默认是开着的) app.enableDoc(app.cfg().isDebugMode() || app.cfg().isFilesMode()); }); } } ``` -------------------------------- ### Previous Packaging Configuration with Maven Assembly Plugin Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-tool/solon-maven-plugin/README.md This snippet demonstrates a previous packaging configuration using the maven-assembly-plugin. It includes settings for the compiler plugin and assembly plugin, specifying the main class and dependency packaging. ```xml org.apache.maven.plugins maven-compiler-plugin ${maven-compiler.version} -parameters ${java.version} ${java.version} UTF-8 org.apache.maven.plugins maven-assembly-plugin ${maven-assembly.version} ${project.artifactId} false jar-with-dependencies webapp.DemoApp make-assembly package single ``` -------------------------------- ### Create Client-Side Web Service (Manual Mode) Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-web/solon-web-webservices/README.md Use WebServiceHelper to create a client proxy for a remote web service. Requires the service interface definition. ```java public class ClientTest { public static void main(String[] args) { String wsAddress = "http://localhost:8080/ws/HelloService"; HelloService helloService = WebServiceHelper.createWebClient(wsAddress, HelloService.class); System.out.println("rst::" + helloService.hello("noear")); } @WebService(serviceName = "HelloService", targetNamespace = "http://demo.solon.io") public interface HelloService { @WebMethod String hello(String name); } } ``` -------------------------------- ### Configure Static File Mappings in YAML Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-web/solon-web-staticfiles/README.md Define static file serving rules in the application.yaml file. Use 'path' to specify the URL prefix and 'repository' to indicate the source location. ```yaml solon.mime.json: "application/json" solon.staticfiles: enabled: true cacheMaxAge: 6000 mappings: - path: "/img/" repository: "/data/sss/app/" #表示磁盘目录地址 - path: "/" repository: "classpath:user" #表示资源目录 - path: "/" repository: ":extend" #表示扩展静态静态 solon.extend: "!jt_ext" #!开头,表示如果没有扩展目录则自动创建 //用于支持 ExtendStaticRepository ``` -------------------------------- ### Dynamic Data Source Configuration Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-data/solon-data-dynamicds/README.md Configure multiple data sources using YAML. Key properties include 'type' for the data source implementation, 'strict' for error handling when a data source is not found, and 'default' for the default data source within a dynamic configuration. ```yaml demo.ds.db_user: type: "com.zaxxer.hikari.HikariDataSource" strict: true default: jdbcUrl: "xxx" #属性名要与 type 类的属性对上 username: "xxx" paasword: "xxx" driverClassName: "xx" db_user_2: jdbcUrl: "xxx" #属性名要与 type 类的属性对上 username: "xxx" paasword: "xxx" driverClassName: "xx" ``` -------------------------------- ### Configuration Reference for Solon Stop Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-web/solon-web-stop/README.md Configure the remote shutdown service using properties in your application.yml file. Key settings include enabling the feature, defining the command path, and specifying an IP whitelist. ```yaml solon.stop: enable: false #是否启用。默认为关闭 path: "/_run/stop/" #命令路径。默认为'/_run/stop/' whitelist: "127.0.0.1" #白名单,`*` 表示不限主机。默认为`127.0.0.1` ``` -------------------------------- ### Solon Docs Configuration Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-docs/solon-openapi2-knife4j/README.md Configuration for Solon's documentation features, including discovery and route definitions. ```yaml solon.docs: discover: #(发现配置,需要引入 solon cloud 发现服务插件),可选 enabled: true syncStatus: true #同步上下线状态 uriPattern: "swagger/v2?group={service}" #上游路径模式(要么带变量 {service},要么用统一固定值) basicAuth: admin: "123456" user: "654321" excludedServices: #排除服务名 - "user-api" includedServices: #包函服务名 - "order-api" routes: - id: appApi #(远程接口文档,即分布式服务或微服务),配置风格 groupName: "app端接口" upstream: target: "lb://app-api" contextPath: "/app" uri: "/xxx" - id: adminApi #(本地接口文档),配置风格 groupName: "admin端接口" globalResponseInData: true basicAuth: admin: "123456" user: "654321" apis: - basePackage: "com.swagger.demo.controller.admin" info: #可选 title: "在线文档" description: "在线API文档" termsOfService: "https://gitee.com/noear/solon" version: 1.0 contact: #可选 name: "demo" email: "demo@qq.com" license: #可选 name: "demo" url: "https://gitee.com/noear/solon/blob/master/LICENSE" ``` -------------------------------- ### Build Swagger2 Knife4j Docket from Configuration Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-docs/solon-swagger2-knife4j/README.md Constructs a DocDocket bean from YAML configuration for API documentation, setting global results and security definitions. ```java @Configuration public class DocConfig { /** * 基于配置构建 */ @Managed("adminApi") public DocDocket adminApi(@Inject("${swagger.adminApi}") DocDocket docket) { docket.globalResult(Result.class); docket.securityDefinitionInHeader("token"); return docket; } } ``` -------------------------------- ### Configure Solon Gradle Plugin in build.gradle Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-tool/solon-gradle-plugin/README.md Add the Solon Gradle plugin dependency and apply the plugin in your build.gradle file. Configure the main class for Solon JAR and WAR packaging. ```groovy buildscript { repositories { mavenLocal() mavenCentral() } dependencies { classpath 'org.noear:solon-gradle-plugin:x.y.z' } } // 使用 apply plugin: 'org.noear.solon' compileJava { // 这两个配置可以不添加了,插件中会默认自动添加 options.encoding = "UTF-8" options.compilerArgs << "-parameters" } // 配置启动文件名 solon { mainClass = "com.example.demo.App" } // 也可以针对 jar包和 war包指定不同的 mainClass solonJar{ mainClass = "com.example.demo.App" } // 使用 solonWar 需要添加 war 插件 solonWar{ mainClass = "com.example.demo.App" } ``` -------------------------------- ### Configure SSL Keystore in app.yml Source: https://github.com/opensolon/solon/blob/main/__hatch/solon-server-nettyhttp/README.md Specify the keystore file path and password in the application configuration file (app.yml) for SSL support. Supports .jks or .pfx formats. Can use file paths or classpath resources. ```yaml server.ssl: keyStore: "/demo.jks" #或者应用内资源文件 "classpath:demo.jks" keyPassword: "demo" ``` -------------------------------- ### Configure Solon Gradle Plugin in build.gradle.kts Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-tool/solon-gradle-plugin/README.md Add the Solon Gradle plugin dependency and apply the plugin in your build.gradle.kts file. Configure the main class for Solon JAR and WAR packaging using Kotlin DSL. ```kotlin buildscript { repositories { mavenLocal() maven { setUrl("https://maven.aliyun.com/repository/public") } mavenCentral() } dependencies { classpath("org.noear:solon-gradle-plugin:x.y.z") } } // 引用插件 apply(plugin = "org.noear.solon") // 统一配置 extensions.configure(org.noear.solon.gradle.dsl.SolonExtension::class.java) { mainClass.set("com.example.demo.App") } // 单独配置 tasks.withType { mainClass.set("com.example.demo.App") } tasks.withType { mainClass.set("com.example.demo.App") } ``` -------------------------------- ### Solon-Flow Graph Hardcoding and Modification Source: https://github.com/opensolon/solon/blob/main/UPDATE_LOG.md Illustrates how to define a graph using hardcoding and how to modify an existing graph in Solon-flow. ```java //硬编码 Graph graph = Graph.create("demo1", "示例", spec -> { spec.addStart("start").title("开始").linkAdd("01"); spec.addActivity("n1").task("@AaMetaProcessCom").linkAdd("end"); spec.addEnd("end").title("结束"); }); //修改 Graph graphNew = Graph.copy(graph, spec -> { spec.getNode("n1").linkRemove("end").linkAdd("n2"); //移掉 n1 连接;改为 n2 连接 spec.addActivity("n2").linkAdd("end"); }); ``` -------------------------------- ### New Solon Maven Plugin Configuration Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-tool/solon-maven-plugin/README.md This snippet shows the configuration for the new solon-maven-plugin. It preserves individual jar packages and avoids overwriting identical files. ```xml org.noear solon-maven-plugin ``` -------------------------------- ### Spymemcached Bean Definition with @Managed Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-data/solon-cache-spymemcached/README.md Demonstrates how to define Spymemcached cache beans using Solon's @Configuration and @Managed annotations. ```java //构建 bean @Configuration public class Config { @Managed(value = "cache1", typed = true) //默认 public CacheService cache1(@Inject("${solon.cache1}") MemCacheService cache){ return cache; } @Managed("cache2") public CacheService cache2(@Inject("${solon.cache2}") CacheServiceSupplier supplier){ //CacheServiceSupplier 可自动识别类型 return supplier.get(); } } ``` -------------------------------- ### Solon-AI McpServerTool with CompletableFuture Source: https://github.com/opensolon/solon/blob/main/UPDATE_LOG.md Showcases a Solon-AI MCP server endpoint using STREAMABLE_STATELESS channel and CompletableFuture for asynchronous operations. ```java @McpServerEndpoint(channel = McpChannel.STREAMABLE_STATELESS, mcpEndpoint = "/mcp1") public class McpServerTool { @ToolMapping(description = "查询天气预报", returnDirect = true) public CompletableFuture getWeather(@Param(description = "城市位置") String location) { return CompletableFuture.completedFuture("晴,14度"); } } ``` -------------------------------- ### Configure JVM for Serialization Permissions on JDK 17 Source: https://github.com/opensolon/solon/blob/main/__test/README.md Use this JVM parameter on JDK 17 or later if serialization permission issues arise. ```shell java --add-opens java.base/java.lang=ALL-UNNAMED -jar xxx.jar ``` -------------------------------- ### Configuring Data Source Beans Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-data/solon-data-dynamicds/README.md Define a DataSource bean for a specific dynamic data source configuration using Solon's dependency injection and managed annotations. ```java @Configuration public class Config { @Managed("db_user") public DataSource dsUser(@Inject("$demo.ds.db_user}") DynamicDataSource dataSource) { return dataSource; } } ``` -------------------------------- ### Build Swagger2 Knife4j Docket via Code (App API) Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-docs/solon-swagger2-knife4j/README.md Programmatically builds a DocDocket for the app API, including vendor extensions, group name, schemes, and security definitions. ```java @Configuration public class DocConfig { @Inject OpenApiExtensionResolver openApiExtensionResolver; /** * 基于代码构建 */ @Managed("appApi") public DocDocket appApi() { //根据情况增加 "knife4j.setting" (可选) return new DocDocket() .vendorExtensions(openApiExtensionResolver.getExtension()) .groupName("app端接口") .schemes(Scheme.HTTP) .globalResult(Result.class) .globalResponseInData(true) .apis("com.swagger.demo.controller.app") .securityDefinitionInHeader("token"); } @Managed("adminApi") public DocDocket adminApi() { return new DocDocket() .groupName("admin端接口") .info(new ApiInfo().title("在线文档") .description("在线API文档") .termsOfService("https://gitee.com/noear/solon") .contact(new Contact().name("demo") .url("https://gitee.com/noear/solon") .email("demo@foxmail.com")) .version("1.0")) .schemes(Scheme.HTTP, Scheme.HTTPS) .globalResponseInData(true) .globalResult(Result.class) .apis("com.swagger.demo.controller.admin") .securityDefinitionInHeader("token"); } } ``` -------------------------------- ### Using Solon Cache Annotation in Controller Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-data/solon-cache-spymemcached/README.md Shows how to apply the @Cache annotation to a method in a Solon controller for automatic caching. ```java //应用 @Controller public class DemoController { @Cache public String hello(String name) { return String.format("Hello {0}!", name); } } ``` -------------------------------- ### Configure JVM for Serialization Permissions on JDK 9-16 Source: https://github.com/opensolon/solon/blob/main/__test/README.md Use this JVM parameter on JDK 9 through JDK 16 if serialization permission issues arise. ```shell java --illegal-access=permit -jar xxx.jar ``` -------------------------------- ### Configure Solon Serialization JSON Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-serialization/solon-serialization-jackson3/README.md Configure Solon's JSON serialization settings using YAML. This includes date formatting, time zone, and how various data types (long, bool, null) are represented. ```yaml solon.serialization.json: dateAsFormat: 'yyyy-MM-dd HH:mm:ss' #配置日期格式(默认输出为时间戳) dateAsTimeZone: 'GMT+8' #配置时区 dateAsTicks: false #将date转为毫秒数(和 dateAsFormat 二选一) longAsString: true #将long型转为字符串输出 (默认为false) boolAsInt: false #将bool型转为字符串输出 (默认为false) nullStringAsEmpty: false nullBoolAsFalse: false nullNumberAsZero: false nullArrayAsEmpty: false nullAsWriteable: false #输出所有null值 ``` -------------------------------- ### Declare HTTP RPC Interface Source: https://github.com/opensolon/solon/blob/main/__release/nami-bundle/README.md Define the interface for your HTTP RPC service. This interface will be used by Nami to generate a client proxy. ```java public interface IComplexModelService { //持久化 void save(ComplexModel model); //读取 ComplexModel read(Integer modelId); } ``` -------------------------------- ### Configure Swagger2 Knife4j via YAML Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-docs/solon-swagger2-knife4j/README.md Defines Swagger2 Knife4j configurations using YAML for API documentation, including group name, authentication, and API base packages. ```yaml swagger.adminApi: groupName: "admin端接口" globalResponseInData: true basicAuth: admin: "123456" user: "654321" apis: - basePackage: "com.swagger.demo.controller.admin" info: #可选 title: "在线文档" description: "在线API文档" termsOfService: "https://gitee.com/noear/solon" version: 1.0 contact: #可选 name: "demo" email: "demo@qq.com" license: #可选 name: "demo" url: "https://gitee.com/noear/solon/blob/master/LICENSE" ``` -------------------------------- ### Configure Specific Logger Levels Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-logging/solon-logging/README.md Define logging levels for specific packages like Apache ZooKeeper and Eclipse Jetty. ```yaml solon.logging.logger: "org.apache.zookeeper.*": ``` ```yaml level: "WARN" "org.eclipse.jetty.*": ``` ```yaml level: "WARN" ``` -------------------------------- ### Configure Web Service Path Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-web/solon-web-webservices/README.md Specify a custom path segment for web services in the application configuration. ```yaml server.webservices.path: "/ws/" #默认为 ws ``` -------------------------------- ### Inject Nami Client with @NamiClient Source: https://github.com/opensolon/solon/blob/main/__release/nami-bundle/README.md Use the @NamiClient annotation to inject an instance of your service interface. This requires a LoadBalance component to be configured for the specified name. ```java @Managed public class Demo1{ @NamiClient(name="test", path="/ComplexModelService/") IComplexModelService service; public void test(){ ComplexModel tmp = service.read(1); service.save(tmp); } } ``` ```java //构建一个test负载均衡组件 @Managed("test") public class TestUpstream implements LoadBalance { @Override public String getServer() { return "http://localhost:8080"; } } ``` ```java //更改默认配置器的代理,将编码器换掉 NamiConfigurationDefault.proxy = (c,b)->b.encoder(SnackTypeEncoder.instance); ``` -------------------------------- ### Inject Client-Side Web Service (Container Mode) Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-web/solon-web-webservices/README.md Use @WebServiceReference annotation to inject a web service client into a Solon controller. Requires the service interface definition. ```java //定义测试控制器 @Controller public static class DemoController { @WebServiceReference("http://localhost:8080/ws/HelloService") private HelloService helloService; @Mapping("/test") public String test() { return helloService.hello("noear"); } } //配置 WebService 接口 @WebService(serviceName = "HelloService", targetNamespace = "http://demo.solon.io") public interface HelloService { @WebMethod String hello(String name); } //启动 Solon public class ClientTest { public static void main(String[] args) { Solon.start(ClientTest2.class, args); } } ``` -------------------------------- ### Add Solon Web Services Dependency Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-web/solon-web-webservices/README.md Include the solon-web-webservices artifact in your project's dependencies. ```xml org.noear solon-web-webservices ``` -------------------------------- ### Configure Solon Banner Plugin Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-config/solon-config-banner/README.md Customize the banner's behavior by setting these properties in your Solon application configuration. The banner is enabled by default. ```yaml #By default the banner is true solon.banner.enable: true #Where to print the banner , values console/log/both solon.banner.mode: "console" #Path to banner resource file solon.banner.path: "banner.txt" ``` -------------------------------- ### JavaScript WebSocket Connection and Subscription Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-net/solon-net-stomp/src/test/resources/static/user2.html Establishes a WebSocket connection using StompJS, subscribes to various topics including user-specific and application-wide topics, and handles WebSocket close events. ```javascript var stompClient = null; function setConnected(connected) { document.getElementById('connect').disabled = connected; document.getElementById('disconnect').disabled = !connected; document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden'; $('#response').html(); } function connect() { //https://stomp-js.github.io/api-docs/latest/classes/Client.html var stompConfig = { connectHeaders: { 'connectedCallUri': 'www.baidu.com?test=123', 'disconnectedCallUri': 'www.baidu.com?test=321', "resource": "pc-web", "name": "web测试" }, disconnectHeaders: {}, debug: function (str) { console.log(str); }, //等于0则不自动重连 reconnectDelay: 5000, heartbeatIncoming: 0, heartbeatOutgoing: 0, stompVersions: { protocolVersions: function () { return []; }, supportedVersions: function(){ return []; } }, onConnect: function (frame) { setConnected(true); console.info('Connected', frame); stompClient.subscribe('/topic/todoTask1/\*', function (response) { showResponse(response.body); }); stompClient.subscribe('/app/todoTask1/\*', function (response) { showResponse(response.body); //response.ack({"message-id": response.headers["message-id"]}); }); stompClient.subscribe('/user/app/errors', function (response) { showResponse(response.body); }); var subscription = stompClient.subscribe('/topic/todoTask2/\*', function (response) { }); subscription.unsubscribe(); }, onWebSocketClose: function (frame) { console.error("onWebSocketClose", frame); setConnected(false); } } var wsurl = $('#wsurl').val(); console.error("stompConfig", stompConfig); stompClient = new StompJs.Client($.extend({ brokerURL: wsurl }, stompConfig)); stompClient.activate(); } function disconnect(frame) { if (stompClient != null) { stompClient.deactivate(); } stompClient = null; setConnected(false); } ``` -------------------------------- ### Dynamic Data Source Switching with Annotations Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-data/solon-data-dynamicds/README.md Use the @DynamicDs annotation to specify which data source to use for a method. The annotation can take a data source name as an argument, or if left empty, it uses the default data source within the configured dynamic data source. ```java @ProxyComponent public class UserService{ @Db("db_user") UserMapper userMapper; @DynamicDs //使用 db_user 动态源内的 默认源 public void addUser(){ userMapper.inserUser(); } @DynamicDs("db_user_1") //使用 db_user 动态源内的 db_user_1 源 public void getUserList(){ userMapper.selectUserList(); } public void getUserList2(){ DynamicDsHolder.set("db_user_2"); //使用 db_user 动态源内的 db_user_2 源 userMapper.selectUserList(); } } ``` -------------------------------- ### Maven Dependency for Solon Web Stop Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-web/solon-web-stop/README.md Add this dependency to your Maven project to include the Solon web stop extension. ```xml org.noear solon-web-stop ``` -------------------------------- ### JavaScript Stomp.js Message Sending Functions Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-net/solon-net-stomp/src/test/resources/static/user1.html Provides functions to publish messages to different Stomp destinations. Includes options for message body, persistence, and acknowledgments. ```javascript function send() { if($('#message').val()){ stompClient.publish({ destination: "/topic/todoTask1/open", body: $('#message').val(), headers: {"openPersistence": "true", "openAck": "true"} }); } } function send2() { if($('#message').val()){ stompClient.publish({ destination: "/app/todoTask1/user", body: $('#message').val(), headers: {"openPersistence": "true", "openAck": "true", "user": "test001"} }); } } function send3() { if($('#message').val()){ stompClient.publish({ destination: "/app/todoTask1/self", body: $('#message').val(), headers: {"openPersistence": "true", "openAck": "true"} }); } } function send4() { if($('#message').val()){ stompClient.publish({ destination: "/app/todoTask1/error", body: $('#message').val(), headers: {"openPersistence": "true", "openAck": "true"} }); } } ``` -------------------------------- ### Advanced JSON Formatting Customization with Snack3 Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-serialization/solon-serialization-snack3/README.md Customize JSON serialization by adding convertors for specific data types like Date, LocalDate, and LocalDateTime using SnackRenderFactory. This should be done before the plugin runs. ```java public class DemoApp { public static void main(String[] args){ Solon.start(DemoApp.class, args, app->{ initMvcJsonCustom(); }); } /** * 初始化json定制(需要在插件运行前定制) */ private static void initMvcJsonCustom() { //通过转换器,做简单类型的定制 SnackRenderFactory.global .addConvertor(Date.class, s -> s.getTime()); SnackRenderFactory.global .addConvertor(LocalDate.class, s -> s.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); SnackRenderFactory.global .addConvertor(LocalDateTime.class, s -> s.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))) SnackRenderFactory.global.add } } ``` -------------------------------- ### Add Solon Banner Dependency Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-config/solon-config-banner/README.md Include this Maven dependency in your project to use the Solon Banner plugin. ```xml org.noear solon-banner ``` -------------------------------- ### Solon-Flow FlowContext LastNodeId Usage Source: https://github.com/opensolon/solon/blob/main/UPDATE_LOG.md Demonstrates using FlowContext.lastNodeId() for interrupting and resuming flow execution in Solon-flow. ```java flowEngine.eval(graph, context.lastNodeId(), context); //...(从上一个节点开始执行) flowEngine.eval(graph, context.lastNodeId(), context); ``` -------------------------------- ### Beetl Template Rendering with Error Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-view/solon-view-beetl/src/test/resources/templates/beetl_out_error.htm This snippet shows a Beetl template that attempts to render a non-existent object property, causing an error. It highlights the template's structure before and after the problematic rendering. ```html ${title} beetl模板引擎先渲染,再写入请求响应。 **之前** <% // entity.name 这是一个不存在的对象、属性,用于报错抛出 %> ${entity.name} **之后** ``` -------------------------------- ### Remotely Shutting Down Service with Curl Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-web/solon-web-stop/README.md Use the curl command to trigger the remote shutdown of the service. This is primarily for operational assistance. ```shell curl http://127.0.0.1/_run/stop/ ``` -------------------------------- ### JavaScript Stomp.js Response Handling Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-net/solon-net-stomp/src/test/resources/static/user1.html Appends received messages to the response area and scrolls to the bottom to show the latest message. ```javascript function showResponse(message) { var response = $('#response'); response.append(message + "
"); var div = document.getElementById('response'); div.scrollTop = div.scrollHeight; } ``` -------------------------------- ### Advanced Fastjson Customization with Converters and Encoders Source: https://github.com/opensolon/solon/blob/main/solon-projects/solon-serialization/solon-serialization-fastjson/README.md Customize Fastjson serialization for specific data types like Date and LocalDate using global converters and encoders. This allows for fine-grained control over how these types are represented in JSON. ```java public class DemoApp { public static void main(String[] args){ Solon.start(DemoApp.class, args, app->{ initMvcJsonCustom(); }); } /** * 初始化json定制(需要在插件运行前定制) * */ private static void initMvcJsonCustom(){ //通过转换器,做简单类型的定制 FastjsonRenderFactory.global.addConvertor(Date.class, (JsonLongConverter) source -> source.getTime()); FastjsonRenderFactory.global.addConvertor(LocalDate.class, (JsonStringConverter) source -> source.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); //通过编码器,做复杂类型的原生定制(基于框架原生接口) FastjsonRenderFactory.global.addEncoder(Date.class, (ser, obj, o1, type, i) -> { SerializeWriter out = ser.getWriter(); out.writeLong(((Date)obj).getTime()); }); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.