Jak mogę zmienić favicon Spring Boot?
UWAGA : Oto moje kolejne pytanie, które dostarcza innego rozwiązania, które nie wymaga żadnego kodowania: Spring Boot: Czy można używać zewnętrznych plików application.properties w dowolnych katalogach z fat jar? Jest przeznaczony dla application.properties, ale można go również zastosować do favicon. W rzeczywistości używam teraz tej metody do zastępowania favicon.
Jeśli zaimplementuję klasę, która ma @EnableWebMvc, klasa WebMvcAutoConfiguration Spring Boot nie ładuje się i mogę obsługiwać własną ikonę favicon, umieszczając ją w katalogu głównym zawartości statycznej.
W przeciwnym razie WebMvcAutoConfiguration rejestruje bean faviconRequestHandler, (patrz źródło https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ web / WebMvcAutoConfiguration.java ) i wyświetla ikonę „zielonego liścia”, która jest umieszczana w głównym katalogu zasobów Spring Boot.
Jak mogę to zastąpić bez implementowania klasy, która ma @EnableWebMvc, wyłączając w ten sposób całą domyślną funkcjonalność konfiguracji klasy WebMvcAutoConfiguration w Spring Boot?
Ponadto, ponieważ chcę jak najszybciej zaktualizować plik ikony po stronie klienta (przeglądarki internetowej), chcę ustawić okres pamięci podręcznej pliku favicon na 0. (podobnie jak poniższy kod, którego używam do mojego `` statyczna '' zawartość aplikacji internetowej i pliki skryptów, które należy zaktualizować po stronie klienta tak szybko, jak to możliwe po zmianie pliku).
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/**")
.addResourceLocations("/")
.setCachePeriod(0);
}
Tak więc, aby znaleźć miejsce do zapisania pliku favicon.ico, które Spring Boot honoruje faviconRequestHandler, może nie wystarczyć.
AKTUALIZACJA
Teraz wiem, że mogę zastąpić domyślny, umieszczając plik favicon w katalogu src / main / resources. Ale problem z okresem pamięci podręcznej nadal pozostaje.
Ponadto lepiej jest umieścić plik favicon w katalogu, w którym umieszczane są statyczne pliki internetowe, a nie w katalogu zasobów.
AKTUALIZACJA
Ok, udało mi się nadpisać domyślny. Oto co zrobiłem:
@Configuration
public class WebMvcConfiguration
{
@Bean
public WebMvcConfigurerAdapter faviconWebMvcConfiguration()
{
return new FaviconWebMvcConfiguration();
}
public class FaviconWebMvcConfiguration extends WebMvcConfigurerAdapter
{
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.setOrder(Integer.MIN_VALUE);
registry.addResourceHandler("/favicon.ico")
.addResourceLocations("/")
.setCachePeriod(0);
}
}
}
Zasadniczo nadpisałem domyślny, dodając procedurę obsługi zasobów o najwyższej kolejności, wywołując register.setOrder (Integer.MIN_VALUE).
Ponieważ domyślny w Spring Boot ma wartość zamówienia (Integer.MIN_VALUE + 1), (patrz klasa FaviconConfiguration w https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/ src / main / java / org / springframework / boot / autoconfigure / web / WebMvcAutoConfiguration.java ) mój program obsługi wygrywa.
Czy to jest ok? Czy jest inny sposób (coś delikatniejszego niż to, co zrobiłem)?
AKTUALIZACJA
Nie jest w porządku. Kiedy dzwonię registry.setOrder(Integer.MIN_VALUE)
, w rzeczywistości podnoszę priorytet wszystkich osób obsługujących zasoby. Tak więc, kiedy dodaję następujący kod do innego WebMvcConfigurerAdapter
, efektywnie wszystkie żądania http są kierowane do tego modułu obsługi zasobów, zapobiegając wszelkiej dynamicznej obsłudze przez kod Java.
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/**")
.addResourceLocations("/")
.setCachePeriod(0);
}
Potrzebne jest inne rozwiązanie.
AKTUALIZACJA
Na razie nie mogłem znaleźć sposobu na zastąpienie funkcji favicon, którą zapewnia Spring Boot.
Może jest sposób na dodanie własnego HandlerMapping
ziarna, ale nie wiem, jak to zrobić.
Teraz mogę wybrać jedną z następujących opcji:
- Mieć klasę, która
@EnableWebMvc
wyłącza w ten sposóbWebMvcAutoConfiguration
klasę Spring Boot . (Mogę skopiować kodWebMvcAutoConfiguration
klasy i usunąć funkcjonalność favicon) - Zrezygnuj ze swobody umieszczania pliku favicon w dowolnej lokalizacji i umieść go w katalogu zasobów, zgodnie z wymaganiami funkcji favicon Spring Boot. I zignoruj problem z buforowaniem.
Ale żadna opcja nie jest zadowalająca.
Chcę tylko umieścić plik favicon z moimi statycznymi plikami sieciowymi (które mogą być dowolnym katalogiem, ponieważ mogę zmienić katalog główny dokumentu) i rozwiązać problem z buforowaniem.
Czy coś mi brakuje?
Każda sugestia byłaby bardzo mile widziana.
AKTUALIZACJA
BTW, powód, dla którego chcę zmienić lokalizację favicon i innych plików statycznych, jest następujący. Na razie jest to głównie kwestia środowiska programistycznego.
Buduję pojedynczą aplikację internetową (SPA).
Biblioteki / frameworki:
- Po stronie serwera używam Spring. (oczywiście)
- Po stronie klienta (przeglądarki internetowej) używam AngularJS.
Przybory:
- Po stronie serwera używam Spring Tool Suite.
- Po stronie klienta używam WebStorm.
Główna struktura katalogów:
ProjectRoot\
src\
bin\
build\
webapp\
build.gradle
- src: Gdzie znajdują się moje pliki źródłowe Java Spring.
- bin: Gdzie Spring Tool Suite umieszcza swoje dane wyjściowe kompilacji.
- build: Gdzie 'gradle build' umieszcza wynik kompilacji.
- webapp: Gdzie znajdują się pliki źródłowe mojego klienta (.js, .css, .htm i favicon). Tak więc jest to katalog projektu WebStorm. (W razie potrzeby mogę zmienić nazwę katalogu)
Chcę:
- Aby móc modyfikować i testować mój kod klienta bez przebudowywania / ponownego uruchamiania aplikacji serwera Spring. Tak więc kod klienta nie może zostać umieszczony w pliku jar. W każdym razie Spring Tool Suite w ogóle nie buduje pliku jar (przynajmniej dla bieżącej konfiguracji)
- Aby móc przetestować moją aplikację serwerową Spring za pomocą kodu klienta, łatwo przełączam się między wyjściem Spring Tool Suite a wyjściem gradle. Zatem kod klienta musi być dostępny zarówno z aplikacji serwera w
build
podkatalogu (faktyczniebuild\libs
), jak iz aplikacji serwera wbin
katalogu. - Kiedy modyfikuję kod klienta, musi on być natychmiast dostępny dla przeglądarki internetowej. Dlatego przeglądarka nie może buforować go w nieskończoność i zawsze musi prosić serwer o aktualizację.
- Po wdrożeniu kod klienta musi być modyfikowalny bez ponownego kompilowania / ponownego uruchamiania aplikacji serwera. Dlatego kod klienta nie może zostać umieszczony w pliku jar.
Odnośnie problemu z pamięcią podręczną:
Bez funkcji setCachePeriod (0) w addResourceHandlers () Google Chrome buforuje plik w nieskończoność, bez pytania serwera o aktualizacje. Nie łączy się nawet z serwerem. (Inżynierowie Google twierdzą, że to zachowanie jest prawidłowe). Więc jedyne, co mogę zrobić, to ręcznie wyczyścić pamięć podręczną przeglądarki. Jest to frustrujące w środowisku programistycznym i niedopuszczalne w środowisku produkcyjnym.
BTW, moduł express.js w Node.js podaje rozsądny domyślny nagłówek HTTP, dzięki czemu Google Chrome prosi serwer o aktualizacje. Kiedy przejrzałem nagłówki HTTP utworzone przez Spring i express.js przy użyciu programu Fiddler, były one różne.
Wszelkie sugestie dotyczące poprawy mojego środowiska będą mile widziane.
Ponieważ zaczynam od wiosny, być może czegoś mi brakuje.
AKTUALIZACJA
Wreszcie mam działający kod. Wygląda następująco:
@Configuration
public static class FaviconConfiguration
{
@Bean
public SimpleUrlHandlerMapping myFaviconHandlerMapping()
{
SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping();
mapping.setOrder(Integer.MIN_VALUE);
mapping.setUrlMap(Collections.singletonMap("/favicon.ico",
myFaviconRequestHandler()));
return mapping;
}
@Autowired
ApplicationContext applicationContext;
@Bean
protected ResourceHttpRequestHandler myFaviconRequestHandler()
{
ResourceHttpRequestHandler requestHandler =
new ResourceHttpRequestHandler();
requestHandler.setLocations(Arrays
.<Resource> asList(applicationContext.getResource("/")));
requestHandler.setCacheSeconds(0);
return requestHandler;
}
}
Zwróć uwagę na nazwy ziaren. Dodałem „mój”, aby uniknąć konfliktu nazw.
Sam kontekst aplikacji autowiring wydaje się niewygodny, ale był niezbędny do naśladowania kodu w org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration.addResourceLocations()
.
Teraz mam program obsługujący favicon wolny od problemu z buforowaniem i mogę umieścić plik favicon w dowolnym miejscu.
Dzięki.
classpath:/static
). (Dlatego myślę, że obsługa favicon w Boot jest we własnym HandlerMapping.)