Skip to content

1.9.1. дополнение к расширению

Чтобы улучшить ваш JsonSaveHandler, мы можем сделать его более гибким при обработке входящих данных. Вместо того, чтобы жестко полагаться только на наличие полей name и message, мы можем анализировать любые другие переданные поля и определять, нужно ли сохранять данные только в PostgreSQL, MongoDB или в обе базы данных. Вот что можно сделать:

1. Анализ содержимого JSON и сохранение в нужную базу

Мы можем реализовать логику проверки содержимого JSON и сохранять объект в MongoDB, если он содержит дополнительные поля, не предусмотренные в PostgreSQL. Если объект содержит только те поля, которые соответствуют структуре PostgreSQL (name и message), он будет сохранен только в PostgreSQL.

2. Логика: определение подходящего хранилища

  • Если JSON содержит только поля name и message, он будет сохранен в PostgreSQL.
  • Если JSON содержит дополнительные поля, то данные будут сохранены в MongoDB.
  • Если JSON содержит name, message и другие поля, то данные могут быть сохранены в обе базы.

Пример улучшенного JsonSaveHandler:

package com.example.websocket8_4.handler;

import com.example.websocket8_4.model.UserData;
import com.example.websocket8_4.model.JsonData;
import com.example.websocket8_4.repository.UserDataRepository;
import com.example.websocket8_4.repository.JsonDataRepository;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.reactive.socket.WebSocketHandler;
import org.springframework.web.reactive.socket.WebSocketSession;
import reactor.core.publisher.Mono;

import java.util.Iterator;
import java.util.Map;

@Controller
public class JsonSaveHandler implements WebSocketHandler {

    @Autowired
    private UserDataRepository userDataRepository;

    @Autowired
    private JsonDataRepository jsonDataRepository;

    @Override
    public Mono<Void> handle(WebSocketSession session) {
        return session.receive()
                .map(msg -> msg.getPayloadAsText())
                .flatMap(this::saveJsonToDatabase)
                .flatMap(result -> session.send(Mono.just(session.textMessage(result))))
                .then();
    }

    private Mono<String> saveJsonToDatabase(String jsonString) {
        try {
            // Парсинг JSON строки
            ObjectMapper mapper = new ObjectMapper();
            JsonNode jsonNode = mapper.readTree(jsonString);

            boolean hasName = jsonNode.has("name");
            boolean hasMessage = jsonNode.has("message");
            boolean hasAdditionalFields = hasOtherFields(jsonNode);

            // Логика сохранения
            if (hasName && hasMessage && !hasAdditionalFields) {
                // Сохраняем только в PostgreSQL
                return saveToPostgres(jsonNode);
            } else if (hasAdditionalFields && (!hasName || !hasMessage)) {
                // Сохраняем только в MongoDB
                return saveToMongo(jsonNode);
            } else if (hasName && hasMessage && hasAdditionalFields) {
                // Сохраняем в обе базы данных
                return saveToPostgres(jsonNode)
                        .then(saveToMongo(jsonNode));
            } else {
                return Mono.just("Json Save: Error: JSON does not contain valid fields for saving.");
            }
        } catch (Exception e) {
            return Mono.just("Json Save: Invalid JSON format: " + e.getMessage());
        }
    }

    // Метод для проверки на дополнительные поля (помимо name и message)
    private boolean hasOtherFields(JsonNode jsonNode) {
        Iterator<String> fieldNames = jsonNode.fieldNames();
        while (fieldNames.hasNext()) {
            String fieldName = fieldNames.next();
            if (!fieldName.equals("name") && !fieldName.equals("message")) {
                return true;
            }
        }
        return false;
    }

    // Метод для сохранения в PostgreSQL
    private Mono<String> saveToPostgres(JsonNode jsonNode) {
        String name = jsonNode.get("name").asText();
        String message = jsonNode.get("message").asText();

        UserData userData = new UserData();
        userData.setName(name);
        userData.setMessage(message);

        return userDataRepository.save(userData)
                .map(saved -> "PostgreSQL Save: Success, ID: " + saved.getId())
                .onErrorResume(e -> Mono.just("PostgreSQL Save: Error: " + e.getMessage()));
    }

    // Метод для сохранения в MongoDB
    private Mono<String> saveToMongo(JsonNode jsonNode) {
        Map<String, Object> jsonDataMap = new ObjectMapper().convertValue(jsonNode, Map.class);
        JsonData jsonData = new JsonData();
        jsonData.setData(jsonDataMap);

        return jsonDataRepository.save(jsonData)
                .map(saved -> "MongoDB Save: Success, MongoDB ID: " + saved.getId())
                .onErrorResume(e -> Mono.just("MongoDB Save: Error: " + e.getMessage()));
    }
}

Описание изменений:

  1. Метод hasOtherFields():
  2. Проверяет, есть ли в JSON другие поля, помимо name и message. Если есть — объект сохраняется в MongoDB.

  3. Метод saveToPostgres():

  4. Сохраняет объект только в PostgreSQL, если в JSON есть только поля name и message.

  5. Метод saveToMongo():

  6. Сохраняет весь объект в MongoDB, если есть дополнительные поля.

  7. Основная логика сохранения:

  8. Если в JSON только name и message, объект сохраняется только в PostgreSQL.
  9. Если есть другие поля, то объект сохраняется в MongoDB.
  10. Если в JSON есть и name, и message, и дополнительные поля, объект сохраняется в обе базы данных.

Вывод:

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