Browse Source

[Java] Update Solon Version To 3.0.3 (#9401)

* Update Solon Version To 2.9.1

* Update Solon Version To 2.9.1

* Update Solon Jdk To 21

* Update Solon Jdk To 21

* Update Solon Jdk To 21

* Update Solon Jdk To 21

* Update Solon Jdk To 21

* Update Solon Version To 2.9.2

* Add Solon-Virtual

* Remove solon-virtual

* Update Solon Version To 3.0.2

* Add Solon-Vertx

* Tweak description

* Tweak the dockerfile

* Tweak the dockerfile

* Tweak config

* Tweak dockefile name

* Add FilterImpl

* Add FilterImpl

* The json plugin is changed to jackson

* Update Solon Jdk To 23

* Update Solon-Vertx Jdk To 23

* Solon-vertx is restored to jdk 21

* Solon is restored to jdk 21

* Solon-vertx adjusts the Date output format

* Solon is restored to jdk 21

* Remove solon-vertx

* [Java] Update Solon Version To 3.0.3
西东 8 months ago
parent
commit
8c007fa705

+ 48 - 2
frameworks/Java/solon/pom.xml

@@ -5,7 +5,7 @@
     <parent>
         <groupId>org.noear</groupId>
         <artifactId>solon-parent</artifactId>
-        <version>3.0.2</version>
+        <version>3.0.3</version>
     </parent>
 
     <groupId>hello</groupId>
@@ -15,24 +15,70 @@
 
     <properties>
         <java.version>21</java.version>
+        <jstachio.version>1.3.6</jstachio.version>
     </properties>
 
     <dependencies>
         <dependency>
             <groupId>org.noear</groupId>
-            <artifactId>solon-boot-smarthttp</artifactId>
+            <artifactId>solon-web</artifactId>
         </dependency>
 
         <dependency>
             <groupId>org.noear</groupId>
             <artifactId>solon-serialization-jackson</artifactId>
         </dependency>
+
+        <dependency>
+            <groupId>org.noear</groupId>
+            <artifactId>solon-data-sqlutils</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>io.jstach</groupId>
+            <artifactId>jstachio</artifactId>
+            <version>${jstachio.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.jstach</groupId>
+            <artifactId>jstachio-apt</artifactId>
+            <version>${jstachio.version}</version>
+            <scope>provided</scope>
+            <optional>true</optional>
+        </dependency>
+
+        <dependency>
+            <groupId>com.zaxxer</groupId>
+            <artifactId>HikariCP</artifactId>
+            <version>6.0.0</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.postgresql</groupId>
+            <artifactId>postgresql</artifactId>
+            <version>42.7.4</version>
+        </dependency>
     </dependencies>
 
     <build>
         <finalName>${project.artifactId}</finalName>
 
         <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>io.jstach</groupId>
+                            <artifactId>jstachio-apt</artifactId>
+                            <version>${jstachio.version}</version>
+                        </path>
+                    </annotationProcessorPaths>
+                </configuration>
+            </plugin>
+
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-assembly-plugin</artifactId>

+ 0 - 4
frameworks/Java/solon/src/main/java/hello/Main.java

@@ -2,10 +2,6 @@ package hello;
 
 import org.noear.solon.Solon;
 
-/**
- * @author pmg1991
- * @version V1.0
- */
 public class Main {
 	public static void main(String[] args) {
 		Solon.start(Main.class, args);

+ 17 - 0
frameworks/Java/solon/src/main/java/hello/Utils.java

@@ -0,0 +1,17 @@
+package hello;
+
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.stream.IntStream;
+
+abstract public class Utils {
+	private static final int MIN_WORLD_NUMBER = 1;
+	private static final int MAX_WORLD_NUMBER_PLUS_ONE = 10_001;
+
+	public static int randomWorldNumber() {
+		return ThreadLocalRandom.current().nextInt(MIN_WORLD_NUMBER, MAX_WORLD_NUMBER_PLUS_ONE);
+	}
+
+	public static IntStream randomWorldNumbers() {
+		return ThreadLocalRandom.current().ints(MIN_WORLD_NUMBER, MAX_WORLD_NUMBER_PLUS_ONE).distinct();
+	}
+}

+ 0 - 25
frameworks/Java/solon/src/main/java/hello/controller/HelloController.java

@@ -1,25 +0,0 @@
-package hello.controller;
-
-import org.noear.solon.annotation.Controller;
-import org.noear.solon.annotation.Get;
-import org.noear.solon.annotation.Mapping;
-import hello.model.Message;
-
-/**
- * @author noear
- * @version V1.0
- */
-@Controller
-public class HelloController {
-    @Get
-    @Mapping("plaintext")
-    public String plaintext() {
-        return "Hello, World!";
-    }
-
-    @Get
-    @Mapping("json")
-    public Message json() {
-        return new Message("Hello, World!");
-    }
-}

+ 16 - 0
frameworks/Java/solon/src/main/java/hello/model/Fortune.java

@@ -0,0 +1,16 @@
+package hello.model;
+
+public final class Fortune implements Comparable<Fortune>{
+	public final int id;
+	public final String message;
+
+	public Fortune(int id, String message) {
+		this.id = id;
+		this.message = message;
+	}
+
+	@Override
+	public int compareTo(final Fortune other) {
+		return message.compareTo(other.message);
+	}
+}

+ 0 - 21
frameworks/Java/solon/src/main/java/hello/model/Message.java

@@ -1,21 +0,0 @@
-package hello.model;
-
-/**
- * @author pmg1991
- * @version V1.0
- */
-public class Message {
-    private String message;
-
-    public Message(String message) {
-        this.message = message;
-    }
-
-    public String getMessage() {
-        return message;
-    }
-
-    public void setMessage(String message) {
-        this.message = message;
-    }
-}

+ 12 - 0
frameworks/Java/solon/src/main/java/hello/model/World.java

@@ -0,0 +1,12 @@
+package hello.model;
+
+
+public final class World {
+	public int id;
+	public int randomNumber;
+	public World(int id, int randomNumber) {
+		this.id = id;
+		this.randomNumber = randomNumber;
+	}
+
+}

+ 15 - 0
frameworks/Java/solon/src/main/java/hello/repository/DbRepository.java

@@ -0,0 +1,15 @@
+package hello.repository;
+
+import hello.model.Fortune;
+import hello.model.World;
+
+import java.util.List;
+
+public interface DbRepository {
+
+    World getWorld(int id) throws Exception;
+
+    void updateWorlds(List<World> worlds) throws Exception;
+
+    List<Fortune> fortunes() throws Exception;
+}

+ 46 - 0
frameworks/Java/solon/src/main/java/hello/repository/JdbcDbRepository.java

@@ -0,0 +1,46 @@
+package hello.repository;
+
+import hello.model.Fortune;
+import hello.model.World;
+import org.noear.solon.annotation.Component;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.data.sql.SqlUtils;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+public class JdbcDbRepository implements DbRepository {
+    @Inject
+    SqlUtils sqlUtils;
+
+    @Override
+    public World getWorld(int id) {
+        try {
+            return sqlUtils.sql("SELECT id, randomnumber FROM world WHERE id = ?", id)
+                    .queryRow()
+                    .toBean(World.class, (r, t) -> new World((int) r.getObject(1), (int) r.getObject(2)));
+        } catch (Exception e) {
+            return null;
+        }
+    }
+
+    @Override
+    public void updateWorlds(List<World> worlds) throws SQLException {
+        List<Object[]> values = new ArrayList<>();
+        for (World w : worlds) {
+            values.add(new Object[]{w.randomNumber, w.id});
+        }
+
+        sqlUtils.sql("UPDATE world SET randomnumber = ? WHERE id = ?")
+                .updateBatch(values);
+    }
+
+    @Override
+    public List<Fortune> fortunes() throws SQLException {
+        return sqlUtils.sql("SELECT id, message FROM fortune")
+                .queryRowList()
+                .toBeanList(Fortune.class, (r, t) -> new Fortune((int) r.getObject(1), (String) r.getObject(2)));
+    }
+}

+ 61 - 0
frameworks/Java/solon/src/main/java/hello/web/DbHandler.java

@@ -0,0 +1,61 @@
+package hello.web;
+
+import hello.Utils;
+import hello.model.Fortune;
+import hello.model.World;
+import hello.repository.JdbcDbRepository;
+import org.noear.solon.annotation.Component;
+import org.noear.solon.annotation.Inject;
+import org.noear.solon.core.handle.Context;
+
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+@Component
+public class DbHandler {
+    @Inject
+    JdbcDbRepository dbRepository;
+
+    public void db(Context ctx) throws Throwable {
+        ctx.render(dbRepository.getWorld(Utils.randomWorldNumber()));
+    }
+
+    public void queries(Context ctx) throws Throwable {
+        int queries = ctx.paramAsInt("queries", 0);
+
+        World[] worlds = Utils.randomWorldNumbers()
+                .mapToObj(dbRepository::getWorld).limit(queries)
+                .toArray(World[]::new);
+
+        ctx.render(worlds);
+    }
+
+    public void updates(Context ctx) throws Throwable {
+        int queries = ctx.paramAsInt("queries", 0);
+
+        List<World> worlds = Utils.randomWorldNumbers()
+                .mapToObj(id -> {
+                    World world = dbRepository.getWorld(id);
+                    int randomNumber;
+                    do {
+                        randomNumber = Utils.randomWorldNumber();
+                    } while (randomNumber == world.randomNumber);
+                    world.randomNumber = randomNumber;
+                    return world;
+                }).limit(queries)
+                .sorted(Comparator.comparingInt(w -> w.id))
+                .toList();
+        dbRepository.updateWorlds(worlds);
+
+        ctx.render(worlds);
+    }
+
+    public void fortunes(Context ctx) throws Throwable {
+        List<Fortune> fortunes = dbRepository.fortunes();
+        fortunes.add(new Fortune(0, "Additional fortune added at request time."));
+        Collections.sort(fortunes);
+
+        ctx.render(new Fortunes(fortunes));
+    }
+}

+ 10 - 0
frameworks/Java/solon/src/main/java/hello/web/Fortunes.java

@@ -0,0 +1,10 @@
+package hello.web;
+
+import hello.model.Fortune;
+import io.jstach.jstache.JStache;
+
+import java.util.List;
+
+@JStache(path = "fortunes.mustache")
+public record Fortunes(List<Fortune> fortunes) {
+}

+ 27 - 0
frameworks/Java/solon/src/main/java/hello/web/JsonHandler.java

@@ -0,0 +1,27 @@
+package hello.web;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import org.noear.solon.annotation.Component;
+import org.noear.solon.boot.web.MimeType;
+import org.noear.solon.core.handle.Context;
+import org.noear.solon.core.handle.Handler;
+
+import java.util.Map;
+
+@Component
+public class JsonHandler implements Handler {
+    private final ObjectWriter writer;
+
+    public JsonHandler() {
+        this.writer = new ObjectMapper().writerFor(Map.class);
+    }
+
+    @Override
+    public void handle(Context ctx) throws Throwable {
+        byte[] body = this.writer.writeValueAsBytes(Map.of("message", "Hello, world!"));
+        ctx.contentLength(body.length);
+        ctx.contentType(MimeType.APPLICATION_JSON_VALUE);
+        ctx.output(body);
+    }
+}

+ 25 - 0
frameworks/Java/solon/src/main/java/hello/web/TextHandler.java

@@ -0,0 +1,25 @@
+package hello.web;
+
+import org.noear.solon.annotation.Component;
+import org.noear.solon.boot.web.MimeType;
+import org.noear.solon.core.handle.Context;
+import org.noear.solon.core.handle.Handler;
+
+import java.nio.charset.StandardCharsets;
+
+@Component
+public class TextHandler implements Handler {
+    private static final byte[] TEXT_BODY = "Hello, World!".getBytes(StandardCharsets.UTF_8);
+
+    private static final String TEXT_BODY_LENGTH = String.valueOf(TEXT_BODY.length);
+    private static final String CONTENT_LENGTH = "Content-Length";
+    private static final String CONTENT_TYPE = "Content-Type";
+
+    @Override
+    public void handle(Context ctx) throws Throwable {
+        ctx.headerSet(CONTENT_LENGTH, TEXT_BODY_LENGTH);
+        ctx.headerSet(CONTENT_TYPE, MimeType.TEXT_PLAIN_VALUE);
+        ctx.output("Hello, World!".getBytes());
+    }
+}
+

+ 29 - 0
frameworks/Java/solon/src/main/java/hello/web/WebmvcRouter.java

@@ -0,0 +1,29 @@
+package hello.web;
+
+import org.noear.solon.SolonApp;
+import org.noear.solon.annotation.Bean;
+import org.noear.solon.annotation.Configuration;
+
+@Configuration
+public class WebmvcRouter {
+    @Bean
+    public void initRouter(SolonApp app,
+                           DbHandler dbHandler,
+                           JsonHandler jsonHandler,
+                           TextHandler textHandler) {
+        app.handler().prev(ctx -> {
+            ctx.setHandled(true);
+            ctx.headerSet("Server", "Solon");
+
+            switch (ctx.path()) {
+                case "/plaintext" -> textHandler.handle(ctx);
+                case "/json" -> jsonHandler.handle(ctx);
+                case "/db" -> dbHandler.db(ctx);
+                case "/queries" -> dbHandler.queries(ctx);
+                case "/updates" -> dbHandler.updates(ctx);
+                case "/fortunes" -> dbHandler.fortunes(ctx);
+                default -> ctx.status(404);
+            }
+        });
+    }
+}

+ 0 - 1
frameworks/Java/solon/src/main/resources/app.properties

@@ -1 +0,0 @@
-server.http.ioBound=false

+ 23 - 0
frameworks/Java/solon/src/main/resources/app.yml

@@ -0,0 +1,23 @@
+database:
+  name: hello_world
+  host: tfb-database
+  port: 5432
+  username: benchmarkdbuser
+  password: benchmarkdbpass
+
+server.http:
+  ioBound: false
+
+solon.threads:
+  virtual:
+    enabled: true
+
+solon.dataSources:
+  test!:
+    class: "com.zaxxer.hikari.HikariDataSource"
+    driverClassName: "org.postgresql.Driver"
+    url: jdbc:postgresql://${database.host}:${database.port}/${database.name}?loggerLevel=OFF&disableColumnSanitiser=true&assumeMinServerVersion=16&sslmode=disable
+    username: ${database.username}
+    password: ${database.password}
+    hikari:
+      maximum-pool-size: 256

+ 20 - 0
frameworks/Java/solon/src/main/resources/fortunes.mustache

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Fortunes</title>
+</head>
+<body>
+<table>
+  <tr>
+    <th>id</th>
+    <th>message</th>
+  </tr>
+  {{#fortunes}}
+  <tr>
+    <td>{{id}}</td>
+    <td>{{message}}</td>
+  </tr>
+  {{/fortunes}}
+</table>
+</body>
+</html>