Java语言处理Js文件内容格式化

前言

本文介绍了一个使用Google Closure Compiler库实现JavaScript代码格式化的工具类。主要内容包括:1) 添加Maven依赖配置;2) 提供完整的JSFormatterUtil工具类,包含代码格式化和移除模块标识功能;3) 给出测试示例,展示如何获取网络JS文件并进行格式化处理。该工具能自动将压缩的JS代码转换为标准格式,支持错误检测和异常处理,格式化失败时返回原代码。文中还提示了常见问题,如自动引入错误包的问题解决方法,并对比了格式化前后的代码效果差异。

一、添加依赖

此依赖用作格式化代码使用,也有一些其他功能,暂不清楚,可以自行探索!!!

XML 复制代码
            <dependency>
                <groupId>com.google.javascript</groupId>
                <artifactId>closure-compiler</artifactId>
                <version>v20240317</version>
            </dependency>

二、格式化工具类

注:1. 格式化前会进行内容校验,若文件内容格式错误,会将原代码返回

  1. 一定要看引入的包是否正确,若复制代码时不复制import包,Compiler类会自动给你引入java.lang下面的,此时代码报错(我自己踩坑了,一直自动引入java底下的,巨恶心)
java 复制代码
import com.google.javascript.jscomp.Compiler;
import com.google.javascript.jscomp.*;
import com.google.javascript.jscomp.jarjar.com.google.common.collect.ImmutableMap;

import java.util.List;

/**
 * @program:
 * @create: 2025-10-31 16:18
 */
public class JSFormatterUtil {
    private static final String MODULE_TAG = "'use strict';";

    /**
     * 格式化 JavaScript 代码字符串
     * 注:1. 若校验格式有问题会返回原代码
     * 2. 格式化后会自动添加模块标识,不想要可以手动处理掉
     *
     * @param jsCode 压缩的 JavaScript 代码
     * @return 格式化后的 JavaScript 代码
     */
    public static String format(String jsCode) {
        if (jsCode == null || jsCode.trim().isEmpty()) {
            return jsCode;
        }
        try {
            // 创建编译器实例
            Compiler compiler = new Compiler();
            // 创建编译器选项
            CompilerOptions options = new CompilerOptions();
            // 设置格式化选项 - 美化输出
            options.setPrettyPrint(true);
            options.setPrintInputDelimiter(false);
            // 设置不进行代码优化,只格式化(仅处理空白字符)
            CompilationLevel.WHITESPACE_ONLY.setOptionsForCompilationLevel(options);
            // 获取所有诊断组(高版本兼容方式)
            ImmutableMap<String, DiagnosticGroup> registeredGroups = DiagnosticGroups.getRegisteredGroups();
            registeredGroups.forEach((k, v) -> options.setWarningLevel(v, CheckLevel.OFF));
            // 不输出警告信息
//            options.setWarningLevel(DiagnosticGroups.ALL, CheckLevel.OFF);
            // 创建源代码输入
            SourceFile input = SourceFile.fromCode("input.js", jsCode);
            // 使用默认的外部依赖(标准 JavaScript API)
            List<SourceFile> externs = CommandLineRunner.getBuiltinExterns(CompilerOptions.Environment.BROWSER);
            // 编译(实际只做格式化,不优化)
            Result result = compiler.compile(
                    externs,  // externs - 外部依赖
                    List.of(input),  // inputs - 输入文件
                    options  // options - 编译选项
            );
            // 检查编译是否成功
            if (!result.success) {
                // 如果编译失败,返回原代码
                return jsCode;
            }
            // 获取格式化后的代码
            String formatted = compiler.toSource();
            // 如果格式化失败,返回原代码
            if (formatted == null || formatted.trim().isEmpty()) {
                return jsCode;
            }
            return formatted.trim();
        } catch (Exception e) {
            // 如果出错,返回原代码
            System.err.println("格式化出错: " + e.getMessage());
            e.printStackTrace();
            return jsCode;
        }
    }

    /**
     * 将格式化时自动添加的模块标识去除
     *
     * @param formatContent 格式化好的文件内容
     * @return 去除模板标识的文件内容
     */
    public static String removeModuleTag(String formatContent) {
        // 将模块标识去除
        String moduleTag = JSFormatterUtil.MODULE_TAG;
        if (formatContent.startsWith(moduleTag)) {
            int index = formatContent.indexOf(moduleTag);
            return formatContent.substring(index + moduleTag.length()).trim();
        } else {
            return formatContent;
        }
    }

}

三、测试

此链接可以测试使用,从百度上拿的

java 复制代码
https://pss.bdstatic.com/r/www/cache/static/protocol/https/jquery/jquery-1.10.2.min_65682a2.js
java 复制代码
    @ApiOperation("测试")
    @GetMapping("/test")
    public void test(String jsUrl, HttpServletResponse response) {
        // 通过jsUrl发送请求获取文件内容,若您的文件是本地文件可以直接读取本地文件,拿到内容就行
        String content = restTemplate.get(jsUrl);
        // 将文件内容传入工具类,进行格式化
        // 格式化后会自动添加一个模块标识,可以根据自己需要是否进行保留
        String formatContent = JSFormatterUtil.format(content);
        // 将模块标识去除
        String finalContent = JSFormatterUtil.removeModuleTag(formatContent);
        // 此时文件内容就处理好了,后面可以根据自己需要进行处理
        {// 将文件保存到本地
            String filePath = "C:\\Users\\marun\\Desktop\\临时文件\\格式化后的JS文件" + System.currentTimeMillis() + ".js";
            try (FileWriter writer = new FileWriter(filePath, true)) {
                writer.write(finalContent);
                System.out.println("内容已成功追加到文件。");
            } catch (IOException e) {
                System.err.println("写入文件时出错: " + e.getMessage());
            }
        }
        {// 以文件形式返回
            byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
            // 1. 设置响应头
            response.setContentType("application/javascript; charset=UTF-8");
            // 强制浏览器下载:attachment,不强制浏览器下载:inline
            response.setHeader("Content-Disposition", "attachment; filename=\"p_im-index.js\"");
            response.setContentLength(bytes.length);
            // 2. 写入响应流
            try (OutputStream os = response.getOutputStream()) {
                os.write(bytes);
                os.flush();
            } catch (Exception e) {
                throw new IYuanMessageException("文件写入失败");
            }
        }
    }

四、格式化前后示例

1. 格式化前:放到idea上面就是一行数据

2. 格式化后:格式清晰

相关推荐
“负拾捌”5 小时前
基于NodeJs实现一个MCP客户端(会话模式和无会话模式)
javascript·ai·node.js·大模型·mcp
蒜香拿铁5 小时前
Angular【基础语法】
前端·javascript·angular.js
为什么要做囚徒6 小时前
IntelliJ IDEA 远程断点调试完全指南
java·ide·intellij-idea
探索宇宙真理.6 小时前
Apache Tomcat RewriteValve目录遍历漏洞 | CVE-2025-55752 复现
java·经验分享·tomcat·apache·安全漏洞
元直数字电路验证6 小时前
ASP.NET Core Web APP(MVC)开发中无法全局配置 NuGet 包,该怎么解?
前端·javascript·ui·docker·asp.net·.net
Boilermaker19926 小时前
【Redis】集群与分布式缓存
java·数据库·redis·1024程序员节
YC运维6 小时前
Kubernetes资源管理全解析
java·容器·kubernetes
rexling17 小时前
【Spring Boot】Spring Boot解决循环依赖
java·前端·spring boot