2014-11-18 3 views
7

के साथ दो बार बुलाया जब मैं कस्टम HandlerInterceptor का उपयोग कर रहा हूं और मेरा नियंत्रक DeferredResult लौटाता है, तो preHandle प्रत्येक कस्टम अनुरोधकर्ता को दो बार अनुरोध किया जाता है। एक खिलौना उदाहरण पर विचार करें।स्प्रिंग एमवीसी इंटरसेप्टर हैंडलर ने डेफर्रेड रीसल्ट

मेरे कस्टम इंटरसेप्टर:

public class MyInterceptor implements HandlerInterceptor { 
    static int i = 0; 

    @Override 
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
     System.out.println(i++); 
     return true; 
    } 

    @Override 
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { 
    } 

    @Override 
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 
    } 
} 

मेरे वसंत जावा विन्यास:

@Configuration 
@EnableWebMvc 
public class ApplicationConfiguration extends WebMvcConfigurerAdapter { 

    @Override 
    public void addInterceptors(InterceptorRegistry registry) { 
     registry.addInterceptor(new MyInterceptor()); 
    } 
} 

मेरे नियंत्रक:

@Controller 
public class MyController { 

    @RequestMapping(value = "/test", method = RequestMethod.GET) 
    public DeferredResult<String> test() { 
     DeferredResult<String> df = new DeferredResult<String>(); 
     df.setResult("blank"); 
     return df; 
    } 
} 

तो, प्रत्येक पृष्ठ लोड पर मैं preHandle विधि से दो outputs देखना । हालांकि, अगर मैं "खाली" टेम्पलेट (DeferredResult के बजाय "रिक्त" टेम्पलेट के साथ) को वापस करने के लिए MyController संशोधित करता हूं, तो मुझे प्रत्येक पृष्ठ लोड पर preHandle से केवल एक आउटपुट दिखाई देता है।

तो, मेरा प्रश्न यह है कि preHandle दो बार बुलाया जाता है जब मैं DeferredResult का उपयोग करता हूं और क्या इससे बचना संभव है?

+0

देखें [इस] (http://stackoverflow.com/questions/15357990/understanding-the-spring-mvcs-deferredresult-class-in-the-context-of-the-spring) जो व्यवहार में विस्तार से समझाया गया है। –

+0

@JavaBond क्या आप कुछ और विवरण प्रदान कर सकते हैं, क्योंकि मुझे उस पोस्ट से स्पष्टीकरण नहीं मिला है। –

+0

[स्वीकृत उत्तर] से उद्धृत (http://stackoverflow.com/a/15384965/1910582) 'काफी बोल रहा है। एक DeferredResult एक खुले अनुरोध से जुड़ा हुआ है। जब अनुरोध पूरा हो जाता है, तो DeferredResult को मानचित्र से हटा दिया जाता है, और उसके बाद, ग्राहक एक नए लंबे मतदान अनुरोध को जारी करता है, जो एक नया DeferredResult उदाहरण जोड़ता है जिसका अर्थ है क्लाइंट द्वारा एक नया अनुरोध जारी किया जाता है जिस पर 'DeferredResult' संलग्न है प्रतिक्रिया। जो बदले में बताता है कि आपके पास प्रत्येक अनुरोध के लिए दो इंटरसेप्टर आमंत्रण क्यों हैं। अगर आपको और स्पष्टीकरण की आवश्यकता है तो मुझे बताएं। –

उत्तर

8

आप org.springframework.web.servlet.AsyncHandlerInterceptor उपयोग करने की आवश्यकता:

public interface AsyncHandlerInterceptor extends HandlerInterceptor { 

    void afterConcurrentHandlingStarted(
      HttpServletRequest request, HttpServletResponse response, Object handler) 
      throws Exception; 

} 

वसंत MVC निष्पादित अनुक्रम:

preHandle 
afterConcurrentHandlingStarted 
preHandle 
postHandle 
afterCompletion 
+0

मुझे चलाने के लिए 'कॉन्क्यूरेंट हैंडलिंग स्टार्टेड' विधि नहीं मिल सका। मेरा ऐप कोड निष्पादित नहीं करेगा लेकिन 'प्रीहैंडल' निष्पादित करेगा। – SomeGuyOnAComputer

2

दो आमंत्रण के बीच का अंतर request.getDispatcherType() का मूल्य का परीक्षण करके देखा जा सकता है।

1

जैसा कि मैं फ़िल्टर और इंटरसेप्टर जोड़ने की खोज कर रहा हूं, मुझे यकीन है कि एसिंक कॉलिंग के कारण यह सुनिश्चित है। आप यहां DeferredResult का उपयोग करते हैं, जो वसंत मूल धागे में फ़िल्टर करेगा और इसे फिर से एक नए थ्रेड में फ़िल्टर करेगा। यदि आप डीबग में लॉग स्तर सेट करते हैं, तो आप इस तरह लॉग देखेंगे।

15:14:06.948 [http-nio-8199-exec-5] DEBUG o.s.s.w.h.writers.HstsHeaderWriter - Not injecting HSTS header since it did not match the requestMatcher org.springframework.se[email protected]efe6068 
15:14:06.948 [http-nio-8199-exec-5] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed 
15:14:06.948 [http-nio-8199-exec-5] DEBUG o.s.b.w.f.OrderedRequestContextFilter - Cleared thread-bound request context: [email protected] 
15:14:07.148 [http-nio-8199-exec-6] DEBUG o.s.b.w.f.OrderedRequestContextFilter - Bound request context to thread: SecurityContextHolderAwareRequestWrapper[ FirewalledRequest[ [email protected]]] 

एक शब्द में, यह एक सूत्र में एक बार निष्पादित, लेकिन here're दो धागे है।

जैसा कि मैंने Google को खोला, मुझे पता चला कि कोई अच्छा समाधान नहीं है। यदि आपके पास अनुरोध में कुछ है, तो security.filter-dispatcher-type = REQUEST, ERROR फिर नया थ्रेड (async one) सुरक्षा संदर्भ नहीं मिलेगा। आपको इसे जांचना होगा और इसके अंदर फ़िल्टर श्रृंखला को रोकना होगा।

या आप जैसे tranditional सिंक कॉल का उपयोग करें:

@RequestMapping(value = "/test", method = RequestMethod.GET) 
public String test() { 
    return "blank"; 
} 

मैं एक और मददगार जवाब मिल गया। https://jira.spring.io/browse/SPR-12608

उम्मीद है कि यह मदद करता है!

1

मैंने request.getDispatcherType() के मूल्य की जांच करके @thunder का पालन किया और यह मेरे लिए काम किया।

public class MyInterceptor extends HandlerInterceptorAdapter { 

    @Override 
    public boolean preHandle(HttpServletRequest request, 
          HttpServletResponse response, 
          Object handler) throws Exception { 
     // only allows the REQUEST dispatcher and ignores the ERROR and any other dispatchers 
     // this prevents the preHandle function from running multiple times 
     if (request.getDispatcherType().name() != "REQUEST") { 
      return true; 
     } 
     // ... continue 
     return true; 
    } 
} 
संबंधित मुद्दे