Java Spring несколько узлов класса

Я новичок в Spring, и мой вопрос довольно простой, но я думаю, что не могу найти ни одного хорошего ресурса. Я просмотрел примеры для начинающих (например, это, это и некоторые другие) и искал ответы в StackOverflow, но я не совсем уверен, что мне нужно искать.

Позвольте мне объяснить сценарий. Скажем, у меня есть центральный узел (C) и несколько внутренних узлов (I_1, ..., I_n), и этот случай:

I_1  
.
.    ------------------> C
.
I_n

На этом очень простом рисунке я пытаюсь проиллюстрировать, что каждый I_i отправляет что-то в C, когда C просит об этом. Вот и все. Теперь я хочу, чтобы у каждого I_i был специальный идентификатор, и они отправляют этот идентификатор в C. Как мне смоделировать это в Spring? На данный момент у меня есть базовая настройка

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

И у меня есть контроллер

@RestController
public class Controller {

    @RequestMapping(value = "/i1/{id}", method = RequestMethod.GET)
    @ResponseBody
    public String i1(
        @PathVariable("id") String id) {
        return id;
    }
}

Так что, если я запустил этот код и скрутил его до http: // локальный: порт / i1 / 560, он вернет 560. Я, конечно, могу создать несколько узлов этого кода, например, создав файл jar и запустив его на разных портах. Проблема в том, что я не могу дать им уникальные идентификаторы. Я имею в виду, что все они являются экземпляром приложения. Я бы хотел, чтобы они относились к классу узлов ниже (или что-то подобное):

class node{
    private int id;

    public node(int id){
        this.id = id;
    }
}

Так что у меня будет n внутренних узлов. А затем я могу открыть терминал и скрутить каждого из них, чтобы получить их идентификатор. Надеюсь, я достаточно хорошо объяснил. Вкратце: моя цель - иметь n экземпляров класса узла с уникальным идентификатором. И я хочу скрутить их по отдельности и получить их идентификаторы, например «curl http: // локальный: 8081 / i1» вернет идентификатор i1, а «curl http: // локальный: 8082 / i2» вернет идентификатор i2 и так далее. Я даже не уверен, какие ключевые слова использовать при поиске. Я пробовал «создать несколько клиентов / хостов / приложений», но на самом деле не нашел нужного, поэтому я даже был бы признателен за ответ, который содержит только это.

Бобы

Я прочитал этот пример, который на самом деле не использует контроллер, но использует beans. Я пробовал этот подход, и это похоже на то, что я хочу сделать, он может создавать несколько узловых объектов, все с уникальным идентификатором. Однако я не уверен, смогу ли я подключить каждый из них к разным узлам и портам.

Итак, вы хотите, чтобы один исполняемый файл работал с разными конфигурациями (портами)?

jAC 14.05.2018 15:37

@jAC Да, наверное. Чтобы уточнить, прямо сейчас у меня есть части приложения и контроллера. Я создаю JAR-файл с этим кодом. Затем я запускаю его несколько раз с разными портами, используя java -Dserver.port = <port> -jar <file>. И я хочу, чтобы это было так, если возможно. Таким образом я получаю несколько узлов на разных портах.

hokosha 14.05.2018 15:45

Хорошо, и каждый узел должен прослушивать отдельный порт или все это должно работать в одном экземпляре?

jAC 14.05.2018 15:55

@jAC каждый узел должен прослушивать отдельные порты. Если я запустил файл jar четыре раза, как я писал выше, на портах 8080, ..., 8083, я создам 4 узла. Я хочу, чтобы это были I_1, ..., I_4. Поэтому, когда я скручиваю http: // (...) / I1, I1 ответит своим идентификатором и так далее. Так что я могу собрать все их идентификаторы, скручивая их.

hokosha 14.05.2018 15:59

Какие-либо ограничения на идентификатор узла?

Jan Larsen 14.05.2018 16:02

@ Ян Ларсен, не совсем. ID был просто примером. Это может быть что угодно, возможно, даже что угодно из таблицы ASCII. Он должен быть отправлен из I_i в C, но я могу просто преобразовать его в какой-то формат, который легко отправить.

hokosha 14.05.2018 16:07
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
6
633
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Принимая ваш вопрос за чистую монету, проще всего было бы создать компоненты узлов, используя «прототип» @Scope (чтобы они не были одиночными, если вы добавите еще один позже), затем один @Autowire на ваш контроллер, затем используйте UUID для идентификатора, чтобы он всегда был уникальным и просто установите его при создании узла:

private UUID id = UUID.randomUUID();

с геттером. Затем контроллер может получить идентификатор от своего собственного узла.

Вы имеете в виду что-то вроде это? Как мне убедиться, что они работают на разных портах?

hokosha 14.05.2018 16:33
Ответ принят как подходящий

Итак, я думаю, что ваше основное требование довольно легко выполнить. Но все же есть вопросы по индексу ваших узлов I_x. Почему они вообще имеют значение? Если у вас есть порт и идентификатор вашего узла, этого достаточно для идентификации узла. Итак, я создал ответ со следующими двумя свойствами:

  • порт
  • Я БЫ

Следуя указанным выше ограничениям, вы не можете создать Controller, который прослушивает определенное отображение I_x. Но, как я понимаю, в этом нет особой необходимости.

Создайте класс NodeInformation, содержащий значения:

@Getter
@Setter
public class NodeInformation {
    private int port;
    private int id;


    public NodeInformation(int port, int id) {
        this.port = port;
        this.id = id;
    }
}

@Getter и @Setter - это аннотации org.projectlombok, которые автоматически создают сеттер и получатель.

Затем введите необходимую информацию, проанализировав вашу конфигурацию. Эта конфигурация может быть установлена:

  • application.properties
  • передача аргументов (-Dnode.port=xy-Dnode.id=myid)

ВНИМАНИЕ: В качестве альтернативы вы можете использовать свойство пружины server.port, которое автоматически устанавливает порт.

Итак, заполнив информацию в вашем NodeInformation, вы должны использовать @ConfigurationNodeInformationConfiguration, который собирает и возвращает ваш Bean:

@Configuration
public class NodeInformationConfiguration {

    private final int port;
    private final int id;

    public NodeInformationConfiguration(@Value("${node.port}") int port, @Value("${node.id}") int id) {
        this.port = port;
        this.id = id;
    }

    @Bean
    public NodeInformation getNodeInfo() {
        return new NodeInformation(port, id);
    }
}

Итак, в конце вы должны установить свой порт и создать контроллер, который возвращает ваш идентификатор.

Настройка порта

Вы можете настроить свой порт с помощью EmbeddedServletContainerCustomizer. Используйте NodeInformation, который мы ранее создали, автоматически подключив его к вашему классу PortSetter.

@Component
public class PortSetter {


    private final int port;

    @Autowired
    public PortConfiguration(NodeInformation nodeInformation) {
        this.port = nodeInformation.getPort();
    }

    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer() {
        return (container -> {
            container.setPort(port);
        });
    }
}

И, наконец, создайте простой RestController, который возвращает идентификатор вашего набора, прослушивая /id:

@RestController
public class NodeController {

    private final NodeInformation nodeInformation;

    @Autowired
    public NodeController(NodeInformation nodeInformation) {
        this.nodeInformation = nodeInformation;
    }

    @RequestMapping("/id")
    public int getNodeId() {
        return this.nodeInformation.getId();
    }
}

Другие вопросы по теме