2013-12-19 5 views
53

어떻게 스프링 부트의 favicon을 무시할 수 있습니까?스프링 부트 : favicon을 대체합니다

참고는 : 그것은 application.properties위한거야 Spring Boot: Is it possible to use external application.properties files in arbitrary directories with a fat jar?, 그러나 또한 파비콘에 적용 할 수 있습니다 : 여기에 코딩을 포함하지 않는 다른 솔루션을 제공합니다 내 또 다른 질문입니다. 사실, 나는 지금 favicon overriding을 위해 그 방법을 사용하고있다.

내가 @EnableWebMvc가있는 클래스를 구현하는 경우, 봄 부팅의 WebMvcAutoConfiguration 클래스는로드되지 않습니다, 나는 정적 내용의 루트 디렉토리에 배치하여 내 자신의 파비콘을 제공 할 수 있습니다.

그렇지 않으면 WebMvcAutoConfiguration은 faviconRequestHandler 빈 (소스 https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java 참조)을 등록하고 Spring 부트의 주 리소스 디렉토리에있는 '녹색 잎'아이콘을 제공합니다.

@EnableWebMvc이있는 클래스를 구현하지 않고 어떻게 재정의하여 스프링 부트의 WebMvcAutoConfiguration 클래스의 전체 기본 구성 기능을 비활성화 할 수 있습니까?

또한 클라이언트 (웹 브라우저) 측에서 가능한 한 빨리 아이콘 파일을 업데이트하고 싶기 때문에 favicon 파일의 캐시 기간을 0으로 설정하고 싶습니다. (다음 코드와 같이, 최대한 빨리 내가 ​​파일을 변경 한 후 클라이언트 측에서 업데이트해야합니다 내 '정적'웹 애플리케이션의 콘텐츠 및 스크립트 파일을 사용하고 있습니다.)

public void addResourceHandlers(ResourceHandlerRegistry registry) 
{ 
    registry.addResourceHandler("/**") 
     .addResourceLocations("/") 
     .setCachePeriod(0); 
} 

그래서 그냥 파비콘을 저장하는 장소를 찾을 수 있습니다. ico 파일은 Spring Boot의 faviconRequestHandler가 충분하지 않을 수도 있습니다.

UPDATE

지금 내가 src/main/resources 디렉토리에 파비콘 파일을 배치하여 기본 하나를 대체 할 수 있음을 알고있다. 그러나 캐시 기간 문제는 여전히 남아 있습니다.
또한 favicon 파일을 리소스 디렉토리가 아닌 정적 웹 파일이있는 디렉토리에 배치하는 것이 좋습니다.

확인

UPDATE, 나는 기본 하나를 오버라이드 (override) 할 수 있었다. 다음과 같이 내가 무슨 짓을 은 다음과 같습니다

@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); 
     } 
    } 
} 

는 기본적으로, 나는 registry.setOrder (는 Integer.MIN_VALUE)를 호출하여 최상위의 자원 핸들러를 추가하여 기본 하나를 무효화한다.

스프링 부트의 기본 값은 순서 값 (Integer.MIN_VALUE +1)을 가지므로 (FaviconConfiguration 클래스 https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration.java 참조) 내 처리기가 우선합니다.

괜찮습니까? 다른 방법 (내가 한 것보다 더 부드러운 것)이 있습니까?

UPDATE

이 좋아 아니다. registry.setOrder(Integer.MIN_VALUE)을 호출하면 실제로 모든 리소스 처리기의 우선 순위가 높아집니다.따라서 다음 코드를 다른 WebMvcConfigurerAdapter에 추가하면 모든 HTTP 요청이 해당 자원 핸들러로 보내 지므로 Java 코드에 의한 동적 처리가 방지됩니다.

public void addResourceHandlers(ResourceHandlerRegistry registry) 
{ 
    registry.addResourceHandler("/**") 
     .addResourceLocations("/") 
     .setCachePeriod(0); 
} 

다른 해결책이 필요합니다.

UPDATE

지금, 나는 파비콘 기능 봄 부팅이 제공 오버라이드 (override) 할 수있는 방법을 찾을 수 없습니다.
어쩌면 내 자신의 HandlerMapping 콩을 추가하는 방법이 있지만, 어떻게해야할지 모르겠다.

지금은 다음 옵션 중 하나를 선택할 수 있습니다

  1. @EnableWebMvc 따라서 해제 봄 부팅 WebMvcAutoConfiguration 클래스가있는 클래스가 있습니다. (WebMvcAutoConfiguration 클래스의 코드를 복사하고 favicon 기능을 삭제할 수 있습니다.)
  2. favicon 파일을 임의의 위치에 배치 할 수있는 자유를 포기하고 Spring Boot의 favicon 기능에 필요한대로 리소스 디렉토리에 배치하십시오. 그리고 캐싱 문제를 무시하십시오.

그러나 어느 옵션도 만족스럽지 않습니다.
그냥 내 정적 웹 파일 (문서 루트를 변경할 수 있기 때문에 어떤 디렉토리가 될 수 있음)로 favicon 파일을 배치하고 캐싱 문제를 해결하고 싶습니다.
내가 뭔가를 놓친 건가요?
모든 의견을 크게 기뻐할 것입니다. 다음과 같이

UPDATE는

BTW, 내가 파비콘과 다른 정적 파일의 위치를 ​​변경하려는 이유입니다. 현재로서는 주로 개발 환경 문제입니다.

단일 페이지 웹 응용 프로그램 (SPA)을 구축 중입니다.

라이브러리/프레임 워크 : 서버 측에 대한

  • , 나는 봄을 사용합니다. (물론)
  • 클라이언트 (웹 브라우저) 측에 대해서는 AngularJS를 사용합니다.

도구 : 서버 측에 대한

  • , 나는 봄 도구 스위트를 사용합니다.
  • 클라이언트 측에서는 WebStorm을 사용합니다.

홈페이지 디렉토리 구조 :

ProjectRoot\ 
    src\ 
    bin\ 
    build\ 
    webapp\ 
    build.gradle 
  • SRC : 내 봄 자바 소스 파일이있는.
  • bin : Spring Tool Suite는 빌드 출력을 저장합니다.
  • build : 'gradle build'는 빌드 출력을 저장합니다.
  • webapp : 내 클라이언트 소스 파일 (.js, .css, .htm 및 favicon)이 상주합니다. 따라서 이것은 WebStorm 프로젝트 디렉토리입니다. 내가 원하는 것은

(필요한 경우 나 디렉토리 이름을 변경할 수 있습니다) :

  • 수정하고 나의 봄 서버 응용 프로그램을 다시 시작/다시 작성하지 않고 내 클라이언트 코드를 테스트 할 수 있으려면. 따라서 클라이언트 코드를 jar 파일에 넣으면 안됩니다. 어쨌든 Spring Tool Suite는 jar 파일을 전혀 만들지 않습니다. (적어도 현재 설정의 경우)
  • Spring Tool Suite 출력과 gradle 출력 사이를 쉽게 전환 할 수 있도록 클라이언트 코드로 Spring 서버 애플리케이션을 테스트 할 수 있습니다. 따라서 클라이언트 코드는 build 하위 디렉토리 (실제로는 build\libs)의 서버 응용 프로그램과 bin 디렉토리의 서버 응용 프로그램에서 액세스 할 수 있어야합니다.
  • 클라이언트 코드를 수정하면 웹 브라우저에서 즉시 사용할 수 있어야합니다. 따라서 브라우저는 무한정 캐시하지 않아야하며 항상 업데이트를 요청해야합니다.
  • 배포 할 때 서버 응용 프로그램을 다시 작성하거나 다시 시작하지 않고 클라이언트 코드를 수정해야합니다. 따라서 클라이언트 코드를 jar 파일에 넣으면 안됩니다. 캐시 문제에 관해서는

: addResourceHandlers(), 구글 크롬, 무기한 파일을 캐시에 setCachePeriod (0)없이

업데이트 서버를 묻지 않고. 서버에 연결조차하지 않습니다. (Google 엔지니어들은 그 행동이 맞다고 말합니다.) 그래서 내가 할 수있는 일은 브라우저 캐시를 수동으로 지우는 것입니다. 개발 환경에 좌절하고 프로덕션 환경에서 수용 할 수 없습니다.

참고 사항 Node.js의 express.js 모듈은 적절한 기본 HTTP 헤더를 제공하므로 Google 크롬이 서버에 업데이트를 요청합니다. Spring과 express.js가 Fiddler를 사용하여 생성 한 HTTP 헤더를 검토했을 때, 그들은 달랐습니다.

내 환경을 개선하기위한 제안 사항을 보내 주시면 감사하겠습니다.
저는 봄 초보자이기 때문에 뭔가 빠져있을 수 있습니다.

UPDATE 마지막으로 나는 작동하는 코드가 있습니다. 다음과 같습니다.

@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; 
    } 
} 

빈 이름에 유의하십시오. 이름 충돌을 피하기 위해 '내'를 추가했습니다.
응용 프로그램 컨텍스트 자체를 autowiring하는 것이 어색한 것처럼 보일 수 있지만 org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration.addResourceLocations()의 코드를 모방해야합니다.

이제 favicon 처리기에 문제가 없으며 원하는 위치에 favicon 파일을 둘 수 있습니다.
감사합니다.

+1

당신의 방법은 OK 보이는을 사용했다. 그렇다고해서 기본 Spring MVC 리소스 핸들러를 대체하지는 않는다 (정적 리소스는 더 이상 classpath :/static에서 제공되지 않을 것이다). (이것이 바로 Boot의 favicon 지원이 내가 생각하는 자체 HandlerMapping에있는 이유입니다.) –

+0

@DaveSyer 이제 나는 그것이 OK가 아니라는 것을 깨달았습니다. 위의 세 번째 업데이트를 작성했습니다. 아마도 'HandlerMapping'이 분리되어 있어야 할 것입니다. – zeodtr

+0

@DaveSyer 위의 네 번째 업데이트를 참조하십시오. 다른 방법이 있습니까? 예를 들어, 내 자신의'HandlerMapping'을 등록 할 수 있습니까? – zeodtr

답변

35

favicon.ico를 classpath의 루트 또는 정적 리소스 위치 (예 : classpath:/static)에 넣을 수 있습니다. 하나의 플래그 spring.mvc.favicon.enabled=false을 사용하여 파비콘 해상도를 완전히 비활성화 할 수도 있습니다.

완전한 제어권을 얻으려면 HandlerMapping을 추가 할 수 있습니다 (Boot에서 복사 한 것보다 우선 순위를 부여하십시오).

@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; 
} 
} 
+0

고맙습니다. 나는 이미 그것을 시도했다고 생각했지만, 이제는 생각해 보았습니다.'@Configuration' 주석을 놓쳤습니다. BTW, 왜 내가 질문에 다른 위치에 정적 파일을 배치하려는 이유를 썼습니다. – zeodtr

+0

문서 루트 (오른쪽?)에 파일을 가져 오기 위해 ResourceLoader.gerResource ("/")를 사용해야하므로 BTW에서 @Autowire ApplicationContext를 사용해야합니다. 응용 프로그램 컨텍스트 DI를 사용해도됩니까? 어떤 사람들은 나쁜 일이라고 말합니다. – zeodtr

+0

나는 당신의 제안을 시도하고있다. 주목해야 할 한 가지 : 나의 bean 이름은 'faviconHandlerMapping'이되어서는 안된다. 왜냐하면 Spring Boot의 faviconHandlerMapping 빈과 bean name clash가 생기기 때문이다. org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestor s()에 의해 호출되는 메소드에 의해 2 개의 빈 중 하나만 선택되며, 이는 다시 org.springframework.web.servlet.initHandlerMappings()에 의해 호출됩니다. 내 콩이 이름 충돌로 우선 오버라이드 된 것 같습니다. – zeodtr

63

이 중 아무 것도 필요하지 않았습니다.

기본값보다 우선 순위가 높은 생성 된 JAR로 자원을 번들 할 수있는 경우 기본값을 대체하십시오.

사용자 지정 favicon.ico 파일을 얻으려면 내 응용 프로그램의 src/main/resources 디렉터리를 만든 다음 favicon.ico 파일을 거기에 복사했습니다. 이 resources 디렉토리에있는 파일들은 컴파일 된 JAR의 루트로 옮겨 지므로 Spring이 제공하기 전에 커스텀 favicon.ico이 발견된다.

위 작업을 수행하면 위의 업데이트 된 솔루션과 동일한 효과가 나타납니다.

v1.2.0부터 파일을 src/main/resources/static에 넣을 수도 있습니다.

+5

이유는 간단합니다. 나는 favicon 파일을 JAR 파일에 넣고 싶지 않습니다. – zeodtr

+0

@zeodtr 이유가 궁금합니다. 이것은 나에게 가장 자연스러운 것 같습니다. 그러나, 나는 그것이'src/main/resources/static/images'에있을 것을 기대했을 것입니다. – btiernay

+1

@btiernay 웹 서버가 웹 클라이언트와 별개의 엔터티이기 때문입니다. 그리고 favicon (들)은 클라이언트에 속합니다. 웹 서버의 war 파일에는 클라이언트에 속한 파일을 포함 할 필요가 없으며 사용자의 필요에 따라 훨씬 자주 수정할 수 있습니다. – zeodtr

20

전반적으로 스마트 솔루션으로 가득차 있기 때문에 저는 Springboot를 정말 좋아하지만, 그저 바보 인 이유 때문에 favicon을 제공하기 위해 애플리케이션 빈을 등록하는 것을 거부합니다.

방금 ​​내 HTML 페이지 헤드에 내 favicon 링크를 추가했습니다.

<link rel="icon" type="image/png" href="images/fav.png"> 

는 그럼 난 내 파비콘을 이름을 변경하고 봄과 자바를 사용하지 않고도

이제
<ProjFolder>/src/main/resources/static/images/fav.png 

내가 크롬과 파이어 폭스 브라우저 탭과 사파리의 주소 표시 줄에 아이콘이 그것을 배치, 내가해야 그러한 사소한 기능을 위해 최신 버전에서 Springboot의 변경 사항을 추적 할 필요가 없습니다.

+3

더 이상 처리기 매핑을 배울 필요가 없습니다 (정적 리소스에 favicon.ico를 넣음). –

+0

그건 아주 간단합니다! 감사. 나는 그것을 조각에 추가한다. –

+0

그것은 매력, ​​최고의 솔루션처럼 작동합니다! –

2

최신 버전의 Boot (1.2는 물론 1.1.8도 가능)를 사용하면 정적 리소스에 favicon.ico를 추가 할 수 있습니다.

1

registry.addResourceHandler를 ("/ robots.txt를") addResourceLocations ("/").

registry.addResourceHandler ("/ favicon.ico"). addResourceLocations ("/");

의 robots.txt, favicon.ico의 파일 위치 :/SRC/메인/자원

내가 봄 부팅 1.2.1