मैं स्प्रिंग बूट के फेविकॉन को कैसे ओवरराइड कर सकता हूं?
नोट : यहां मेरा एक और प्रश्न है जो एक और समाधान प्रदान करता है जिसमें कोई कोडिंग शामिल नहीं है: स्प्रिंग बूट: क्या एक मोटी जार के साथ बाहरी एप्लिकेशन का उपयोग करना संभव है। यह application.properties के लिए है, लेकिन इसे फेविकॉन पर भी लागू किया जा सकता है। वास्तव में, मैं फ़ेविकॉन ओवरराइडिंग के लिए उस पद्धति का उपयोग कर रहा हूं।
यदि मैं एक ऐसी कक्षा को लागू करता हूं जिसमें @EnableWebMvc, WebMvcAutoConfiguration की स्प्रिंग बूट लोड नहीं होती है, और मैं स्थैतिक सामग्री के मूल निर्देशिका में रखकर अपने स्वयं के फ़ेविकॉन की सेवा कर सकता हूं।
अन्यथा, WebMvcAutoConfiguration रजिस्टरों faviconRequestHandler बीन, (देखें स्रोत https://github.com/spring-projects/spring-boot/blob/master/sing-boot-autoconfigure/src/main/java/org/springframework) web / WebMvcAutoConfiguration.java ) और यह 'ग्रीन लीफ' आइकन की सेवा करता है जिसे स्प्रिंग बूट के मुख्य संसाधन निर्देशिका में रखा गया है।
मैं उस वर्ग को लागू किए बिना इसे कैसे ओवरराइड कर सकता हूं, जिसमें खुद @EnableWebMvc है, इस प्रकार स्प्रिंग बूट के WebMvcAutoConfiguration वर्ग की संपूर्ण डिफ़ॉल्ट कॉन्फ़िगरेशन कार्यक्षमता को अक्षम करना?
इसके अलावा, जब से मैं चाहता हूं कि आइकन फ़ाइल को क्लाइंट (वेब ब्राउज़र) की तरफ से जल्द से जल्द अपडेट किया जाए, मैं फ़ेविकॉन फ़ाइल की कैश अवधि को 0. पर सेट करना चाहता हूं (निम्न कोड की तरह, जिसे मैं अपने लिए उपयोग कर रहा हूं 'स्टैटिक' वेबएप्प कंटेंट और स्क्रिप्ट फाइल्स, जिन्हें फाइल बदलने के बाद क्लाइंट साइड पर जल्द से जल्द अपडेट किया जाना चाहिए।)
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/**")
.addResourceLocations("/")
.setCachePeriod(0);
}
तो, बस favicon.ico फ़ाइल को सहेजने की जगह खोजने के लिए कि स्प्रिंग बूट का faviconRequestHandler सम्मान पर्याप्त नहीं हो सकता है।
अपडेट करें
अब मुझे पता है कि मैं एक favicon फ़ाइल को src / main / resource निर्देशिका में रखकर डिफ़ॉल्ट को ओवरराइड कर सकता हूँ। लेकिन कैश अवधि की समस्या अभी भी बनी हुई है।
इसके अलावा, फ़ेविकॉन फ़ाइल को उस निर्देशिका में रखना बेहतर होता है जो स्थिर वेब फ़ाइलों को रखा जाता है, बजाय संसाधन निर्देशिका के।
अपडेट करें
ठीक है, मैं डिफ़ॉल्ट को ओवरराइड करने में कामयाब रहा। मैंने जो किया वह इस प्रकार है:
@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);
}
}
}
मूल रूप से, मैं एक संसाधन हैंडलर को उच्चतम क्रम के साथ रजिस्ट्री.सेटऑर्डर (Integer.MIN_VALUE) कहकर डिफ़ॉल्ट रूप से ओवररोड करता हूं।
चूंकि स्प्रिंग बूट में डिफ़ॉल्ट एक का ऑर्डर मूल्य (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 अनुरोध उस संसाधन हैंडलर को निर्देशित किया जाता है, जो जावा कोड द्वारा किसी भी गतिशील हैंडलिंग को रोकता है।
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/**")
.addResourceLocations("/")
.setCachePeriod(0);
}
एक और उपाय की जरूरत है।
अपडेट करें
अभी के लिए, मुझे फ़ेविकॉन फ़ंक्शनलिटी को ओवरराइड करने का तरीका नहीं मिला जो स्प्रिंग बूट प्रदान करता है।
हो सकता है कि मेरा खुद का HandlerMapping
बीन जोड़ने का कोई तरीका हो , लेकिन मुझे नहीं पता कि यह कैसे करना है।
अब मैं निम्नलिखित विकल्पों में से एक चुन सकता हूं:
- एक वर्ग है जो
@EnableWebMvc
इस प्रकार स्प्रिंग बूटWebMvcAutoConfiguration
वर्ग को अक्षम कर रहा है । (मैंWebMvcAutoConfiguration
कक्षा के कोड की प्रतिलिपि बना सकता हूं और फ़ेविकॉन कार्यक्षमता को हटा सकता हूं ) - फ़ेविकॉन फ़ाइल को मध्यस्थ स्थान पर रखने की स्वतंत्रता दें और इसे रिसोर्स डायरेक्टरी में रखें क्योंकि स्प्रिंग बूट की फ़ेविकॉन फ़ंक्शनलिटी की आवश्यकता होती है। और कैशिंग समस्या की उपेक्षा करें।
लेकिन न तो विकल्प संतोषजनक है।
मैं अपनी स्थिर वेब फ़ाइलों के साथ फ़ेविकॉन फ़ाइल रखना चाहता हूं (जो किसी भी निर्देशिका हो सकती है क्योंकि मैं दस्तावेज़ रूट को बदल सकता हूं) और कैशिंग समस्या को हल कर सकता हूं।
क्या मैं कुछ भूल रहा हूँ?
किसी भी सुझाव बहुत सराहना की जाएगी।
अपडेट करें
BTW, इस कारण मैं फ़ेविकॉन और अन्य स्थिर फ़ाइलों के स्थान को बदलना चाहता हूं। अभी के लिए यह मुख्य रूप से विकास का पर्यावरण मुद्दा है।
मैं एक सिंगल पेज वेब एप्लिकेशन (एसपीए) बना रहा हूं।
पुस्तकालय / फ़्रेमवर्क:
- सर्वर साइड के लिए, मैं स्प्रिंग का उपयोग करता हूं। (बेशक)
- क्लाइंट (वेब ब्राउज़र) पक्ष के लिए, मैं AngularJS का उपयोग करता हूं।
उपकरण:
- सर्वर साइड के लिए, मैं स्प्रिंग टूल सूट का उपयोग करता हूं।
- क्लाइंट साइड के लिए, मैं WebStorm का उपयोग करता हूं।
मुख्य निर्देशिका संरचना:
ProjectRoot\
src\
bin\
build\
webapp\
build.gradle
- src: जहाँ मेरा स्प्रिंग जावा सोर्स फाइल रहता है।
- बिन: जहां स्प्रिंग टूल सूट इसका निर्माण आउटपुट देता है।
- बिल्ड: जहां 'ग्रेडल बिल्ड' अपने बिल्ड आउटपुट को रखता है।
- webapp: जहाँ मेरे क्लाइंट सोर्स फाइल्स (.js, .css, .htm और favicon) रहते हैं। इस प्रकार यह WebStorm प्रोजेक्ट डायरेक्टरी है। (यदि आवश्यक हो तो मैं निर्देशिका का नाम बदल सकता हूं)
मुझे क्या चाहिए:
- मेरे स्प्रिंग सर्वर एप्लिकेशन को पुनः बनाने / पुनः आरंभ किए बिना मेरे क्लाइंट कोड को संशोधित करने और परीक्षण करने में सक्षम होने के लिए। तो, क्लाइंट कोड को जार फ़ाइल में नहीं डाला जाना चाहिए। वैसे भी स्प्रिंग टूल सूट में जार फ़ाइल बिलकुल नहीं बनती है (कम से कम वर्तमान कॉन्फ़िगरेशन के लिए)
- क्लाइंट कोड के साथ मेरे स्प्रिंग सर्वर एप्लिकेशन का परीक्षण करने में सक्षम होने के लिए, आसानी से स्प्रिंग टूल सूट आउटपुट और ग्रेडल आउटपुट के बीच स्विच करना। इसलिए, क्लाइंट कोड को
build
उपनिर्देशिका (वास्तव मेंbuild\libs
) में सर्वर एप्लिकेशन औरbin
निर्देशिका में सर्वर एप्लिकेशन दोनों से सुलभ होना चाहिए । - जब मैं क्लाइंट कोड को संशोधित करता हूं, तो यह तुरंत वेब ब्राउज़र के लिए उपलब्ध होना चाहिए। इसलिए ब्राउज़र को इसे अनिश्चित काल तक कैश नहीं करना चाहिए, और हमेशा अपडेट के लिए सर्वर से पूछना चाहिए।
- जब तैनात किया जाता है, तो क्लाइंट कोड सर्वर एप्लिकेशन के पुनर्निर्माण / पुनः आरंभ किए बिना संशोधित होना चाहिए। तो क्लाइंट कोड को जार फ़ाइल में नहीं डाला जाना चाहिए।
कैश समस्या के बारे में:
AddResourceHandlers () पर setCachePeriod (0) के बिना, Google Chrome अपडेट के लिए सर्वर से पूछे बिना, फ़ाइल को अनिश्चित काल तक कैश करता है। यह सर्वर से कनेक्ट भी नहीं होता है। (Google इंजीनियरों का कहना है कि व्यवहार सही है।) इसलिए, मैं केवल इतना कर सकता हूं कि ब्राउज़र कैश को मैन्युअल रूप से साफ़ करें। यह विकास पर्यावरण पर निराशाजनक है, और उत्पादन पर्यावरण पर अस्वीकार्य है।
BTW, express.js मॉड्यूल Node.js पर उचित डिफ़ॉल्ट HTTP हेडर देता है ताकि Google Chrome सर्वर से अपडेट के लिए पूछ सके। जब मैंने 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;
}
}
बीन नामों पर ध्यान दें। मैंने नाम क्लैश से बचने के लिए 'माय' जोड़ा है।
स्वतः-भरण अनुप्रयोग संदर्भ स्वयं ही अटपटा लगता है, लेकिन इसमें कोड की नकल करने के लिए यह आवश्यक था org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration.addResourceLocations()
।
अब मेरे पास कैवलिंग समस्या से मुक्त एक फ़ेविकॉन हैंडलर है, और मैं फ़ेविकॉन फ़ाइल को कहीं भी रख सकता हूँ।
धन्यवाद।
classpath:/static
उदाहरण के लिए किसी भी और से नहीं दिया जाएगा )। (यही कारण है कि बूट में फ़ेविकॉन समर्थन अपने स्वयं के हैंडलर में है जो मुझे लगता है।)