You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java如何从Maven项目resources目录的JSON数组文件中获取随机元素

实现方案

核心思路很简单:两个JSON文件合计2w多条字符串,全加载到内存也就占几MB空间,完全没必要每次API请求都去读文件做解析,服务启动时一次性把姓名数组加载到内存缓存,后续生成随机人物时直接从内存列表随机取元素赋值即可,性能最高。

  • 第一步:编写启动预加载组件,加载类路径下的JSON文件
    Maven项目src/main/resources目录下的文件会被打包到类路径根目录,必须用类加载器以流的方式读取,不要硬写src/main/resources/xxx.json这类本地文件路径,否则项目打包成jar部署后会报文件找不到的错误。
    以SpringBoot环境(自带Jackson JSON解析库)为例,写一个单例组件在启动时完成文件加载:

    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.stereotype.Component;
    import jakarta.annotation.PostConstruct;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.ThreadLocalRandom;
    
    @Component
    public class NameCache {
        private List<String> firstNames;
        private List<String> lastNames;
        private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    
        // Bean初始化完成后自动执行该方法加载文件
        @PostConstruct
        private void loadNameData() throws Exception {
            // 加载名数据
            try (InputStream firstNameIs = getClass().getClassLoader().getResourceAsStream("first-names.json")) {
                JsonNode firstNameNode = OBJECT_MAPPER.readTree(firstNameIs);
                firstNames = OBJECT_MAPPER.convertValue(firstNameNode.get("first_names"),
                        OBJECT_MAPPER.getTypeFactory().constructCollectionType(ArrayList.class, String.class));
            }
            // 加载姓数据
            try (InputStream lastNameIs = getClass().getClassLoader().getResourceAsStream("last-names.json")) {
                JsonNode lastNameNode = OBJECT_MAPPER.readTree(lastNameIs);
                lastNames = OBJECT_MAPPER.convertValue(lastNameNode.get("last_names"),
                        OBJECT_MAPPER.getTypeFactory().constructCollectionType(ArrayList.class, String.class));
            }
        }
    
        // 对外暴露随机取姓名的方法
        public String getRandomFirstName() {
            return firstNames.get(ThreadLocalRandom.current().nextInt(firstNames.size()));
        }
    
        public String getRandomLastName() {
            return lastNames.get(ThreadLocalRandom.current().nextInt(lastNames.size()));
        }
    }
    

    如果你用的是非Spring的普通Maven项目,把这个类改成饿汉单例模式,在私有构造方法里执行loadNameData()逻辑即可;如果用Gson、Fastjson2等其他JSON库,替换掉JSON解析部分的代码就行,核心逻辑不变。这里用ThreadLocalRandom代替普通Random,高并发场景下不会出现种子竞争的性能问题,普通并发量下用Random也完全没问题。

  • 第二步:生成Person对象时直接从缓存取随机值赋值
    在你的业务逻辑层注入上面的缓存组件,生成随机人物时直接调用方法赋值即可:

    @Service
    public class PersonGenerateService {
        @Resource
        private NameCache nameCache;
    
        public Person getRandomPerson() {
            Person person = new Person();
            person.setFirstName(nameCache.getRandomFirstName());
            person.setLastName(nameCache.getRandomLastName());
            // 其余随机属性按相同逻辑生成赋值即可
            return person;
        }
    }
    
  • 避坑提醒

    • 不要每次接口请求都重新读取、解析JSON文件,频繁IO加JSON解析会把接口响应速度拉低几个数量级,完全没有必要。
    • 读取resources下的文件必须用类加载器的getResourceAsStream()方法,不要用本地文件路径读取,否则打包部署后100%找不到文件。
    • 随机取下标时不要硬编码数组长度,用列表的size()方法动态获取,后续你往JSON文件里增删姓名数据不需要改代码。

项目结构截图

内容的提问来源于stack exchange,提问作者cantcode4mylife

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 21:06:22