Spring Boot : favicon 재정의


84

Spring Boot의 favicon을 어떻게 재정의 할 수 있습니까?

참고 : 여기에 코딩을 포함하지 않는 또 다른 솔루션을 제공하는 또 다른 질문이 있습니다. Spring Boot : fat jar와 함께 임의의 디렉토리에서 외부 application.properties 파일을 사용할 수 있습니까? application.properties 용이지만 favicon에도 적용 할 수 있습니다. 사실, 지금은 favicon 재정의에이 방법을 사용하고 있습니다.

@EnableWebMvc가있는 클래스를 구현하면 Spring Boot의 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 Boot의 기본 리소스 디렉토리에있는 'green leaf'아이콘을 제공합니다.

@EnableWebMvc가있는 클래스를 직접 구현하지 않고 어떻게 재정 의하여 Spring Boot의 WebMvcAutoConfiguration 클래스의 전체 기본 구성 기능을 비활성화 할 수 있습니까?

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

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

따라서 Spring Boot의 faviconRequestHandler가 존중하는 favicon.ico 파일을 저장할 위치를 찾는 것만으로는 충분하지 않을 수 있습니다.

최신 정보

이제 favicon 파일을 src / main / resources 디렉터리에 배치하여 기본 파일을 재정의 할 수 있음을 알고 있습니다. 그러나 캐시 기간 문제는 여전히 남아 있습니다.
또한 리소스 디렉토리보다는 정적 웹 파일이있는 디렉토리에 favicon 파일을 배치하는 것이 좋습니다.

최신 정보

좋아, 기본 설정을 재정의했습니다. 내가 한 일은 다음과 같습니다.

@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)를 호출하여 순서가 가장 높은 리소스 핸들러를 추가하여 기본 값을 덮어 씁니다.

Spring Boot의 기본 값은 순서 값 (Integer.MIN_VALUE + 1)을 갖기 때문에 ( https://github.com/spring-projects/spring-boot/blob/master/spring-boot-autoconfigure/의 FaviconConfiguration 클래스 참조) src / main / java / org / springframework / boot / autoconfigure / web / WebMvcAutoConfiguration.java ) 내 핸들러가 이깁니다.

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

최신 정보

괜찮지 않습니다. 를 호출 registry.setOrder(Integer.MIN_VALUE)하면 실제로 모든 리소스 처리기의 우선 순위를 높입니다. 따라서 다른 코드에 다음 코드를 추가 WebMvcConfigurerAdapter하면 사실상 모든 http 요청이 해당 리소스 핸들러로 전달되어 Java 코드에 의한 동적 처리를 방지합니다.

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

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

최신 정보

지금은 Spring Boot가 제공하는 favicon 기능을 재정의하는 방법을 찾을 수 없습니다.
내 자신의 HandlerMapping빈 을 추가하는 방법이 있을지 모르지만 방법을 모르겠습니다.

이제 다음 옵션 중 하나를 선택할 수 있습니다.

  1. @EnableWebMvc따라서 Spring Boot WebMvcAutoConfiguration클래스 를 비활성화 하는 클래스가 있습니다 . ( WebMvcAutoConfiguration클래스 코드 복사 및 파비콘 기능 삭제 가능)
  2. favicon 파일을 임의의 위치에 배치하는 자유를 포기하고 Spring Boot의 favicon 기능이 요구하는대로 리소스 디렉토리에 배치합니다. 그리고 캐싱 문제를 무시하십시오.

그러나 어느 옵션도 만족스럽지 않습니다.
정적 웹 파일 (문서 루트를 변경할 수 있으므로 모든 디렉토리가 될 수 있음)과 함께 favicon 파일을 배치하고 캐싱 문제를 해결하고 싶습니다.
내가 뭔가를 놓치고 있습니까?
어떤 제안이라도 대단히 감사하겠습니다.

최신 정보

BTW, favicon 및 기타 정적 파일의 위치를 ​​변경하려는 이유는 다음과 같습니다. 현재로서는 주로 개발 환경 문제입니다.

단일 페이지 웹 애플리케이션 (SPA)을 구축 중입니다.

라이브러리 / 프레임 워크 :

  • 서버 측에서는 Spring을 사용합니다. (물론이야)
  • 클라이언트 (웹 브라우저) 측의 경우 AngularJS를 사용합니다.

도구 :

  • 서버 측에서는 Spring Tool Suite를 사용합니다.
  • 클라이언트 측에서는 WebStorm을 사용합니다.

기본 디렉토리 구조 :

ProjectRoot\
    src\
    bin\
    build\
    webapp\
    build.gradle
  • src : 내 Spring 자바 소스 파일이있는 곳.
  • bin : Spring Tool Suite는 빌드 출력을 배치합니다.
  • build : 'gradle build'는 빌드 출력을 배치합니다.
  • webapp : 내 클라이언트 소스 파일 (.js, .css, .htm 및 favicon)이있는 위치입니다. 따라서 이것이 WebStorm 프로젝트 디렉터리입니다. (필요한 경우 디렉토리 이름을 변경할 수 있습니다)

내가 원하는 것은 :

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

캐시 문제 관련 :

addResourceHandlers ()에 setCachePeriod (0)가 없으면 Google 크롬은 서버에 업데이트를 요청하지 않고 파일을 무기한 캐시합니다. 서버에도 연결되지 않습니다. (Google 엔지니어들은 동작이 옳다고 말합니다.) 그래서 제가 할 수있는 일은 브라우저 캐시를 수동으로 지우는 것뿐입니다. 개발 환경에서는 실망스럽고 프로덕션 환경에서는 용납 할 수 없습니다.

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

내 환경 개선에 대한 제안을 주시면 감사하겠습니다.
저는 봄 초심자라서 뭔가 빠졌을 수도 있습니다.

최신 정보

마지막으로 작업 코드가 있습니다. 다음과 같습니다.

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

빈 이름을 확인하십시오. 이름 충돌을 피하기 위해 'my'를 추가했습니다.
Autowiring 애플리케이션 컨텍스트 자체는 어색해 보이지만 .NET에서 코드를 모방하는 데 필요했습니다 org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration.addResourceLocations().

이제 캐싱 문제가없는 파비콘 핸들러가 있으며 원하는 곳에 파비콘 파일을 배치 할 수 있습니다.
감사.


1
귀하의 방법은 괜찮아 보입니다. 그래도 기본 Spring MVC 리소스 핸들러를 대체 하지 않습니다 ( classpath:/static예를 들어 정적 리소스는 더 이상 제공되지 않습니다 ). (부팅에서 파비콘 지원 내가 생각하는 자신의 모든 HandlerMapping에있는 이유입니다.)
데이브 Syer

@DaveSyer 이제 괜찮지 않다는 것을 깨달았습니다. 위의 세 번째 업데이트를 작성했습니다. 아마도 분리 HandlerMapping가 필요할 수 있습니다.
zeodtr

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

예, 추가 할 수 있습니다 HandlerMapping(부팅에서 복사하고 더 높은 우선 순위를 부여). 의 위치에 관심이있는 이유를 잘 모르겠지만 favicon.ico file원하는 경우 구성 할 수 있습니다. 모든 브라우저도 캐시를 캐시하므로 캐시 설정이 중요하지 않지만 잘못된 것으로 판명되어 기쁩니다.
Dave Syer

@DaveSyer 정적 파일을 다른 위치에 배치하려는 이유에 대한 업데이트 된 질문을 참조하십시오. 또한 캐시 문제입니다.
zeodtr

답변:


54

클래스 경로의 루트 또는 정적 리소스 위치 (예 :)에 자신의 favicon.ico를 넣을 수 있습니다 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;
}
}

감사합니다. 이미 해본 것 같았는데 이제 생각이 나서 @Configuration주석을 놓쳤습니다 . BTW, 질문의 다른 위치에 정적 파일을 배치하려는 이유를 작성했습니다.
zeodtr

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

나는 당신의 제안을 시도하고 있습니다. 한 가지 주목할 점 : 내 빈 이름은 Spring Boot의 faviconHandlerMapping 빈과 빈 이름이 충돌하기 때문에 'faviconHandlerMapping'이 아니어야합니다. org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestor‌ s ()에 의해 호출되는 메소드에 의해 2 개의 bean 중 하나만 선택되며 이는 org.springframework.web.servlet.initHandlerMappings ()에 의해 다시 호출됩니다. 내 빈이 더 일찍로드 된 다음 이름 충돌로 재정의 된 것 같습니다.
zeodtr 2013-12-20

다음과 같이 등록 된 모든 HandlerMapping 콩의 이름은 다음과 같습니다 { faviconHandlerMapping, requestMappingHandlerMapping, viewControllerHandlerMapping, beanNameHandlerMapping, resourceHandlerMapping, defaultServletHandlerMapping, endpointHandlerMapping내가 그 이름을 피해야한다} 그래서.
zeodtr

2
업데이트 된 답변과 사용 설명서를 읽어야합니다. 당신이 원하는 것은 아이콘을 변경하는 것뿐이라면 결코 어려운 변경이 아닙니다. OP가 왜 그렇게 많은 문제를 겪었는지 모르겠습니다.
Dave Syer 2016

75

이 중 어느 것도 나에게 필요하지 않았습니다.

기본 JAR보다 우선 순위가 더 높은 생성 된 JAR로 자원을 번들 할 수 있는데 기본값을 대체하는 이유는 무엇입니까?

사용자 지정 favicon.ico파일 을 얻기 위해 src/main/resources응용 프로그램에 대한 디렉터리를 만든 다음 favicon.ico파일을 여기에 복사 했습니다. 이 리소스 디렉토리의 파일은 컴파일 된 JAR의 루트로 이동하므로 favicon.icoSpring이 제공 한 JAR 이전에 사용자 정의 가 발견됩니다.

위의 작업을 수행하면 위의 업데이트 된 솔루션과 동일한 효과를 얻었습니다.

v1.2.0 이후로 파일을 src/main/resources/static.


6
그 이유는 간단합니다. favicon 파일을 JAR에 넣고 싶지 않습니다.
zeodtr 2014 년

@zeodtr은 이유가 궁금합니다. 이것은 나에게 가장 자연스러운 것 같습니다. 그러나 나는 그것이있을 것으로 예상했을 것입니다src/main/resources/static/images
btiernay 2014 년

1
@btiernay 웹 서버가 웹 클라이언트와는 별개의 개체이기 때문입니다. 그리고 파비콘은 클라이언트에 속합니다. 웹 서버의 war 파일은 사용자의 필요에 따라 훨씬 더 자주 수정할 수있는 클라이언트에 속한 파일을 포함 할 이유가 없습니다.
zeodtr 2014 년

참고로, 이제 다음에서 해결할 수 favicon.ico있습니다 static. github.com/spring-projects/spring-boot/commit/…
btiernay

1
src / main / resources / static 경로가 잘 작동합니다. 이것은 가장 간단하고 규칙적인 방법입니다.
pdem

29

전반적으로 스마트 솔루션으로 가득 차 있기 때문에 Springboot를 정말 좋아하지만 파비콘을 제공하기 위해 응용 프로그램 빈을 등록하는 것은 어리석은 일이기 때문에 거부합니다.

내 HTML 페이지 헤드에 내 자신의 파비콘 링크를 추가했습니다.

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

그런 다음 파비콘의 이름을 변경하고

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

이제 Spring과 Java를 사용하지 않고도 Chrome 및 Firefox 브라우저 탭과 Safari 주소 표시 줄에 아이콘이 있으며, 이러한 사소한 기능을 위해 최신 버전에서 Springboot에 대한 변경 사항을 추적 할 필요가 없습니다.


4
더 이상 핸들러 매핑을 다룰 필요가 없습니다 (정적 리소스에 favicon.ico를 넣으면됩니다).
Dave Syer 2014

너무 간단합니다! 감사. 내 조각에 추가합니다.
Lay Leangsros

당신은 단지 API 서비스 백엔드로 springboot을 사용하는 경우 무엇을, 당신이 어떤 HTML 페이지가 없습니다 : /
Paramvir 싱 Karwal

@ParamvirSinghKarwal 서비스 만 있다면 왜 파비콘을 원하십니까?
jeremyjjbrown

브라우저 주소에서 직접 api를 치면 녹색 잎과 같은 스프링 애플리케이션의 기본 파비콘이 표시됩니다. 브랜드 파비콘이되기를 바랍니다. 나는 그것을 할 수 있었다.
Paramvir Singh Karwal 19 년

13

Spring Boot 1.2.2 및 1.1.11 이후로 다음을 사용하여 기본 파비콘을 쉽게 비활성화 할 수 있습니다. spring.mvc.favicon.enabled = false 속성을 .

자세한 정보는 다음을 방문하십시오.

업데이트 : spring.mvc.favicon.enabledSpring Boot 2.2.x 이후 로 더 이상 속성 이 없습니다.


spring.mvc.favicon.enabled는 스프링 부트 2.2에서 제거되었습니다. 대체 무엇을 알고 있습니까?
Shilan

1
@Shilan 더 이상 기본 파비콘이 없기 때문에 아무것도 대체되지 않습니다. 원하는 경우 자신의 파비콘에 대한 매핑을 구성해야합니다.
Trynkiewicz Mariusz

1
네 결국 나는 이것을 대신해야한다는 것을 알았습니다. @Override public void addResourceHandlers (ResourceHandlerRegistry registry) {registry.addResourceHandler ( "/ favicon.ico"). addResourceLocations ( "classpath : / static /"); }
Shilan

2

최신 버전의 Boot (1.2 확실하지만 1.1.8도 가능)를 사용하면 정적 리소스에 favicon.ico를 넣을 수 있습니다.


2

많은 옵션 / 변형을 시도했지만 이것 만 효과가있었습니다. (스프링 부트 2.2.7)

/ resources / static 에있는 Favicon.ico 파일 및 robots.txt

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

@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
@Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler(
      "/favicon.ico",
      "/robots.txt")
      .addResourceLocations(
        "classpath:/static/");
  }
}

도움이된다면 마음에 들어주세요;)


1

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

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

robots.txt, favicon.ico 파일 위치 : / src / main / resources

나는 스프링 부트 1.2.1을 사용했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.