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.
źródło
classpath:/static
). (Dlatego myślę, że obsługa favicon w Boot jest we własnym HandlerMapping.)HandlerMapping
potrzebny jest oddzielny .HandlerMapping
?HandlerMapping
(po prostu skopiuj ten z Boot i nadaj mu wyższy priorytet). Nie jestem pewien, dlaczego miałbyś przejmować się lokalizacją,favicon.ico file
ale możemy ją skonfigurować, jeśli chcesz. Wszystkie przeglądarki również będą go buforować, więc wątpię, czy ustawienia pamięci podręcznej mają znaczenie, ale cieszę się, że udowodniono, że się mylą.Odpowiedzi:
Możesz po prostu umieścić swój własny plik favicon.ico w katalogu głównym ścieżki klas lub w dowolnej statycznej lokalizacji zasobów (np
classpath:/static
.). Możesz także całkowicie wyłączyć rozdzielczość favicon za pomocą jednej flagispring.mvc.favicon.enabled=false
.Aby przejąć pełną kontrolę, możesz dodać HandlerMapping (po prostu skopiuj ten z Boot i nadaj mu wyższy priorytet), np.
@Configuration public static class FaviconConfiguration { @Bean public SimpleUrlHandlerMapping faviconHandlerMapping() { SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(); mapping.setOrder(Integer.MIN_VALUE); mapping.setUrlMap(Collections.singletonMap("mylocation/favicon.ico", faviconRequestHandler())); return mapping; } @Bean protected ResourceHttpRequestHandler faviconRequestHandler() { ResourceHttpRequestHandler requestHandler = new ResourceHttpRequestHandler(); requestHandler.setLocations(Arrays .<Resource> asList(new ClassPathResource("/"))); return requestHandler; } }
źródło
@Configuration
adnotację. BTW, napisałem powód, dla którego chcę umieścić pliki statyczne w innej lokalizacji w pytaniu.faviconHandlerMapping
,requestMappingHandlerMapping
,viewControllerHandlerMapping
,beanNameHandlerMapping
,resourceHandlerMapping
,defaultServletHandlerMapping
,endpointHandlerMapping
} Więc muszę unikać tych nazwisk.Nic z tego nie było mi potrzebne.
Po co zastępować wartość domyślną, skoro można spakować zasób z wygenerowanym plikiem JAR, który będzie miał wyższy priorytet niż domyślny.
Aby uzyskać niestandardowy
favicon.ico
plik, utworzyłemsrc/main/resources
katalog dla mojej aplikacji, a następnie skopiowałem tamfavicon.ico
plik. Pliki w tym katalogu zasobów są przenoszone do katalogu głównego skompilowanego pliku JAR i dlatego Twój niestandardowy plikfavicon.ico
znajduje się przed plikiem dostarczonym przez Spring.Wykonanie powyższego przyniosło taki sam efekt, jak zaktualizowane rozwiązanie powyżej.
Zauważ, że od wersji 1.2.0 możesz również umieścić plik w formacie
src/main/resources/static
.źródło
src/main/resources/static/images
favicon.ico
zstatic
: github.com/spring-projects/spring-boot/commit/ ...Bardzo podoba mi się Springboot, ponieważ ogólnie jest pełen inteligentnych rozwiązań, ale odmawiam zarejestrowania komponentu bean aplikacji, aby zapewnić favicon, ponieważ jest to po prostu głupie.
Właśnie dodałem własny link do favicon w nagłówku mojej strony html.
<link rel="icon" type="image/png" href="images/fav.png">
Następnie zmieniłem nazwę mojej ulubionej ikony i umieściłem ją pod adresem
<ProjFolder>/src/main/resources/static/images/fav.png
Teraz mam ikonę na kartach przeglądarek Chrome i Firefox oraz pasek adresu Safari bez konieczności używania Springa i Javy i nie powinienem gonić zmian w Springboot w nowszych wersjach, aby uzyskać tak trywialną funkcjonalność.
źródło
Od wersji Spring Boot 1.2.2 i 1.1.11 możesz łatwo wyłączyć domyślną ikonę favicon za pomocą
spring.mvc.favicon.enabled = false
właściwości.Więcej informacji na stronie:
AKTUALIZACJA: nie ma już
spring.mvc.favicon.enabled
właściwości od wersji Spring Boot 2.2.x.źródło
Nowsze wersje Boot (na pewno 1.2, ale może także 1.1.8) pozwalają po prostu umieścić favicon.ico w zasobach statycznych.
źródło
Wypróbowałem wiele opcji / wariantów, ale tylko to działało. (Spring Boot 2.2.7)
Pliki Favicon.ico i plik robots.txt umieszczają w / resources / static
@Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/favicon.ico").permitAll() .antMatchers("/robots.txt").permitAll() .antMatchers("/").permitAll() .anyRequest().authenticated(); } }
i
@Configuration @EnableWebMvc public class MvcConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler( "/favicon.ico", "/robots.txt") .addResourceLocations( "classpath:/static/"); } }
Jeśli to pomoże, polub to;)
źródło
register.addResourceHandler ("/ robots.txt"). addResourceLocations ("/");
register.addResourceHandler ("/ favicon.ico"). addResourceLocations ("/");
robots.txt, lokalizacja pliku favicon.ico: / src / main / resources
użyłem buta sprężynowego 1.2.1
źródło