diff --git a/README-zh.md b/README-zh.md index 2bc0700..97cb8a1 100644 --- a/README-zh.md +++ b/README-zh.md @@ -6,25 +6,23 @@ ## 文档 - [如何自定义内容](docs/howToCustom-zh.md) - [代码贡献](docs/CONTRIBUTING-zh.md) - +- [常见问题](docs/faq-zh.md) + ## 代码结构 这是一个源自于 Spring Initializr 构建的云原生应用脚手架项目,你可以直接体验该项目的功能通过 [start.aliyun.com](https://start.aliyun.com/) ,项目本身包含以下模块: * initializer-generator: 脚手架生成项目模块,在其中`io.spring.start.site`目录下引用了部分 [start.spring.io](https://start.spring.io/) 的基础代码。 * initializer-page: 脚手架前端页面 +* initializer-start: 脚手架启动、打包入口模块 ## 基于源代码运行 请在本地 clone 该项目,并确保具备 Java 17 环境。 ### 构建项目 - -首先,确保 python 在您的环境中已经安装。在项目根目录,执行以下命令,安装 Node 和 Yarn: +由于前端是以源码的形式存储与本项目中,需要使用yarn进行编译后,成为当前项目的资源文件,才能被正确访问: ```shell -mvn compile -P install-yarn -``` -在项目根目录,执行以下命令,将静态文件 Copy 到 `initializer-generator` 模块的 target 中: -```shell -mvn prepare-package +mvn process-sources ``` +此步骤执行后,编译后的前端文件,会被复制到 `initializer-page/target/classes/static` 目录下 ### 启动项目 进入`initializer-generator` 模块,执行以下命令启动应用: diff --git a/docs/faq-zh.md b/docs/faq-zh.md new file mode 100644 index 0000000..d8b3acf --- /dev/null +++ b/docs/faq-zh.md @@ -0,0 +1,7 @@ +# 常见问题 + +## MAC 系统前端无法编译 +对于使用了 Arm 架构(即使用了 M1、M2 处理器)的 Mac 电脑,由于 node 安装包没有适配 Arm 架构的 release 包,需要通过环境变量的方式让 Maven 认为在 x64 系统下运行: +```bash +mvn clean package -Dos.arch=x64 +``` \ No newline at end of file diff --git a/initializer-generator/src/main/java/com/alibaba/initializer/core/template/loader/ClasspathTemplateLoader.java b/initializer-generator/src/main/java/com/alibaba/initializer/core/template/loader/ClasspathTemplateLoader.java index 17fc2fe..803a8c4 100644 --- a/initializer-generator/src/main/java/com/alibaba/initializer/core/template/loader/ClasspathTemplateLoader.java +++ b/initializer-generator/src/main/java/com/alibaba/initializer/core/template/loader/ClasspathTemplateLoader.java @@ -16,45 +16,27 @@ package com.alibaba.initializer.core.template.loader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.net.URI; -import java.net.URL; -import java.nio.file.FileVisitOption; -import java.nio.file.FileVisitResult; -import java.nio.file.FileVisitor; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.Arrays; -import java.util.Collection; -import java.util.EnumSet; -import java.util.Enumeration; -import java.util.List; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; -import java.util.stream.Collectors; - import com.alibaba.initializer.core.constants.ErrorCodeEnum; import com.alibaba.initializer.core.exception.BizRuntimeException; import com.alibaba.initializer.core.template.CodeTemplate; import com.alibaba.initializer.core.template.CodeTemplateRepo; import com.alibaba.initializer.core.template.CodeTemplateRepoLoader; -import com.google.common.collect.Lists; -import lombok.SneakyThrows; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.core.io.Resource; -import org.springframework.util.ResourceUtils; - import static org.springframework.util.ResourceUtils.JAR_URL_SEPARATOR; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.net.URI; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + /** * load template file from classpath * @@ -72,12 +54,13 @@ public class ClasspathTemplateLoader implements CodeTemplateRepoLoader { try { URI uri = new URI(uriStr); - Resource[] resources = resourceLoader.getResources(CLASSPAHT_PREFIX + uri.getPath()); + Path rootPath = Paths.get(uri.getPath()); + + Resource[] resources = resourceLoader.getResources(CLASSPAHT_PREFIX + rootPath + "/**"); List templates = Arrays.stream(resources) - .filter(Resource::exists) - .map(this::scanTemplte) - .flatMap(Collection::stream) + .filter(Resource::isReadable) + .map(item -> toTemplate(item, rootPath)) .collect(Collectors.toList()); return new CodeTemplateRepo(uri, templates); @@ -86,99 +69,23 @@ public class ClasspathTemplateLoader implements CodeTemplateRepoLoader { } } - @SneakyThrows - private List scanTemplte(Resource resource) { - List templates = Lists.newArrayList(); + private CodeTemplate toTemplate(Resource resource, Path scanRootPath) { - URL url = resource.getURL(); + try { + URL url = resource.getURL(); - if (ResourceUtils.isFileURL(url)) { - visitFileSystem(templates::add, resource); - } else if (ResourceUtils.isJarURL(url)) { - visitJarSystem(templates::add, resource); - } + String urlFile = url.getFile(); - return templates; - } + int separatorIndex = urlFile.lastIndexOf(JAR_URL_SEPARATOR); - private void visitFileSystem(TempFileVisitor visitor, Resource resource) - throws IOException { - if (!resource.isFile()) { - return; - } - File rootFile = resource.getFile(); - Path scanRoot = Paths.get(rootFile.getAbsolutePath()); - Files.walkFileTree(scanRoot, EnumSet.of(FileVisitOption.FOLLOW_LINKS), - Integer.MAX_VALUE, new FileVisitor() { - @Override - public FileVisitResult preVisitDirectory(Path dir, - BasicFileAttributes attrs) { - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile(Path originPath, - BasicFileAttributes attrs) { - String fileName = originPath.getFileName().toString(); - - Path relativePath = originPath.subpath(scanRoot.getNameCount(), - originPath.getNameCount()); - Path relativeFolderPath = relativePath.getNameCount() == 1 - ? null - : relativePath.subpath(0, - relativePath.getNameCount() - 1); - - visitor.visit(new CodeTemplate(relativeFolderPath, fileName) { - @Override - public Reader getReader() { - try { - return new FileReader(originPath.toFile()); - } catch (FileNotFoundException e) { - throw new BizRuntimeException(ErrorCodeEnum.SYSTEM_ERROR, "", e); - } - } - } - ); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) { - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) { - return FileVisitResult.CONTINUE; - } - }); - } - - private void visitJarSystem(TempFileVisitor visitor, Resource resource) throws IOException { - URL url = resource.getURL(); - - URL jarUrl = ResourceUtils.extractJarFileURL(url); - - JarFile jarFile = new JarFile(jarUrl.getFile()); - - Enumeration entries = jarFile.entries(); - - String resourcePath = url.getFile(); - - // the scan root from jar file - String scanRoot = resourcePath.substring(resourcePath.indexOf(JAR_URL_SEPARATOR) + JAR_URL_SEPARATOR.length()); - Path scanRootPath = Paths.get(scanRoot); - - while (entries.hasMoreElements()) { - JarEntry entry = entries.nextElement(); - - // the full name of jar entry - String entryName = entry.getName(); - if (!entryName.startsWith(scanRoot) || entry.isDirectory()) { - continue; + if (separatorIndex > -1) { + urlFile = urlFile.substring(separatorIndex + 1); + } else { + String classpathPath = ClasspathTemplateLoader.class.getProtectionDomain().getCodeSource().getLocation().getPath(); + urlFile = urlFile.startsWith(classpathPath) ? urlFile.replace(classpathPath, "/") : urlFile; } - Path entryPath = Paths.get(entryName); + Path entryPath = Paths.get(urlFile); String fileName = entryPath.getFileName().toString(); Path relativePath = entryPath.subpath(scanRootPath.getNameCount(), entryPath.getNameCount()); @@ -187,25 +94,17 @@ public class ClasspathTemplateLoader implements CodeTemplateRepoLoader { : relativePath.subpath(0, relativePath.getNameCount() - 1); - visitor.visit(new CodeTemplate(relativeFolderPath, fileName) { - @Override - public Reader getReader() { - try { - return new InputStreamReader(resourceLoader.getResource("classpath:/" + entryPath.toString()).getInputStream()); - } catch (IOException e) { - throw new BizRuntimeException(ErrorCodeEnum.SYSTEM_ERROR, "load resource error", e); - } - } - } - ); + return new CodeTemplate(relativeFolderPath, fileName) { + @Override + public Reader getReader() throws IOException { + return new InputStreamReader(resource.getInputStream()); + } + }; + } catch (Exception e) { + throw new RuntimeException(e); } } - @FunctionalInterface - public interface TempFileVisitor { - void visit(CodeTemplate template); - } - @Override public String getProtocol() { return "classpath"; diff --git a/initializer-page/pom.xml b/initializer-page/pom.xml index 145b38e..ffd372b 100644 --- a/initializer-page/pom.xml +++ b/initializer-page/pom.xml @@ -54,7 +54,7 @@ copy-base-web-resource - prepare-package + process-sources copy-resources diff --git a/initializer-start/src/main/java/com/alibaba/initializer/start/web/CommonPages.java b/initializer-start/src/main/java/com/alibaba/initializer/start/web/CommonPages.java deleted file mode 100644 index b9e6278..0000000 --- a/initializer-start/src/main/java/com/alibaba/initializer/start/web/CommonPages.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2022-2023 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.alibaba.initializer.start.web; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.io.ResourceLoader; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.ResponseBody; - -@Controller -public class CommonPages { - - @Autowired - private ResourceLoader resourceLoader; - - @GetMapping({"/checkpreload.htm", "nginx_status"}) - @ResponseBody - public String checkPreload() { - return "success"; - } - -}