Пошаговое руководство на примере швейцарского сыра

Недавно я начал новый Java-проект для вернувшегося клиента. Одной из первых моих задач было реализовать новую функцию с целью сделать приложение глобально настраиваемым с помощью файла свойств JSON.

Получившееся решение мне показалось относительно удобным, и я подумал, что поделюсь им в новом сообщении в блоге. Более того, поскольку я до сих пор не писал никаких сообщений в блогах о Java, мне это показалось довольно сложным и интересным.

Вступление

В этой статье мы собираемся:

  1. Создайте новый проект.
  2. Прочтите файл и свойство JSON.
  3. Создайте перечисление.
  4. Сопоставьте свойства с общим перечислением.

Примечание: если у вас уже есть проект, вы, очевидно, можете пропустить первую главу, в которой цель состоит в создании проекта. Точно так же, если вы не хотите использовать Maven, пропустите и его и включите библиотеку, которую мы собираемся использовать, как того требует ваша установка.

Создать новый проект

Для начала создадим новый проект, используя стартовый набор Maven. Для этого выполните в терминале следующую команду:

$ mvn archetype:generate -DgroupId=com.jsontoenum.app -DartifactId=json-to-enum -DarchetypeArtifactId=maven-archetype-quickstart -DarchetypeVersion=1.4 -DinteractiveMode=false

Если все прошло хорошо, теперь вы можете перейти в каталог, чтобы скомпилировать проект без ошибок:

$ cd json-to-enum/ && mvn package

Прочтите файл и свойство JSON

Сначала я реализовал быстрое индивидуальное решение, но результат меня совсем не удовлетворил. Вот почему я попытался найти готовое решение в Интернете и нашел невероятную библиотеку с открытым исходным кодом com.typesafe.config.

Он использует всю работу по чтению файлов JSON и доступу к их свойствам, не имеет зависимостей и даже совместим с Java 8.

По крайней мере, на этот раз поиск решения в Google был отличной идеей.

Чтобы использовать библиотеку, давайте добавим новую зависимость этой библиотеки в наш pom.xml:

<dependency>
    <groupId>com.typesafe</groupId>
    <artifactId>config</artifactId>
    <version>1.3.4</version>
</dependency>

Более того, мы также должны добавить следующие <resources/> и <plugins/> цели в наш <build/>, чтобы иметь возможность загрузить файл JSON (который мы собираемся создать) и упаковать зависимость, на которую мы только что ссылались, в нашем файле JAR.

<resources>
  <resource>
    <directory>src/resources</directory>
  </resource>
</resources>

<plugins>
  <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-shade-plugin</artifactId>
    <version>3.2.0</version>
    <executions>
      <execution>
        <phase>package</phase>
        <goals>
          <goal>shade</goal>
        </goals>
      </execution>
    </executions>
  </plugin>
</plugins>

Наша сборка наконец-то настроена. Теперь мы можем перейти к следующему шагу и создать наш файл свойств JSON.

По умолчанию библиотека конфигурации попытается загрузить файл с именем application.json в качестве источника свойств.

Поэтому давайте будем простыми и будем использовать это предопределенное имя для создания этого нового файла в новой папке src/resources/ со следующим содержимым JSON:

{
  "swiss": {
    "cheese": "gruyere"
  }
}

Все настроено, время писать код.

Мы могли бы изменить наше приложение (App.java в папке src/main/java/com/jsontoenum/app) для инициализации и загрузки свойств из файла JSON и распечатать название нашего любимого вида сыра.

package com.jsontoenum.app;

import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;

public class App {
   public static void main(String[] args) {
       // Load and init the configuration library
      final Config conf = ConfigFactory.load();

      // Get the value of the JSON property
      final String cheese = conf.getString("swiss.cheese");

      System.out.println(String.format("I like %s 🧀", cheese));
   }
}

Давайте скомпилируем все и запустим наш проект, используя следующую командную строку в терминале, чтобы опробовать нашу реализацию:

$ mvn package && java -cp target/json-to-enum-1.0-SNAPSHOT.jar com.jsontoenum.app.App

Если все прошло нормально, в конце трассировки стека в выводе консоли должно отображаться следующее:

[INFO] -------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -------------------------------------------------------------
[INFO] Total time:  2.179 s
[INFO] Finished at: 2019-08-16T15:04:35+02:00
[INFO] -------------------------------------------------------------
I like gruyere 🧀

Создать Enum

Даже если было уже круто иметь возможность читать свойства JSON, при разработке назначенной мне функции я быстро понял, что возможность сопоставить свойства с enum будет как бы обязательной, если приложение должно вести себя по-другому соответственно.

Кроме того, Швейцария производит более одного вида сыра.

Поэтому в качестве следующего шага мы могли бы создать перечисление в папке src/main/java/com/jsontoenum/app/, в котором можно было бы перечислить пару сыров из франкоязычной части страны:

package com.jsontoenum.app;

public enum Cheese {

   GRUYERE,
   TETE_DE_MOINE,
   CHAUX_DABEL,
   RACLETTE,
   VACHERIN,
   TOMME

}

Сопоставьте свойства с общим перечислением

В этой статье мы используем сыр в демонстрационных целях, но очевидно, что Швейцария экспортирует многие другие продукты, такие как шоколад и часы.

Точно так же приложение, над которым я работаю, не содержит только одного перечисления. Вот почему мы не только добавляем метод для синтаксического анализа свойств одного типа перечисления, но и объявляем его универсальным в нашем приложении (App.java).

private static <E extends Enum<E>> E getEnumProperty(final Config conf, final String key, final Class<E> myClass) {
    // If no config loaded
    if (conf == null) {
        return null;
    }

    // If the config doesn't contains the key
    if (!conf.hasPath(key)) {
        return null;
    }

    // As previously, load the key value
    final String keyValue = conf.getString(key);

    // Does the property has a value
    if (keyValue == null || keyValue.isEmpty()) {
        return null;
    }

    // Map the property to the ENUM
    return Enum.valueOf(myClass, keyValue.toUpperCase());
}

Наконец, для заключительного теста давайте усовершенствуем наш main метод, загрузив перечисление и проверив его, чтобы показать, является ли сыр нашим любимым сыром или нет:

public static void main(String[] args) {
    // Load and init the configuration library
   final Config conf = ConfigFactory.load();

   // Get the value of the JSON property
   final Cheese cheese =
                getEnumProperty(conf, "swiss.cheese", Cheese.class);

   if (Cheese.GRUYERE.equals(cheese)) {
       System.out.println(String.format("I really like %s 🧀", cheese));
   } else {
       System.out.println(String.format("%s is ok", cheese));
   }
}

Вуаля, вот и все, не больше и не меньше.

Вы можете попробовать запустить наш проект, используя предыдущую командную строку, и если все пойдет по плану, результат должен выглядеть так:

[INFO] -------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -------------------------------------------------------------
[INFO] Total time:  2.437 s
[INFO] Finished at: 2019-08-16T15:43:42+02:00
[INFO] -------------------------------------------------------------
I really like GRUYERE 🧀

Вишня на торте 🍒🎂

Если вы хотите избежать хлопот с созданием собственного проекта и копированием приведенного выше кода, я опубликовал проект в Интернете, будь моим гостем.

$ git clone https://github.com/peterpeterparker/json-to-enum.git

До бесконечности и дальше 🚀

Дэйвид