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"
|
||||
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>
|
||||
<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>
|
||||
<artifactId>tvbox-mv</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>tvbox-mv</name>
|
||||
|
||||
<description>Demo project for Spring Boot</description>
|
||||
<properties>
|
||||
<java.version>17</java.version>
|
||||
@@ -20,46 +15,164 @@
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<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>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
<groupId>io.vertx</groupId>
|
||||
<artifactId>vertx-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<groupId>io.vertx</groupId>
|
||||
<artifactId>vertx-junit5</artifactId>
|
||||
<scope>test</scope>
|
||||
</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-->
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-core</artifactId>
|
||||
<version>8.5.2</version>
|
||||
<version>9.5.0</version>
|
||||
</dependency>
|
||||
<!--Lucene Queryparser-->
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-queryparser</artifactId>
|
||||
<version>8.5.2</version>
|
||||
<version>9.5.0</version>
|
||||
</dependency>
|
||||
<!-- Lucene提供的中文分词器模块,lucene-analyzers-smartcn:Lucene 的中文分词器 SmartChineseAnalyzer -->
|
||||
<dependency>
|
||||
<groupId>org.apache.lucene</groupId>
|
||||
<artifactId>lucene-analyzers-smartcn</artifactId>
|
||||
<version>8.5.2</version>
|
||||
<version>8.11.2</version>
|
||||
</dependency>
|
||||
|
||||
</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>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven-compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<release>17</release>
|
||||
</configuration>
|
||||
</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>
|
||||
</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;
|
||||
|
||||
import io.vertx.ext.web.impl.LRUCache;
|
||||
import org.apache.lucene.analysis.Analyzer;
|
||||
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
|
||||
import org.apache.lucene.document.Document;
|
||||
import org.apache.lucene.index.DirectoryReader;
|
||||
import org.apache.lucene.index.IndexReader;
|
||||
import org.apache.lucene.index.StoredFields;
|
||||
import org.apache.lucene.queryparser.classic.QueryParser;
|
||||
import org.apache.lucene.search.IndexSearcher;
|
||||
import org.apache.lucene.search.Query;
|
||||
@@ -24,39 +26,58 @@ import java.nio.file.Paths;
|
||||
public class MvSearcher {
|
||||
private IndexReader reader;
|
||||
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 {
|
||||
Path indexPath = Paths.get(indexDirectoryPath);
|
||||
Directory directory = FSDirectory.open(indexPath);
|
||||
reader = DirectoryReader.open(directory);
|
||||
searcher = new IndexSearcher(reader);
|
||||
storedFields = reader.storedFields();
|
||||
}
|
||||
|
||||
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 StandardAnalyzer();
|
||||
QueryParser parser = new QueryParser(field, analyzer);
|
||||
Query query = parser.parse(queryStr);
|
||||
TopDocs docs = searcher.search(query, maxHit);
|
||||
|
||||
topDocsLruCache.put(cacheKey, docs);
|
||||
return docs;
|
||||
}
|
||||
|
||||
public void search(String field, String queryStr) throws Exception {
|
||||
Analyzer analyzer = new SmartChineseAnalyzer();
|
||||
// Analyzer analyzer = new StandardAnalyzer();
|
||||
// Analyzer analyzer = new StandardAnalyzer();
|
||||
QueryParser parser = new QueryParser(field, analyzer);
|
||||
Query query = parser.parse(queryStr);
|
||||
TopDocs docs = searcher.search(query, 200);
|
||||
|
||||
// 处理搜索结果
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public Document getDocument(int docID) throws IOException {
|
||||
Document document = searcher.doc(docID);
|
||||
public Document getDocument(int docId) throws IOException {
|
||||
Document document = documentLruCache.get(docId);
|
||||
if (document != null) {
|
||||
return document;
|
||||
}
|
||||
document = storedFields.document(docId);
|
||||
if (document != null) {
|
||||
documentLruCache.put(docId, 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.MvSearcher;
|
||||
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.Field;
|
||||
import org.apache.lucene.document.StringField;
|
||||
@@ -15,14 +18,10 @@ import org.apache.lucene.search.ScoreDoc;
|
||||
import org.apache.lucene.search.TopDocs;
|
||||
import org.slf4j.Logger;
|
||||
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.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
@@ -34,16 +33,16 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
* @author admin
|
||||
* @since 2023/6/10 17:35
|
||||
*/
|
||||
@Service
|
||||
public class MvService implements InitializingBean {
|
||||
public class MvService {
|
||||
private static final Logger logger = LoggerFactory.getLogger(MvService.class);
|
||||
|
||||
private static final String indexDirectoryPath = "index";
|
||||
private static final String MV_FILE = "tvbox/16wMV.txt";
|
||||
|
||||
private MvSearcher mvSearcher;
|
||||
|
||||
public MvResult search(String query, int max) throws Exception {
|
||||
if (!StringUtils.hasText(query)) {
|
||||
if (StringUtils.isEmpty(query) || mvSearcher == null) {
|
||||
return new MvResult();
|
||||
}
|
||||
|
||||
@@ -55,7 +54,7 @@ public class MvService implements InitializingBean {
|
||||
MvResult result = new MvResult();
|
||||
result.setQuery(query);
|
||||
result.setTotalHits(topDocs.totalHits.value);
|
||||
result.setList(new LinkedList<>());
|
||||
result.setList(new ArrayList<>(topDocs.scoreDocs.length));
|
||||
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
|
||||
Document document = mvSearcher.getDocument(scoreDoc.doc);
|
||||
if (document == null) {
|
||||
@@ -66,8 +65,9 @@ public class MvService implements InitializingBean {
|
||||
String songName = name;
|
||||
String songUser = null;
|
||||
if (name.contains("-")) {
|
||||
songUser = name.split("-", 2)[0];
|
||||
songName = name.split("-", 2)[1];
|
||||
String[] split = name.split("-", 2);
|
||||
songUser = split[0];
|
||||
songName = split[1];
|
||||
}
|
||||
String url = document.get("url");
|
||||
if (!url.startsWith("http")) {
|
||||
@@ -96,12 +96,13 @@ public class MvService implements InitializingBean {
|
||||
vod.setVodId(wd);
|
||||
vod.setVodName(wd);
|
||||
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<>();
|
||||
Set<String> vodActorList = new LinkedHashSet<>();
|
||||
for (MvContent content : search.getList()) {
|
||||
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());
|
||||
}
|
||||
}
|
||||
@@ -115,8 +116,8 @@ public class MvService implements InitializingBean {
|
||||
return vodResult;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
public void initIndex() throws Exception {
|
||||
|
||||
// 重建索引
|
||||
String indexAbsolutePath = new File(indexDirectoryPath).getAbsoluteFile().getAbsolutePath();
|
||||
reBuildIndex(indexAbsolutePath);
|
||||
@@ -130,13 +131,22 @@ public class MvService implements InitializingBean {
|
||||
|
||||
|
||||
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();
|
||||
logger.info("重建索引中....");
|
||||
|
||||
// 清空以前的索引
|
||||
stopWatch.start("清空以前索引");
|
||||
logger.info("清空历史索引....");
|
||||
File file = new File(indexDirectoryPath).getAbsoluteFile();
|
||||
|
||||
if (file.isDirectory()) {
|
||||
File[] files = file.listFiles();
|
||||
for (File file1 : files) {
|
||||
@@ -152,7 +162,7 @@ public class MvService implements InitializingBean {
|
||||
logger.info("创建索引中....");
|
||||
AtomicInteger line = new AtomicInteger();
|
||||
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("-"))
|
||||
.forEach(l -> {
|
||||
@@ -182,6 +192,7 @@ public class MvService implements InitializingBean {
|
||||
}
|
||||
});
|
||||
mvIndex.close();
|
||||
mvFileSizeTxt.createNewFile();
|
||||
logger.info("创建索引中....完成, 总共{}条", line.get());
|
||||
stopWatch.stop();
|
||||
logger.info("重建索引中....完成,耗时 {} 毫秒, 索引位置:{}", stopWatch.getTotalTimeMillis(), file.getPath());
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.leosam.tvbox.mv.utils;
|
||||
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* @author admin
|
||||
@@ -14,19 +14,33 @@ import java.util.Properties;
|
||||
*/
|
||||
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) {
|
||||
try {
|
||||
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;
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static BufferedReader getBufferedReader(String path) {
|
||||
try {
|
||||
ClassPathResource resource = new ClassPathResource(path);
|
||||
|
||||
|
||||
InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream(),StandardCharsets.UTF_8);
|
||||
BufferedReader reader = new BufferedReader(inputStreamReader);
|
||||
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) {
|
||||
StringBuilder content = new StringBuilder();
|
||||
@@ -70,5 +73,52 @@ public class ClassPathReaderUtils {
|
||||
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 static int toInt(final String str, final int defaultValue) {
|
||||
if (str == null) {
|
||||
if (str == null || str.length() == 0) {
|
||||
return defaultValue;
|
||||
}
|
||||
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