MOD:更换为Vertx框架 提高效率
This commit is contained in:
@@ -2,16 +2,11 @@
|
|||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
|
||||||
<groupId>org.springframework.boot</groupId>
|
|
||||||
<artifactId>spring-boot-starter-parent</artifactId>
|
|
||||||
<version>3.1.0</version>
|
|
||||||
<relativePath/> <!-- lookup parent from repository -->
|
|
||||||
</parent>
|
|
||||||
<groupId>com.leosam.tvbox</groupId>
|
<groupId>com.leosam.tvbox</groupId>
|
||||||
<artifactId>tvbox-mv</artifactId>
|
<artifactId>tvbox-mv</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<name>tvbox-mv</name>
|
<name>tvbox-mv</name>
|
||||||
|
|
||||||
<description>Demo project for Spring Boot</description>
|
<description>Demo project for Spring Boot</description>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>17</java.version>
|
<java.version>17</java.version>
|
||||||
@@ -20,46 +15,164 @@
|
|||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<maven.resources.overwrite>true</maven.resources.overwrite>
|
<maven.resources.overwrite>true</maven.resources.overwrite>
|
||||||
|
|
||||||
|
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
|
||||||
|
<maven-shade-plugin.version>3.2.4</maven-shade-plugin.version>
|
||||||
|
<maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
|
||||||
|
<exec-maven-plugin.version>3.0.0</exec-maven-plugin.version>
|
||||||
|
|
||||||
|
<vertx.version>4.4.3</vertx.version>
|
||||||
|
<junit-jupiter.version>5.9.2</junit-jupiter.version>
|
||||||
|
|
||||||
|
<main.verticle>com.leosam.tvbox.mv.MainVerticle</main.verticle>
|
||||||
|
<launcher.class>io.vertx.core.Launcher</launcher.class>
|
||||||
|
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>io.vertx</groupId>
|
||||||
<artifactId>spring-boot-starter-web</artifactId>
|
<artifactId>vertx-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<groupId>io.vertx</groupId>
|
||||||
<artifactId>spring-boot-starter-test</artifactId>
|
<artifactId>vertx-junit5</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<version>${junit-jupiter.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
|
<version>${junit-jupiter.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>slf4j-api</artifactId>
|
||||||
|
<version>2.0.5</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ch.qos.logback</groupId>
|
||||||
|
<artifactId>logback-classic</artifactId>
|
||||||
|
<version>1.4.7</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.codehaus.janino</groupId>
|
||||||
|
<artifactId>janino</artifactId>
|
||||||
|
<version>3.1.9</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.fusesource.jansi</groupId>
|
||||||
|
<artifactId>jansi</artifactId>
|
||||||
|
<version>2.4.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<!--Lucene Core-->
|
<!--Lucene Core-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.lucene</groupId>
|
<groupId>org.apache.lucene</groupId>
|
||||||
<artifactId>lucene-core</artifactId>
|
<artifactId>lucene-core</artifactId>
|
||||||
<version>8.5.2</version>
|
<version>9.5.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!--Lucene Queryparser-->
|
<!--Lucene Queryparser-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.lucene</groupId>
|
<groupId>org.apache.lucene</groupId>
|
||||||
<artifactId>lucene-queryparser</artifactId>
|
<artifactId>lucene-queryparser</artifactId>
|
||||||
<version>8.5.2</version>
|
<version>9.5.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- Lucene提供的中文分词器模块,lucene-analyzers-smartcn:Lucene 的中文分词器 SmartChineseAnalyzer -->
|
<!-- Lucene提供的中文分词器模块,lucene-analyzers-smartcn:Lucene 的中文分词器 SmartChineseAnalyzer -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.lucene</groupId>
|
<groupId>org.apache.lucene</groupId>
|
||||||
<artifactId>lucene-analyzers-smartcn</artifactId>
|
<artifactId>lucene-analyzers-smartcn</artifactId>
|
||||||
<version>8.5.2</version>
|
<version>8.11.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.vertx</groupId>
|
||||||
|
<artifactId>vertx-stack-depchain</artifactId>
|
||||||
|
<version>${vertx.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.springframework.boot</groupId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
<version>${maven-compiler-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<release>17</release>
|
||||||
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>${maven-shade-plugin.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
<filters>
|
||||||
|
<filter>
|
||||||
|
<artifact>*:*</artifact>
|
||||||
|
<excludes>
|
||||||
|
<exclude>META-INF/*.SF</exclude>
|
||||||
|
<exclude>META-INF/*.DSA</exclude>
|
||||||
|
<exclude>META-INF/*.RSA</exclude>
|
||||||
|
</excludes>
|
||||||
|
</filter>
|
||||||
|
</filters>
|
||||||
|
<transformers>
|
||||||
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
<manifestEntries>
|
||||||
|
<Main-Class>${launcher.class}</Main-Class>
|
||||||
|
<Main-Verticle>${main.verticle}</Main-Verticle>
|
||||||
|
</manifestEntries>
|
||||||
|
</transformer>
|
||||||
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
|
||||||
|
</transformers>
|
||||||
|
<finalName>${project.artifactId}-${project.version}</finalName>
|
||||||
|
<!-- <outputFile>${project.build.directory}/${project.artifactId}-${project.version}.jar</outputFile>-->
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${maven-surefire-plugin.version}</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>exec-maven-plugin</artifactId>
|
||||||
|
<version>${exec-maven-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<mainClass>io.vertx.core.Launcher</mainClass>
|
||||||
|
<arguments>
|
||||||
|
<argument>run</argument>
|
||||||
|
<argument>${main.verticle}</argument>
|
||||||
|
</arguments>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,123 @@
|
|||||||
|
package com.leosam.tvbox.mv;
|
||||||
|
|
||||||
|
import com.leosam.tvbox.mv.data.MvResult;
|
||||||
|
import com.leosam.tvbox.mv.data.VodResult;
|
||||||
|
import com.leosam.tvbox.mv.service.MvService;
|
||||||
|
import com.leosam.tvbox.mv.utils.NumberUtils;
|
||||||
|
import com.leosam.tvbox.mv.utils.StringUtils;
|
||||||
|
import com.leosam.tvbox.mv.utils.VertxUtils;
|
||||||
|
import io.vertx.core.AbstractVerticle;
|
||||||
|
import io.vertx.core.Promise;
|
||||||
|
import io.vertx.core.Vertx;
|
||||||
|
import io.vertx.core.http.HttpServer;
|
||||||
|
import io.vertx.core.json.Json;
|
||||||
|
import io.vertx.ext.web.Router;
|
||||||
|
import io.vertx.ext.web.RoutingContext;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
public class MainVerticle extends AbstractVerticle {
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(MainVerticle.class);
|
||||||
|
|
||||||
|
private static MvService mvService;
|
||||||
|
private static int port = 0;
|
||||||
|
|
||||||
|
static {
|
||||||
|
CompletableFuture.runAsync(MainVerticle::initIndex)
|
||||||
|
.thenAcceptAsync((a) -> {
|
||||||
|
if (port > 0) {
|
||||||
|
logger.info("索引完成,可以请求数据了, HTTP server port " + port);
|
||||||
|
} else {
|
||||||
|
logger.info("索引完成,可以请求数据了");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initIndex() {
|
||||||
|
try {
|
||||||
|
MvService mvService = new MvService();
|
||||||
|
mvService.initIndex();
|
||||||
|
MainVerticle.mvService = mvService;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("初始化索引失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start(Promise<Void> startPromise) throws Exception {
|
||||||
|
HttpServer httpServer = vertx.createHttpServer();
|
||||||
|
|
||||||
|
Router router = Router.router(vertx);
|
||||||
|
router.route("/mv/search").handler(this::searchMv);
|
||||||
|
router.route("/mv/vod").handler(this::searchMvVod);
|
||||||
|
router.route().handler(req -> req.response().putHeader("content-type", "text/plain").end("Hello from Vert.x!"));
|
||||||
|
httpServer.requestHandler(router);
|
||||||
|
|
||||||
|
httpServer.listen(7777, http -> {
|
||||||
|
if (http.succeeded()) {
|
||||||
|
startPromise.complete();
|
||||||
|
logger.info("HTTP server started on port 7777");
|
||||||
|
} else {
|
||||||
|
startPromise.fail(http.cause());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
port = httpServer.actualPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void searchMvVod(RoutingContext req) {
|
||||||
|
// 获取参数
|
||||||
|
String wd = VertxUtils.queryParam(req, "wd");
|
||||||
|
String ac = VertxUtils.queryParam(req, "ac");
|
||||||
|
String ids = VertxUtils.queryParam(req, "ids");
|
||||||
|
String maxCount = VertxUtils.queryParam(req, "maxCount");
|
||||||
|
int max = Math.min(Math.max(NumberUtils.toInt(maxCount, 100), 10), 1000);
|
||||||
|
String query = StringUtils.isNotEmpty(wd) ? wd : ids;
|
||||||
|
|
||||||
|
// 处理结果
|
||||||
|
VodResult vodResult = null;
|
||||||
|
try {
|
||||||
|
if (mvService != null) {
|
||||||
|
vodResult = mvService.searchVod(query, max);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回数据
|
||||||
|
String jsonString = Json.encode(vodResult);
|
||||||
|
req.response()
|
||||||
|
.putHeader("content-type", "application/json")
|
||||||
|
.end(jsonString);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void searchMv(RoutingContext req) {
|
||||||
|
// 获取参数
|
||||||
|
String query = VertxUtils.queryParam(req, "query");
|
||||||
|
String maxCount = VertxUtils.queryParam(req, "maxCount");
|
||||||
|
int max = Math.min(Math.max(NumberUtils.toInt(maxCount, 100), 10), 1000);
|
||||||
|
|
||||||
|
// 处理结果
|
||||||
|
MvResult search = null;
|
||||||
|
try {
|
||||||
|
if (mvService != null) {
|
||||||
|
search = mvService.search(query, max);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 返回数据
|
||||||
|
String jsonString = Json.encode(search);
|
||||||
|
req.response()
|
||||||
|
.putHeader("content-type", "application/json")
|
||||||
|
.end(jsonString);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Vertx vertx = Vertx.vertx();
|
||||||
|
vertx.deployVerticle(new MainVerticle());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package com.leosam.tvbox.mv;
|
|
||||||
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
|
|
||||||
@SpringBootApplication
|
|
||||||
public class TvboxMvApplication {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
SpringApplication.run(TvboxMvApplication.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
package com.leosam.tvbox.mv.controller;
|
|
||||||
|
|
||||||
import com.leosam.tvbox.mv.data.MvResult;
|
|
||||||
import com.leosam.tvbox.mv.service.MvService;
|
|
||||||
import com.leosam.tvbox.mv.utils.NumberUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author admin
|
|
||||||
* @since 2023/6/10 17:34
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
public class IndexController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private MvService mvService;
|
|
||||||
|
|
||||||
@RequestMapping(value = {"/mv/search"})
|
|
||||||
public MvResult searchMv(String query, String maxCount) throws Exception {
|
|
||||||
int max = Math.min(Math.max(NumberUtils.toInt(maxCount, 100), 10), 1000);
|
|
||||||
return mvService.search(query, max);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package com.leosam.tvbox.mv.controller;
|
|
||||||
|
|
||||||
import com.leosam.tvbox.mv.data.VodResult;
|
|
||||||
import com.leosam.tvbox.mv.service.MvService;
|
|
||||||
import com.leosam.tvbox.mv.utils.NumberUtils;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author admin
|
|
||||||
* @since 2023/6/11 18:54
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
public class VodController {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private MvService mvService;
|
|
||||||
|
|
||||||
@RequestMapping(value = {"/mv/vod"})
|
|
||||||
public VodResult searchVod(String wd, String ac, String ids, String maxCount) throws Exception {
|
|
||||||
int max = Math.min(Math.max(NumberUtils.toInt(maxCount, 100), 10), 1000);
|
|
||||||
String query = StringUtils.hasText(wd) ? wd : ids;
|
|
||||||
return mvService.searchVod(query, max);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
package com.leosam.tvbox.mv.lucene;
|
package com.leosam.tvbox.mv.lucene;
|
||||||
|
|
||||||
|
import io.vertx.ext.web.impl.LRUCache;
|
||||||
import org.apache.lucene.analysis.Analyzer;
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
|
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
|
||||||
import org.apache.lucene.document.Document;
|
import org.apache.lucene.document.Document;
|
||||||
import org.apache.lucene.index.DirectoryReader;
|
import org.apache.lucene.index.DirectoryReader;
|
||||||
import org.apache.lucene.index.IndexReader;
|
import org.apache.lucene.index.IndexReader;
|
||||||
|
import org.apache.lucene.index.StoredFields;
|
||||||
import org.apache.lucene.queryparser.classic.QueryParser;
|
import org.apache.lucene.queryparser.classic.QueryParser;
|
||||||
import org.apache.lucene.search.IndexSearcher;
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
@@ -24,39 +26,58 @@ import java.nio.file.Paths;
|
|||||||
public class MvSearcher {
|
public class MvSearcher {
|
||||||
private IndexReader reader;
|
private IndexReader reader;
|
||||||
private IndexSearcher searcher;
|
private IndexSearcher searcher;
|
||||||
|
private StoredFields storedFields;
|
||||||
|
private final LRUCache<Integer, Document> documentLruCache = new LRUCache<>(1000);
|
||||||
|
private final LRUCache<String, TopDocs> topDocsLruCache = new LRUCache<>(100);
|
||||||
|
|
||||||
public MvSearcher(String indexDirectoryPath) throws IOException {
|
public MvSearcher(String indexDirectoryPath) throws IOException {
|
||||||
Path indexPath = Paths.get(indexDirectoryPath);
|
Path indexPath = Paths.get(indexDirectoryPath);
|
||||||
Directory directory = FSDirectory.open(indexPath);
|
Directory directory = FSDirectory.open(indexPath);
|
||||||
reader = DirectoryReader.open(directory);
|
reader = DirectoryReader.open(directory);
|
||||||
searcher = new IndexSearcher(reader);
|
searcher = new IndexSearcher(reader);
|
||||||
|
storedFields = reader.storedFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
public TopDocs searchTopDocs(String field, String queryStr, int maxHit) throws Exception {
|
public TopDocs searchTopDocs(String field, String queryStr, int maxHit) throws Exception {
|
||||||
|
String cacheKey = field + "_" + queryStr + "_" + maxHit;
|
||||||
|
TopDocs topDocs = topDocsLruCache.get(cacheKey);
|
||||||
|
if (topDocs != null) {
|
||||||
|
return topDocs;
|
||||||
|
}
|
||||||
|
|
||||||
Analyzer analyzer = new SmartChineseAnalyzer();
|
Analyzer analyzer = new SmartChineseAnalyzer();
|
||||||
// Analyzer analyzer = new StandardAnalyzer();
|
// Analyzer analyzer = new StandardAnalyzer();
|
||||||
QueryParser parser = new QueryParser(field, analyzer);
|
QueryParser parser = new QueryParser(field, analyzer);
|
||||||
Query query = parser.parse(queryStr);
|
Query query = parser.parse(queryStr);
|
||||||
TopDocs docs = searcher.search(query, maxHit);
|
TopDocs docs = searcher.search(query, maxHit);
|
||||||
|
|
||||||
|
topDocsLruCache.put(cacheKey, docs);
|
||||||
return docs;
|
return docs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void search(String field, String queryStr) throws Exception {
|
public void search(String field, String queryStr) throws Exception {
|
||||||
Analyzer analyzer = new SmartChineseAnalyzer();
|
Analyzer analyzer = new SmartChineseAnalyzer();
|
||||||
// Analyzer analyzer = new StandardAnalyzer();
|
// Analyzer analyzer = new StandardAnalyzer();
|
||||||
QueryParser parser = new QueryParser(field, analyzer);
|
QueryParser parser = new QueryParser(field, analyzer);
|
||||||
Query query = parser.parse(queryStr);
|
Query query = parser.parse(queryStr);
|
||||||
TopDocs docs = searcher.search(query, 200);
|
TopDocs docs = searcher.search(query, 200);
|
||||||
|
|
||||||
// 处理搜索结果
|
// 处理搜索结果
|
||||||
for (ScoreDoc scoreDoc : docs.scoreDocs) {
|
for (ScoreDoc scoreDoc : docs.scoreDocs) {
|
||||||
Document document = searcher.doc(scoreDoc.doc);
|
Document document = getDocument(scoreDoc.doc);
|
||||||
System.out.println(document.get("name") + "," + document.get("url") + " score=" + scoreDoc.score);
|
System.out.println(document.get("name") + "," + document.get("url") + " score=" + scoreDoc.score);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Document getDocument(int docID) throws IOException {
|
public Document getDocument(int docId) throws IOException {
|
||||||
Document document = searcher.doc(docID);
|
Document document = documentLruCache.get(docId);
|
||||||
|
if (document != null) {
|
||||||
|
return document;
|
||||||
|
}
|
||||||
|
document = storedFields.document(docId);
|
||||||
|
if (document != null) {
|
||||||
|
documentLruCache.put(docId, document);
|
||||||
|
}
|
||||||
return document;
|
return document;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import com.leosam.tvbox.mv.data.VodResult;
|
|||||||
import com.leosam.tvbox.mv.lucene.MvIndex;
|
import com.leosam.tvbox.mv.lucene.MvIndex;
|
||||||
import com.leosam.tvbox.mv.lucene.MvSearcher;
|
import com.leosam.tvbox.mv.lucene.MvSearcher;
|
||||||
import com.leosam.tvbox.mv.utils.ClassPathReaderUtils;
|
import com.leosam.tvbox.mv.utils.ClassPathReaderUtils;
|
||||||
|
import com.leosam.tvbox.mv.utils.CollectionUtils;
|
||||||
|
import com.leosam.tvbox.mv.utils.StopWatch;
|
||||||
|
import com.leosam.tvbox.mv.utils.StringUtils;
|
||||||
import org.apache.lucene.document.Document;
|
import org.apache.lucene.document.Document;
|
||||||
import org.apache.lucene.document.Field;
|
import org.apache.lucene.document.Field;
|
||||||
import org.apache.lucene.document.StringField;
|
import org.apache.lucene.document.StringField;
|
||||||
@@ -15,14 +18,10 @@ import org.apache.lucene.search.ScoreDoc;
|
|||||||
import org.apache.lucene.search.TopDocs;
|
import org.apache.lucene.search.TopDocs;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
import org.springframework.util.StopWatch;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -34,16 +33,16 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
* @author admin
|
* @author admin
|
||||||
* @since 2023/6/10 17:35
|
* @since 2023/6/10 17:35
|
||||||
*/
|
*/
|
||||||
@Service
|
public class MvService {
|
||||||
public class MvService implements InitializingBean {
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(MvService.class);
|
private static final Logger logger = LoggerFactory.getLogger(MvService.class);
|
||||||
|
|
||||||
private static final String indexDirectoryPath = "index";
|
private static final String indexDirectoryPath = "index";
|
||||||
|
private static final String MV_FILE = "tvbox/16wMV.txt";
|
||||||
|
|
||||||
private MvSearcher mvSearcher;
|
private MvSearcher mvSearcher;
|
||||||
|
|
||||||
public MvResult search(String query, int max) throws Exception {
|
public MvResult search(String query, int max) throws Exception {
|
||||||
if (!StringUtils.hasText(query)) {
|
if (StringUtils.isEmpty(query) || mvSearcher == null) {
|
||||||
return new MvResult();
|
return new MvResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +54,7 @@ public class MvService implements InitializingBean {
|
|||||||
MvResult result = new MvResult();
|
MvResult result = new MvResult();
|
||||||
result.setQuery(query);
|
result.setQuery(query);
|
||||||
result.setTotalHits(topDocs.totalHits.value);
|
result.setTotalHits(topDocs.totalHits.value);
|
||||||
result.setList(new LinkedList<>());
|
result.setList(new ArrayList<>(topDocs.scoreDocs.length));
|
||||||
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
|
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
|
||||||
Document document = mvSearcher.getDocument(scoreDoc.doc);
|
Document document = mvSearcher.getDocument(scoreDoc.doc);
|
||||||
if (document == null) {
|
if (document == null) {
|
||||||
@@ -66,8 +65,9 @@ public class MvService implements InitializingBean {
|
|||||||
String songName = name;
|
String songName = name;
|
||||||
String songUser = null;
|
String songUser = null;
|
||||||
if (name.contains("-")) {
|
if (name.contains("-")) {
|
||||||
songUser = name.split("-", 2)[0];
|
String[] split = name.split("-", 2);
|
||||||
songName = name.split("-", 2)[1];
|
songUser = split[0];
|
||||||
|
songName = split[1];
|
||||||
}
|
}
|
||||||
String url = document.get("url");
|
String url = document.get("url");
|
||||||
if (!url.startsWith("http")) {
|
if (!url.startsWith("http")) {
|
||||||
@@ -96,12 +96,13 @@ public class MvService implements InitializingBean {
|
|||||||
vod.setVodId(wd);
|
vod.setVodId(wd);
|
||||||
vod.setVodName(wd);
|
vod.setVodName(wd);
|
||||||
vod.setVodPlayFrom("mv");
|
vod.setVodPlayFrom("mv");
|
||||||
vod.setVodPic("http://m4.auto.itc.cn/auto/content/20230611/45d65d8a001f0c5aa008030f41c98666.jpeg");
|
vod.setVodPic("http://yanxuan.nosdn.127.net/b6fb987ce79f308949e44f5129a4b51c.jpeg");
|
||||||
|
// vod.setVodPic("http://m4.auto.itc.cn/auto/content/20230611/45d65d8a001f0c5aa008030f41c98666.jpeg");
|
||||||
List<String> playUrlList = new LinkedList<>();
|
List<String> playUrlList = new LinkedList<>();
|
||||||
Set<String> vodActorList = new LinkedHashSet<>();
|
Set<String> vodActorList = new LinkedHashSet<>();
|
||||||
for (MvContent content : search.getList()) {
|
for (MvContent content : search.getList()) {
|
||||||
playUrlList.add(content.getName() + "$" + content.getUrl());
|
playUrlList.add(content.getName() + "$" + content.getUrl());
|
||||||
if (vodActorList.size() < 5 && StringUtils.hasText(content.getSongUser())) {
|
if (vodActorList.size() < 5 && StringUtils.isNotEmpty(content.getSongUser())) {
|
||||||
vodActorList.add(content.getSongUser());
|
vodActorList.add(content.getSongUser());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,8 +116,8 @@ public class MvService implements InitializingBean {
|
|||||||
return vodResult;
|
return vodResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void initIndex() throws Exception {
|
||||||
public void afterPropertiesSet() throws Exception {
|
|
||||||
// 重建索引
|
// 重建索引
|
||||||
String indexAbsolutePath = new File(indexDirectoryPath).getAbsoluteFile().getAbsolutePath();
|
String indexAbsolutePath = new File(indexDirectoryPath).getAbsoluteFile().getAbsolutePath();
|
||||||
reBuildIndex(indexAbsolutePath);
|
reBuildIndex(indexAbsolutePath);
|
||||||
@@ -130,13 +131,22 @@ public class MvService implements InitializingBean {
|
|||||||
|
|
||||||
|
|
||||||
private static void reBuildIndex(String indexDirectoryPath) throws IOException {
|
private static void reBuildIndex(String indexDirectoryPath) throws IOException {
|
||||||
|
File file = new File(indexDirectoryPath).getAbsoluteFile();
|
||||||
|
int mvFileSize = ClassPathReaderUtils.getSize(MV_FILE);
|
||||||
|
File mvFileSizeTxt = Path.of(file.getAbsolutePath(), "" + mvFileSize + ".txt").toFile();
|
||||||
|
if (mvFileSizeTxt.exists()) {
|
||||||
|
logger.info("{}已经索引, 跳过索引", MV_FILE);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
StopWatch stopWatch = new StopWatch();
|
StopWatch stopWatch = new StopWatch();
|
||||||
logger.info("重建索引中....");
|
logger.info("重建索引中....");
|
||||||
|
|
||||||
// 清空以前的索引
|
// 清空以前的索引
|
||||||
stopWatch.start("清空以前索引");
|
stopWatch.start("清空以前索引");
|
||||||
logger.info("清空历史索引....");
|
logger.info("清空历史索引....");
|
||||||
File file = new File(indexDirectoryPath).getAbsoluteFile();
|
|
||||||
if (file.isDirectory()) {
|
if (file.isDirectory()) {
|
||||||
File[] files = file.listFiles();
|
File[] files = file.listFiles();
|
||||||
for (File file1 : files) {
|
for (File file1 : files) {
|
||||||
@@ -152,7 +162,7 @@ public class MvService implements InitializingBean {
|
|||||||
logger.info("创建索引中....");
|
logger.info("创建索引中....");
|
||||||
AtomicInteger line = new AtomicInteger();
|
AtomicInteger line = new AtomicInteger();
|
||||||
MvIndex mvIndex = new MvIndex(indexDirectoryPath);
|
MvIndex mvIndex = new MvIndex(indexDirectoryPath);
|
||||||
ClassPathReaderUtils.getBufferedReader("tvbox/16wMV.txt").lines()
|
ClassPathReaderUtils.getBufferedReader(MV_FILE).lines()
|
||||||
.filter(l -> l.contains(",h"))
|
.filter(l -> l.contains(",h"))
|
||||||
.filter(l -> l.contains("-"))
|
.filter(l -> l.contains("-"))
|
||||||
.forEach(l -> {
|
.forEach(l -> {
|
||||||
@@ -182,6 +192,7 @@ public class MvService implements InitializingBean {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
mvIndex.close();
|
mvIndex.close();
|
||||||
|
mvFileSizeTxt.createNewFile();
|
||||||
logger.info("创建索引中....完成, 总共{}条", line.get());
|
logger.info("创建索引中....完成, 总共{}条", line.get());
|
||||||
stopWatch.stop();
|
stopWatch.stop();
|
||||||
logger.info("重建索引中....完成,耗时 {} 毫秒, 索引位置:{}", stopWatch.getTotalTimeMillis(), file.getPath());
|
logger.info("重建索引中....完成,耗时 {} 毫秒, 索引位置:{}", stopWatch.getTotalTimeMillis(), file.getPath());
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package com.leosam.tvbox.mv.utils;
|
package com.leosam.tvbox.mv.utils;
|
||||||
|
|
||||||
import org.springframework.core.io.ClassPathResource;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author admin
|
* @author admin
|
||||||
@@ -14,19 +14,33 @@ import java.util.Properties;
|
|||||||
*/
|
*/
|
||||||
public class ClassPathReaderUtils {
|
public class ClassPathReaderUtils {
|
||||||
|
|
||||||
|
public static int getSize(String path) {
|
||||||
|
try {
|
||||||
|
ClassPathResource resource = new ClassPathResource(path);
|
||||||
|
InputStream inputStream = resource.getInputStream();
|
||||||
|
int available = inputStream.available();
|
||||||
|
return available;
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new RuntimeException(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static InputStreamReader getInputStreamReader(String path) {
|
public static InputStreamReader getInputStreamReader(String path) {
|
||||||
try {
|
try {
|
||||||
ClassPathResource resource = new ClassPathResource(path);
|
ClassPathResource resource = new ClassPathResource(path);
|
||||||
InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream(),StandardCharsets.UTF_8);
|
InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8);
|
||||||
return inputStreamReader;
|
return inputStreamReader;
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static BufferedReader getBufferedReader(String path) {
|
public static BufferedReader getBufferedReader(String path) {
|
||||||
try {
|
try {
|
||||||
ClassPathResource resource = new ClassPathResource(path);
|
ClassPathResource resource = new ClassPathResource(path);
|
||||||
|
|
||||||
|
|
||||||
InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream(),StandardCharsets.UTF_8);
|
InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream(),StandardCharsets.UTF_8);
|
||||||
BufferedReader reader = new BufferedReader(inputStreamReader);
|
BufferedReader reader = new BufferedReader(inputStreamReader);
|
||||||
return reader;
|
return reader;
|
||||||
@@ -35,17 +49,6 @@ public class ClassPathReaderUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Properties getProperties(String path) {
|
|
||||||
Properties properties = new Properties();
|
|
||||||
try {
|
|
||||||
ClassPathResource resource = new ClassPathResource(path);
|
|
||||||
InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream());
|
|
||||||
properties.load(new BufferedReader(inputStreamReader));
|
|
||||||
} catch (IOException ex) {
|
|
||||||
throw new RuntimeException(ex);
|
|
||||||
}
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getContent(String path) {
|
public static String getContent(String path) {
|
||||||
StringBuilder content = new StringBuilder();
|
StringBuilder content = new StringBuilder();
|
||||||
@@ -70,5 +73,52 @@ public class ClassPathReaderUtils {
|
|||||||
System.out.println(json);
|
System.out.println(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ClassPathResource {
|
||||||
|
private final String path;
|
||||||
|
|
||||||
|
private final ClassLoader classLoader;
|
||||||
|
|
||||||
|
public ClassPathResource(String path) {
|
||||||
|
this.path = path;
|
||||||
|
this.classLoader = getDefaultClassLoader();
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream getInputStream() throws IOException {
|
||||||
|
InputStream is;
|
||||||
|
if (this.classLoader != null) {
|
||||||
|
is = this.classLoader.getResourceAsStream(this.path);
|
||||||
|
} else {
|
||||||
|
is = ClassLoader.getSystemResourceAsStream(this.path);
|
||||||
|
}
|
||||||
|
if (is == null) {
|
||||||
|
throw new FileNotFoundException(path + " cannot be opened because it does not exist");
|
||||||
|
}
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static ClassLoader getDefaultClassLoader() {
|
||||||
|
ClassLoader cl = null;
|
||||||
|
try {
|
||||||
|
cl = Thread.currentThread().getContextClassLoader();
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
// Cannot access thread context ClassLoader - falling back...
|
||||||
|
}
|
||||||
|
if (cl == null) {
|
||||||
|
// No thread context class loader -> use class loader of this class.
|
||||||
|
cl = ClassPathResource.class.getClassLoader();
|
||||||
|
if (cl == null) {
|
||||||
|
// getClassLoader() returning null indicates the bootstrap ClassLoader
|
||||||
|
try {
|
||||||
|
cl = ClassLoader.getSystemClassLoader();
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.leosam.tvbox.mv.utils;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author admin
|
||||||
|
* @since 2023/6/12 21:15
|
||||||
|
*/
|
||||||
|
public class CollectionUtils {
|
||||||
|
|
||||||
|
public static boolean isEmpty(Collection<?> collection) {
|
||||||
|
return (collection == null || collection.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
package com.leosam.tvbox.mv.utils;
|
|
||||||
|
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
||||||
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class JsonUtils {
|
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(JsonUtils.class);
|
|
||||||
private static final TypeReference<HashMap<String, String>> TYPE_MAP =
|
|
||||||
new TypeReference<HashMap<String, String>>() {
|
|
||||||
};
|
|
||||||
|
|
||||||
public static ObjectMapper objectMapper = new ObjectMapper();
|
|
||||||
|
|
||||||
static {
|
|
||||||
objectMapper.registerModule(new Jdk8Module());
|
|
||||||
objectMapper.enable(JsonParser.Feature.ALLOW_COMMENTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String writeValue(Object o) {
|
|
||||||
try {
|
|
||||||
return writeValueThrowException(o);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String writeValuePrettyPrinter(Object o) {
|
|
||||||
try {
|
|
||||||
return objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(o);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error("exception occur when Json serializePretty", e);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public static String writeValueThrowException(Object o) throws JsonProcessingException {
|
|
||||||
try {
|
|
||||||
return objectMapper.writeValueAsString(o);
|
|
||||||
} catch (Exception e) {
|
|
||||||
LOG.error("exception occur when Json serialize", e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T readValue(String json, Class<T> clazz) {
|
|
||||||
try {
|
|
||||||
return readValueThrowException(json, clazz);
|
|
||||||
} catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T readValueThrowException(String json, Class<T> clazz) throws IOException {
|
|
||||||
try {
|
|
||||||
return objectMapper.readValue(json, clazz);
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOG.warn("Failed to deserialize from JSON string", e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T readValue(String json, TypeReference<T> typeReference) {
|
|
||||||
try {
|
|
||||||
return readValueThrowException(json, typeReference);
|
|
||||||
} catch (IOException e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> T readValueThrowException(String json, TypeReference<T> typeReference) throws IOException {
|
|
||||||
try {
|
|
||||||
return objectMapper.readValue(json, typeReference);
|
|
||||||
} catch (IOException e) {
|
|
||||||
LOG.warn("Failed to deserialize from JSON string", e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -7,7 +7,7 @@ package com.leosam.tvbox.mv.utils;
|
|||||||
public class NumberUtils {
|
public class NumberUtils {
|
||||||
|
|
||||||
public static int toInt(final String str, final int defaultValue) {
|
public static int toInt(final String str, final int defaultValue) {
|
||||||
if (str == null) {
|
if (str == null || str.length() == 0) {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -0,0 +1,392 @@
|
|||||||
|
package com.leosam.tvbox.mv.utils;
|
||||||
|
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple stop watch, allowing for timing of a number of tasks, exposing total
|
||||||
|
* running time and running time for each named task.
|
||||||
|
*
|
||||||
|
* <p>Conceals use of {@link System#nanoTime()}, improving the readability of
|
||||||
|
* application code and reducing the likelihood of calculation errors.
|
||||||
|
*
|
||||||
|
* <p>Note that this object is not designed to be thread-safe and does not use
|
||||||
|
* synchronization.
|
||||||
|
*
|
||||||
|
* <p>This class is normally used to verify performance during proof-of-concept
|
||||||
|
* work and in development, rather than as part of production applications.
|
||||||
|
*
|
||||||
|
* <p>As of Spring Framework 5.2, running time is tracked and reported in
|
||||||
|
* nanoseconds.
|
||||||
|
*
|
||||||
|
* @author Rod Johnson
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since May 2, 2001
|
||||||
|
*/
|
||||||
|
public class StopWatch {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identifier of this {@code StopWatch}.
|
||||||
|
* <p>Handy when we have output from multiple stop watches and need to
|
||||||
|
* distinguish between them in log or console output.
|
||||||
|
*/
|
||||||
|
private final String id;
|
||||||
|
|
||||||
|
private boolean keepTaskList = true;
|
||||||
|
|
||||||
|
private final List<TaskInfo> taskList = new ArrayList<>(1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start time of the current task.
|
||||||
|
*/
|
||||||
|
private long startTimeNanos;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name of the current task.
|
||||||
|
*/
|
||||||
|
private String currentTaskName;
|
||||||
|
|
||||||
|
private TaskInfo lastTaskInfo;
|
||||||
|
|
||||||
|
private int taskCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Total running time.
|
||||||
|
*/
|
||||||
|
private long totalTimeNanos;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new {@code StopWatch}.
|
||||||
|
* <p>Does not start any task.
|
||||||
|
*/
|
||||||
|
public StopWatch() {
|
||||||
|
this("");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new {@code StopWatch} with the given ID.
|
||||||
|
* <p>The ID is handy when we have output from multiple stop watches and need
|
||||||
|
* to distinguish between them.
|
||||||
|
* <p>Does not start any task.
|
||||||
|
*
|
||||||
|
* @param id identifier for this stop watch
|
||||||
|
*/
|
||||||
|
public StopWatch(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ID of this {@code StopWatch}, as specified on construction.
|
||||||
|
*
|
||||||
|
* @return the ID (empty String by default)
|
||||||
|
* @see #StopWatch(String)
|
||||||
|
* @since 4.2.2
|
||||||
|
*/
|
||||||
|
public String getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure whether the {@link StopWatch.TaskInfo} array is built over time.
|
||||||
|
* <p>Set this to {@code false} when using a {@code StopWatch} for millions
|
||||||
|
* of intervals; otherwise, the {@code TaskInfo} structure will consume
|
||||||
|
* excessive memory.
|
||||||
|
* <p>Default is {@code true}.
|
||||||
|
*/
|
||||||
|
public void setKeepTaskList(boolean keepTaskList) {
|
||||||
|
this.keepTaskList = keepTaskList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start an unnamed task.
|
||||||
|
* <p>The results are undefined if {@link #stop()} or timing methods are
|
||||||
|
* called without invoking this method first.
|
||||||
|
*
|
||||||
|
* @see #start(String)
|
||||||
|
* @see #stop()
|
||||||
|
*/
|
||||||
|
public void start() throws IllegalStateException {
|
||||||
|
start("");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start a named task.
|
||||||
|
* <p>The results are undefined if {@link #stop()} or timing methods are
|
||||||
|
* called without invoking this method first.
|
||||||
|
*
|
||||||
|
* @param taskName the name of the task to start
|
||||||
|
* @see #start()
|
||||||
|
* @see #stop()
|
||||||
|
*/
|
||||||
|
public void start(String taskName) throws IllegalStateException {
|
||||||
|
if (this.currentTaskName != null) {
|
||||||
|
throw new IllegalStateException("Can't start StopWatch: it's already running");
|
||||||
|
}
|
||||||
|
this.currentTaskName = taskName;
|
||||||
|
this.startTimeNanos = System.nanoTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop the current task.
|
||||||
|
* <p>The results are undefined if timing methods are called without invoking
|
||||||
|
* at least one pair of {@code start()} / {@code stop()} methods.
|
||||||
|
*
|
||||||
|
* @see #start()
|
||||||
|
* @see #start(String)
|
||||||
|
*/
|
||||||
|
public void stop() throws IllegalStateException {
|
||||||
|
if (this.currentTaskName == null) {
|
||||||
|
throw new IllegalStateException("Can't stop StopWatch: it's not running");
|
||||||
|
}
|
||||||
|
long lastTime = System.nanoTime() - this.startTimeNanos;
|
||||||
|
this.totalTimeNanos += lastTime;
|
||||||
|
this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTime);
|
||||||
|
if (this.keepTaskList) {
|
||||||
|
this.taskList.add(this.lastTaskInfo);
|
||||||
|
}
|
||||||
|
++this.taskCount;
|
||||||
|
this.currentTaskName = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether this {@code StopWatch} is currently running.
|
||||||
|
*
|
||||||
|
* @see #currentTaskName()
|
||||||
|
*/
|
||||||
|
public boolean isRunning() {
|
||||||
|
return (this.currentTaskName != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the currently running task, if any.
|
||||||
|
*
|
||||||
|
* @see #isRunning()
|
||||||
|
* @since 4.2.2
|
||||||
|
*/
|
||||||
|
public String currentTaskName() {
|
||||||
|
return this.currentTaskName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the time taken by the last task in nanoseconds.
|
||||||
|
*
|
||||||
|
* @see #getLastTaskTimeMillis()
|
||||||
|
* @since 5.2
|
||||||
|
*/
|
||||||
|
public long getLastTaskTimeNanos() throws IllegalStateException {
|
||||||
|
if (this.lastTaskInfo == null) {
|
||||||
|
throw new IllegalStateException("No tasks run: can't get last task interval");
|
||||||
|
}
|
||||||
|
return this.lastTaskInfo.getTimeNanos();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the time taken by the last task in milliseconds.
|
||||||
|
*
|
||||||
|
* @see #getLastTaskTimeNanos()
|
||||||
|
*/
|
||||||
|
public long getLastTaskTimeMillis() throws IllegalStateException {
|
||||||
|
if (this.lastTaskInfo == null) {
|
||||||
|
throw new IllegalStateException("No tasks run: can't get last task interval");
|
||||||
|
}
|
||||||
|
return this.lastTaskInfo.getTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the last task.
|
||||||
|
*/
|
||||||
|
public String getLastTaskName() throws IllegalStateException {
|
||||||
|
if (this.lastTaskInfo == null) {
|
||||||
|
throw new IllegalStateException("No tasks run: can't get last task name");
|
||||||
|
}
|
||||||
|
return this.lastTaskInfo.getTaskName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the last task as a {@link StopWatch.TaskInfo} object.
|
||||||
|
*/
|
||||||
|
public StopWatch.TaskInfo getLastTaskInfo() throws IllegalStateException {
|
||||||
|
if (this.lastTaskInfo == null) {
|
||||||
|
throw new IllegalStateException("No tasks run: can't get last task info");
|
||||||
|
}
|
||||||
|
return this.lastTaskInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the total time in nanoseconds for all tasks.
|
||||||
|
*
|
||||||
|
* @see #getTotalTimeMillis()
|
||||||
|
* @see #getTotalTimeSeconds()
|
||||||
|
* @since 5.2
|
||||||
|
*/
|
||||||
|
public long getTotalTimeNanos() {
|
||||||
|
return this.totalTimeNanos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the total time in milliseconds for all tasks.
|
||||||
|
*
|
||||||
|
* @see #getTotalTimeNanos()
|
||||||
|
* @see #getTotalTimeSeconds()
|
||||||
|
*/
|
||||||
|
public long getTotalTimeMillis() {
|
||||||
|
return nanosToMillis(this.totalTimeNanos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the total time in seconds for all tasks.
|
||||||
|
*
|
||||||
|
* @see #getTotalTimeNanos()
|
||||||
|
* @see #getTotalTimeMillis()
|
||||||
|
*/
|
||||||
|
public double getTotalTimeSeconds() {
|
||||||
|
return nanosToSeconds(this.totalTimeNanos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the number of tasks timed.
|
||||||
|
*/
|
||||||
|
public int getTaskCount() {
|
||||||
|
return this.taskCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an array of the data for tasks performed.
|
||||||
|
*/
|
||||||
|
public StopWatch.TaskInfo[] getTaskInfo() {
|
||||||
|
if (!this.keepTaskList) {
|
||||||
|
throw new UnsupportedOperationException("Task info is not being kept!");
|
||||||
|
}
|
||||||
|
return this.taskList.toArray(new StopWatch.TaskInfo[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a short description of the total running time.
|
||||||
|
*/
|
||||||
|
public String shortSummary() {
|
||||||
|
return "StopWatch '" + getId() + "': running time = " + getTotalTimeNanos() + " ns";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a string with a table describing all tasks performed.
|
||||||
|
* <p>For custom reporting, call {@link #getTaskInfo()} and use the task info
|
||||||
|
* directly.
|
||||||
|
*/
|
||||||
|
public String prettyPrint() {
|
||||||
|
StringBuilder sb = new StringBuilder(shortSummary());
|
||||||
|
sb.append('\n');
|
||||||
|
if (!this.keepTaskList) {
|
||||||
|
sb.append("No task info kept");
|
||||||
|
} else {
|
||||||
|
sb.append("---------------------------------------------\n");
|
||||||
|
sb.append("ns % Task name\n");
|
||||||
|
sb.append("---------------------------------------------\n");
|
||||||
|
NumberFormat nf = NumberFormat.getNumberInstance();
|
||||||
|
nf.setMinimumIntegerDigits(9);
|
||||||
|
nf.setGroupingUsed(false);
|
||||||
|
NumberFormat pf = NumberFormat.getPercentInstance();
|
||||||
|
pf.setMinimumIntegerDigits(3);
|
||||||
|
pf.setGroupingUsed(false);
|
||||||
|
for (StopWatch.TaskInfo task : getTaskInfo()) {
|
||||||
|
sb.append(nf.format(task.getTimeNanos())).append(" ");
|
||||||
|
sb.append(pf.format((double) task.getTimeNanos() / getTotalTimeNanos())).append(" ");
|
||||||
|
sb.append(task.getTaskName()).append('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate an informative string describing all tasks performed
|
||||||
|
* <p>For custom reporting, call {@link #getTaskInfo()} and use the task info
|
||||||
|
* directly.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder(shortSummary());
|
||||||
|
if (this.keepTaskList) {
|
||||||
|
for (StopWatch.TaskInfo task : getTaskInfo()) {
|
||||||
|
sb.append("; [").append(task.getTaskName()).append("] took ").append(task.getTimeNanos()).append(" ns");
|
||||||
|
long percent = Math.round(100.0 * task.getTimeNanos() / getTotalTimeNanos());
|
||||||
|
sb.append(" = ").append(percent).append('%');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sb.append("; no task info kept");
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static long nanosToMillis(long duration) {
|
||||||
|
return TimeUnit.NANOSECONDS.toMillis(duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double nanosToSeconds(long duration) {
|
||||||
|
return duration / 1_000_000_000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nested class to hold data about one task executed within the {@code StopWatch}.
|
||||||
|
*/
|
||||||
|
public static final class TaskInfo {
|
||||||
|
|
||||||
|
private final String taskName;
|
||||||
|
|
||||||
|
private final long timeNanos;
|
||||||
|
|
||||||
|
TaskInfo(String taskName, long timeNanos) {
|
||||||
|
this.taskName = taskName;
|
||||||
|
this.timeNanos = timeNanos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of this task.
|
||||||
|
*/
|
||||||
|
public String getTaskName() {
|
||||||
|
return this.taskName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the time in nanoseconds this task took.
|
||||||
|
*
|
||||||
|
* @see #getTimeMillis()
|
||||||
|
* @see #getTimeSeconds()
|
||||||
|
* @since 5.2
|
||||||
|
*/
|
||||||
|
public long getTimeNanos() {
|
||||||
|
return this.timeNanos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the time in milliseconds this task took.
|
||||||
|
*
|
||||||
|
* @see #getTimeNanos()
|
||||||
|
* @see #getTimeSeconds()
|
||||||
|
*/
|
||||||
|
public long getTimeMillis() {
|
||||||
|
return nanosToMillis(this.timeNanos);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the time in seconds this task took.
|
||||||
|
*
|
||||||
|
* @see #getTimeMillis()
|
||||||
|
* @see #getTimeNanos()
|
||||||
|
*/
|
||||||
|
public double getTimeSeconds() {
|
||||||
|
return nanosToSeconds(this.timeNanos);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.leosam.tvbox.mv.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author admin
|
||||||
|
* @since 2023/6/12 21:32
|
||||||
|
*/
|
||||||
|
public class StringUtils {
|
||||||
|
|
||||||
|
public static boolean isNotEmpty(final CharSequence cs) {
|
||||||
|
return !isEmpty(cs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isEmpty(final CharSequence cs) {
|
||||||
|
return cs == null || cs.length() == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package com.leosam.tvbox.mv.utils;
|
||||||
|
|
||||||
|
import io.vertx.ext.web.RoutingContext;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author admin
|
||||||
|
* @since 2023/6/12 21:16
|
||||||
|
*/
|
||||||
|
public class VertxUtils {
|
||||||
|
|
||||||
|
public static String queryParam(RoutingContext context, String wd) {
|
||||||
|
List<String> param = context.queryParam(wd);
|
||||||
|
if (param != null && param.size() > 0) {
|
||||||
|
return param.get(0);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.leosam.tvbox.mv.view;
|
|
||||||
|
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author admin
|
|
||||||
* @since 2023/6/11 20:03
|
|
||||||
*/
|
|
||||||
public class MyTimeInterceptor implements HandlerInterceptor {
|
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(MyTimeInterceptor.class);
|
|
||||||
/**
|
|
||||||
* 线程变量 - 开始执行时间
|
|
||||||
*/
|
|
||||||
private final ThreadLocal<Long> startTime = new ThreadLocal<>();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
|
||||||
startTime.set(System.nanoTime());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
|
|
||||||
if (startTime.get() == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
long processTime = System.nanoTime() - startTime.get();
|
|
||||||
if (logger.isInfoEnabled()) {
|
|
||||||
logger.info("RequestURL[{}], Referer[{}], TIME[{} ms]", request.getRequestURL().toString(), request.getHeader("Referer"), String.format("%.3f", (processTime / 1_000_000.0)));
|
|
||||||
}
|
|
||||||
startTime.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package com.leosam.tvbox.mv.view;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author admin
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class MyWebMvcConfig implements WebMvcConfigurer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
|
||||||
registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
|
||||||
// 页面运行时间统计
|
|
||||||
registry.addInterceptor(new MyTimeInterceptor())
|
|
||||||
.addPathPatterns("/**")
|
|
||||||
.excludePathPatterns("/static/**")
|
|
||||||
.excludePathPatterns("/favicon.ico");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
server:
|
|
||||||
port: 7777
|
|
||||||
spring:
|
|
||||||
profiles:
|
|
||||||
active: test
|
|
||||||
logging:
|
|
||||||
file:
|
|
||||||
name: ./logs/tvbox-mv.log
|
|
||||||
level:
|
|
||||||
.: error
|
|
||||||
org.spring.framework: debug
|
|
||||||
com.leosam: debug
|
|
||||||
|
|
||||||
---
|
|
||||||
server:
|
|
||||||
port: 7777
|
|
||||||
spring:
|
|
||||||
config:
|
|
||||||
activate:
|
|
||||||
on-profile: test
|
|
||||||
logging:
|
|
||||||
file:
|
|
||||||
name: ./logs/tvbox-mv.log
|
|
||||||
|
|
||||||
---
|
|
||||||
server:
|
|
||||||
port: 7777
|
|
||||||
spring:
|
|
||||||
config:
|
|
||||||
activate:
|
|
||||||
on-profile: linux
|
|
||||||
logging:
|
|
||||||
file:
|
|
||||||
name: /opt/logs/tvbox-mv.log
|
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<configuration>
|
||||||
|
|
||||||
|
<!-- 不输出logback 初始化日志 -->
|
||||||
|
<statusListener class="ch.qos.logback.core.status.NopStatusListener" />
|
||||||
|
|
||||||
|
<property name="ENCODING" value="utf-8" />
|
||||||
|
<property name="PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %n"/>
|
||||||
|
<property name="PATTERN-COLOR" value="%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%thread] %highlight(%-5level) %green(%logger{36}) - %highlight(%msg) %n"/>
|
||||||
|
|
||||||
|
<!-- 控制台输出 -->
|
||||||
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
|
||||||
|
<pattern>${PATTERN}</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<!-- 控制台输出-带颜色 -->
|
||||||
|
<appender name="CONSOLE-WITH-COLOR" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<!-- 根据操作环境设置编码器 -->
|
||||||
|
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
|
||||||
|
<!-- 设置控制台输出编码 -->
|
||||||
|
<charset>${ENCODING}</charset>
|
||||||
|
</encoder>
|
||||||
|
<if condition=' !property("java.class.path").contains("SNAPSHOT") || property("jboss.modules.system.pkgs").contains("intellij")'>
|
||||||
|
<then>
|
||||||
|
<!-- 控制台输出-带颜色 -->
|
||||||
|
<encoder>
|
||||||
|
<pattern>${PATTERN-COLOR}</pattern>
|
||||||
|
<withJansi>true</withJansi>
|
||||||
|
</encoder>
|
||||||
|
</then>
|
||||||
|
<else>
|
||||||
|
<!-- 控制台输出-不带颜色 -->
|
||||||
|
<encoder>
|
||||||
|
<pattern>${PATTERN}</pattern>
|
||||||
|
<withJansi>true</withJansi>
|
||||||
|
</encoder>
|
||||||
|
</else>
|
||||||
|
</if>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||||
|
<file>./logs/run.log</file>
|
||||||
|
|
||||||
|
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
|
||||||
|
<!-- 日志保存7天 -->
|
||||||
|
<maxHistory>7</maxHistory>
|
||||||
|
<fileNamePattern>./logs/run.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||||
|
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
|
||||||
|
<maxFileSize>100MB</maxFileSize>
|
||||||
|
</timeBasedFileNamingAndTriggeringPolicy>
|
||||||
|
</rollingPolicy>
|
||||||
|
|
||||||
|
<encoder>
|
||||||
|
<pattern>${PATTERN}</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
<logger name="io.vertx" level="INFO"/>
|
||||||
|
<logger name="io.netty" level="INFO"/>
|
||||||
|
|
||||||
|
<root level="DEBUG">
|
||||||
|
<appender-ref ref="CONSOLE-WITH-COLOR" />
|
||||||
|
<appender-ref ref="FILE" />
|
||||||
|
</root>
|
||||||
|
</configuration>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"sites": [
|
||||||
|
{
|
||||||
|
"key": "MV_vod",
|
||||||
|
"name": "👀┃MV┃视频",
|
||||||
|
"type": 1,
|
||||||
|
"api": "http://192.168.31.253:7777/mv/vod",
|
||||||
|
"searchable": 1,
|
||||||
|
"quickSearch": 1,
|
||||||
|
"filterable": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.leosam.tvbox.mv;
|
||||||
|
|
||||||
|
import io.vertx.core.Vertx;
|
||||||
|
import io.vertx.junit5.VertxExtension;
|
||||||
|
import io.vertx.junit5.VertxTestContext;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
|
||||||
|
@ExtendWith(VertxExtension.class)
|
||||||
|
public class TestMainVerticle {
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void deploy_verticle(Vertx vertx, VertxTestContext testContext) {
|
||||||
|
vertx.deployVerticle(new MainVerticle(), testContext.succeeding(id -> testContext.completeNow()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void verticle_deployed(Vertx vertx, VertxTestContext testContext) throws Throwable {
|
||||||
|
testContext.completeNow();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
package com.leosam.tvbox.mv;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
|
||||||
|
|
||||||
@SpringBootTest
|
|
||||||
class TvboxMvApplicationTests {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void contextLoads() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user