2017-01-05 24 views
8

Buduję usługę internetową, która musi przełączać się między dwoma zestawami właściwości w zależności od adresu URL żądania. Nie jestem pewien, która z metod jest najlepsza.Jak zarządzać dwoma zestawami właściwości w czasie wykonywania?

Mam aplikację Spring Boot, która ma plik właściwości yaml. Wewnątrz pliku właściwości struktura wygląda mniej więcej tak;

optionA: 
    foo: 
    urls: 
     - a 
     - b 
    bar: 
    something: hello 

optionB: 
    foo: 
    urls: 
     - x 
     - y 
    bar: 
    something: bye 

Zarówno optionA i optionB dość dużo te same właściwości, tylko różne wartości.

W związku z tym wniosek przychodzi, sprawdzam żądanie i decyduję, czy potrzebuję opcji A, czy opcji B.

Próbowałem uzyskać @ConfigurationProperties, aby obsłużyć to, ale właściwości są inicjalizowane przy starcie, więc nie może być dynamiczne. Inną możliwością jest to, że mam dwie klasy konfiguracji, po jednej dla każdej opcji, ale potem mój kod jest pełen czeków, aby przełączać się między dwiema klasami, a klasy są prawie identyczne, niezbyt ładne.

Wszelkie najlepsze praktyki lub zalecenia dotyczące najlepszego sposobu zarządzania tym byłoby docenione, okrzyki!

Odpowiedz

1

Jeśli nie masz zbyt wiele opcji pójdę w ten sposób: (po prostu się przykład z mniejszą config)

opcji.yml:

optionA: 
    name: optionA 
optionB: 
    name: optionB 

Stworzyłem klasę Opcja rozszerzenia:

public class Option { 

    private String name; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 
} 

I dwie klasy opcji gdzie @ConfigurationProperties są ustawione uzyskiwanie: (na razie te zajęcia są puste, ale trzeba możliwość dokładniejszego określenia każdej innej opcji)

@Component 
@ConfigurationProperties(prefix ="optionA", locations = "classpath:options.yml") 
public class OptionA extends Option{ 
} 
@Component 
@ConfigurationProperties(prefix ="optionB", locations = "classpath:options.yml") 
public class OptionB extends Option{ 
} 

na decyzję różnych opcji I stworzył interface:

public interface OptionService { 

    Option findOption(boolean businessLogic); 
} 

I w realizacji I wstrzyknąć obie opcje i realizację logiki biznesowej: (w prosty sposób)

@Service 
public class OptionServiceImpl implements OptionService { 

    private OptionA optionA; 
    private OptionB optionB; 

    @Override 
    public Option findOption(boolean businessLogic) { 
     if(businessLogic){ 
      return getOptionA(); 
     } else { 
      return getOptionB(); 
     } 
    } 

    public OptionA getOptionA() { 
     return optionA; 
    } 

    @Autowired 
    public void setOptionA(OptionA optionA) { 
     this.optionA = optionA; 
    } 

    public OptionB getOptionB() { 
     return optionB; 
    } 

    @Autowired 
    public void setOptionB(OptionB optionB) { 
     this.optionB = optionB; 
    } 
} 

I na koniec twój kontroler po prostu zadzwoń do klasy OptionServiceImpl i sprawdź, której opcji należy użyć:

@Controller 
public class YourController { 

    private OptionService optionServiceImpl; 

    @RequestMapping("/") 
    public String getIndex(){ 
     Option option = getOptionServiceImpl().findOption(true); 
     System.out.println(option.getName()); 
     option = getOptionServiceImpl().findOption(false); 
     System.out.println(option.getName()); 

     return "Hello World"; 
    } 

    public OptionService getOptionServiceImpl() { 
     return optionServiceImpl; 
    } 

    @Autowired 
    public void setOptionServiceImpl(OptionService optionServiceImpl) { 
     this.optionServiceImpl = optionServiceImpl; 
    } 
} 

Wyjście System.out.println:

optionA 
optionB 

Więc logika biznesowa zdecydować, która opcja powinna być używana, jeśli nie jest - inny konstrukt. Jesteś w stanie stworzyć zasady decyzyjne w interfejsie i jego implementacji. Myślę, że jesteś w stanie stworzyć więcej reguł dla większej liczby kontrolerów.

+0

Dzięki, to to w zasadzie to, co zaimplementowałem przed wysłaniem, czuję się trochę hackem z pustymi opisanymi klasami, ale działa tak, że nie będę marnował więcej czasu na tej haha – pquill

0

Można zdefiniować pary wartości kluczy w pliku application.properties.

gdzie kluczem jest nazwa usługi internetowej i wartość opcji (lista właściwości)

użycie Marka @ConfigurationProperties

@ConfigurationProperties 
class Configuration { 

    Map<String,Option> options; 

    // getters and setters 
} 

@Component 
class ChooseServiceBasedConfiguration { 

    @Autowired 
    Configuration configuration; 

    public void serviceMethod(String key){ 
     //get appropriate properties of the web service 
     configuration.getOptions().get(key); 
    }  
} 

na podstawie usługi internetowej uzyskać wartości wymagane przy użyciu klucza.

+0

Nie mogę uruchomić twojego przykładu. Czy możesz opisać, co masz na myśli mówiąc o "definiowaniu par wartości klucza w application.properties"? –

+0

@WaleryStrauch Chciałem zdefiniować pary wartości klucza, jak wspomniano w tym przykładzie https://dzone.com/articles/spring-boot-configurationproperties-1. Oparte na kluczach odpowiednich właściwości można uzyskać z mapy – Barath

0

Zmień yml do:

options: 
    - name: optionA 
    foo: 
     urls: 
     - a 
     - b 
    bar: 
     something: hello 
    - name: optionB 
    foo: 
     urls: 
     - x 
     - y 
    bar: 
     something: bye 

Dodaj Config Klasa:

@Data 
@ConfigurationProperties 
@Configuration 
public class MyConfig { 

    private List<Option> options; 
} 

go używać:

@Component 
public class UseConfig { 

    @Autowired 
    public UseConfig(final MyConfig config) { 
     System.out.println(config.getOptions()); 
    } 

} 

Wynik:

[Option(name=optionA, foo=Foo(urls=[a, b]), bar=Bar(something=hello)), Option(name=optionB, foo=Foo(urls=[x, y]), bar=Bar(something=bye))]