2011-09-23 12 views
5

में स्प्रिंग MVC एनोटेट नियंत्रक मैं src/मुख्य/ग्रूवी में इस राशि/...ग्रूवी

package com.mycompany.web; 
// imports.... 

@Controller 
class GroovyController { 

    @RequestMapping("/status_groovy") 
    public @ResponseBody String getStatus() { 
     return "Hello World from groovy!"; 
    } 
} 

Maven 3 और वसंत 3.1 (मील का पत्थर) का उपयोग करना। स्प्रिंग एमवीसी जावा नियंत्रकों के लिए पूरी तरह से अच्छी तरह से काम करता है और सब कुछ ठीक स्थापित किया गया है। ग्रोवी क्लास ठीक से संकलित करता है और जावा नियंत्रक कक्षाओं के साथ classes निर्देशिका में पाया जा सकता है।

मेरे पास एक ही पैकेज में जावा (जावाकंट्रोलर) में लिखा गया समान नियंत्रक है लेकिन स्रोत/मुख्य/जावा के तहत और वसंत और मैप द्वारा इसे ठीक से उठाया जा रहा है और जब मैं यूआरएल दबाता हूं तो स्क्रीन पर प्रतिक्रिया देख सकता हूं।

package com.mycompany.web; 
// imports.... 

@Controller 
class JavaController { 

    @RequestMapping("/status") 
    public @ResponseBody String getStatus() { 
     return "Hello World!"; 
    } 
} 

जेट्टी लॉग में कोई त्रुटि के साथ सामान्य रूप से शुरू होता है, लेकिन में मैं ग्रूवी यूआरएल देखना न जबकि मैं जावा एक देख सकते हैं मैप किया जा रहा है।

2011-09-23 16:05:50,412 [main] INFO org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/status],methods=[],params=[],headers=[],consumes=[],produces=[]}" onto public java.lang.String com.mycompany.web.JavaController.getStatus() 

सभी सेटिंग ठीक के रूप में एप्लिकेशन के अन्य भागों एनोटेशन (घटक-स्कैन आदि) के साथ ठीक काम कर रहे हैं कर रहे हैं, बस यह है कि मैं यूआरएल GroovyController में मैप नहीं मिल सकता है

किसी को भी व्याख्या कर सकते हैं क्या groovy काम में लिखे Controller एस प्राप्त करने के लिए करने की जरूरत है?

पीएस: मैं स्क्रिप्ट चलाने के लिए ग्रोवी सर्वलेट से परहेज कर रहा हूं क्योंकि बीन इंजेक्शन और यूआरएल पथ मैपिंग की बात आती है क्योंकि इसमें बड़ी गिरावट आई है।

उत्तर

1

दुर्भाग्यवश, यदि आप इसे ग्रोवी में चलाना चाहते हैं तो आपको अपने कंट्रोलर क्लास के लिए एक इंटरफेस बनाना होगा और विधि परिभाषाओं को भी एनोटेट करना होगा। वसंत Cglib का उपयोग कर अपनी कक्षा के लिए एक प्रॉक्सी बनाता है। हालांकि, आपके नियंत्रक के लिए कस्टम इंटरफेस बनाने के बिना वसंत groovy.lang.GroovyObject पर प्रॉक्सी कर रहा है क्योंकि सभी ग्रोवी ऑब्जेक्ट्स डिफ़ॉल्ट रूप से उस इंटरफ़ेस को कार्यान्वित करते हैं।

interface GroovyControllerInterface { 
    @RequestMapping("/status_groovy") 
    @ResponseBody String getStatus() 
} 

@Controller 
class GroovyController implements GroovyControllerInterface { 
    @RequestMapping("/status_groovy") 
    public @ResponseBody String getStatus() { 
     return "Hello World from groovy!"; 
    } 
} 
6

बेन (जिनके साथ मैं काम करता हूं) के सभी सम्मान के साथ, समस्या यह नहीं है कि वसंत एक cglib प्रॉक्सी बना रहा है। इसके बजाय, यह गतिशील जेडीके (या इंटरफ़ेस-आधारित) प्रॉक्सी बना रहा है। प्रॉक्सी बनाने की यह विधि केवल लक्ष्य के कार्यान्वित इंटरफेस में घोषित विधियों को लागू कर सकती है। आप वास्तव में चाहते हैं स्प्रिंग एक cglib प्रॉक्सी बनाने के लिए, जो एक प्रॉक्सी बनाता है जो लक्षित ऑब्जेक्ट का उप-वर्ग है और इसलिए इसके सभी सार्वजनिक तरीकों को फिर से बना सकता है। जब तक आप अन्यथा निर्दिष्ट नहीं करते हैं, तो स्प्रिंग एक cglib प्रॉक्सी बनाएगी यदि लक्ष्य ऑब्जेक्ट किसी भी इंटरफेस को लागू नहीं करता है, और अन्यथा इंटरफ़ेस-आधारित प्रॉक्सी। चूंकि सभी ग्रोवी ऑब्जेक्ट्स ग्रोवी ऑब्जेक्ट को लागू करते हैं, इसलिए आपको इंटरफ़ेस-आधारित प्रॉक्सी मिल रही है, भले ही आपने अपने ग्रोवी नियंत्रक में किसी भी इंटरफ़ेस को स्पष्ट रूप से कार्यान्वित नहीं किया हो। बेन का समाधान उसमें सही है यदि आप अपने सभी नियंत्रक विधियों के साथ एक इंटरफेस बनाते हैं, तो आपको अपेक्षित व्यवहार मिल जाएगा। एक विकल्प है जो बीनफैक्टरीपोस्टप्रोसेसर बनाने के लिए है जो स्प्रिंग को कक्षाओं के लिए cglib प्रॉक्सी बनाने के लिए निर्देश देता है जो ग्रोवी ऑब्जेक्ट और केवल ग्रोवी ऑब्जेक्ट को लागू करता है। कोड यह रहा:

/** 
* Finds all objects in the bean factory that implement GroovyObject and only GroovyObject, and sets the 
* AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE value to true. This will, in the case when a proxy 
* is necessary, force the creation of a CGLIB subclass proxy, rather than a dynamic JDK proxy, which 
* would create a useless proxy that only implements the methods of GroovyObject. 
* 
* @author caleb 
*/ 
public class GroovyObjectTargetClassPreservingBeanFactoryPostProcessor implements BeanFactoryPostProcessor { 
    private static final Logger logger = LoggerFactory.getLogger(GroovyObjectTargetClassPreservingBeanFactoryPostProcessor.class); 

    @Override 
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { 
     for (String beanDefName : beanFactory.getBeanDefinitionNames()) { 
      BeanDefinition bd = beanFactory.getBeanDefinition(beanDefName); 
      //ignore abstract definitions (parent beans) 
      if (bd.isAbstract()) 
       continue; 
      String className = bd.getBeanClassName(); 
      //ignore definitions with null class names 
      if (className == null) 
       continue; 
      Class<?> beanClass; 
      try { 
       beanClass = ClassUtils.forName(className, beanFactory.getBeanClassLoader()); 
      } 
      catch (ClassNotFoundException e) { 
       throw new CannotLoadBeanClassException(bd.getResourceDescription(), beanDefName, bd.getBeanClassName(), e); 
      } 
      catch (LinkageError e) { 
       throw new CannotLoadBeanClassException(bd.getResourceDescription(), beanDefName, bd.getBeanClassName(), e); 
      } 

      Class<?>[] interfaces = beanClass.getInterfaces(); 
      if (interfaces.length == 1 && interfaces[0] == GroovyObject.class) { 
       logger.debug("Setting attribute {} to true for bean {}", AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, beanDefName); 
       bd.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, true); 
      } 
     } 
    } 
} 

बस अपने संदर्भ है, और देखा में इस प्रकार का एक सेम शामिल हैं! आप इंटरफेस को परिभाषित किए बिना ग्रोवी नियंत्रकों को प्राप्त कर सकते हैं।

+0

मैं तुम्हें अपने जवाब के लिए सेम परिभाषा जोड़ने के सुझाव देते हैं। – Zeki

2

मैं अलग होना चाहता हूं। एक इंटरफ़ेस को लागू करने की कोई आवश्यकता नहीं है। यहां समस्या यह है कि डिफ़ॉल्ट AnnotationMethodHandlerAdapter प्रॉक्सी से एनोटेशन नहीं पढ़ता है। इसलिए हमें इस प्रॉक्सी जागरूक एनोटेशन मैथ्यू हैंडलर एडाप्टर बनाना होगा जो वसंत के डिफ़ॉल्ट AnnotationMethodHandlerAdapter को बढ़ाता है। हमें स्प्रिंग कॉन्फ़िगरेशन xml फ़ाइल में इस ProxyAwareAnnotationMethodHandlerAdapter के लिए एक बीन को तुरंत चालू करने की आवश्यकता है। नोट: यह सुविधा वसंत 3.x में उपलब्ध नहीं है, लेकिन वसंत 4.0 ग्रोवी बीन्स का समर्थन करेगी, इसलिए इस सुविधा को कवर किया जाना चाहिए।

//ProxyAwareAnnotationMethodHandlerAdapter.java 

    package name.assafberg.spring; 

    import javax.servlet.http.HttpServletRequest; 
    import javax.servlet.http.HttpServletResponse; 

    import org.springframework.aop.TargetSource; 
    import org.springframework.aop.framework.Advised; 
    import org.springframework.web.servlet.ModelAndView; 
    import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter; 

    /** 
    * Add proxy awareness to <code>AnnotationMethodHandlerAdapter</code>. 
    * 
    * @author assaf 
    */ 
    public class ProxyAwareAnnotationMethodHandlerAdapter extends AnnotationMethodHandlerAdapter { 

     /** 
     * @param request 
     * @param response 
     * @param handler 
     * @return 
     * @throws Exception 
     * @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, java.lang.Object) 
     */ 
     @Override 
     public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
      handler = unwrapHandler(handler); 

      return super.handle(request, response, handler); 
     } 

     /** 
     * @param handler 
     * @return 
     * @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter#supports(java.lang.Object) 
     */ 
     @Override 
     public boolean supports(Object handler) { 
      handler = unwrapHandler(handler); 

      return super.supports(handler); 
     } 

     /** 
     * Attempt to unwrap the given handler in case it is an AOP proxy 
     * 
     * @param handler 
     * @return Object 
     */ 
     private Object unwrapHandler(Object handler) { 
      if (handler instanceof Advised) { 
       try { 
        TargetSource targetSource = ((Advised) handler).getTargetSource(); 
        return targetSource.getTarget(); 

       } catch (Exception x) { 
        throw new RuntimeException(x); 
       } 

      } else { 
       return handler;  
      }  
     } 

    } 

वसंत कॉन्फ़िगरेशन XML फ़ाइल में निम्न होना चाहिए। AnnotationMethodHandlerAdapter का एक बीन बनाने के बजाय हमें एक प्रॉक्सीएवेयरएनोटेशनMethodHandlerAdapter बीन बनाना होगा।

<beans ......... 
... 
... 
     <bean class="full.qualified.name.of.ProxyAwareAnnotationMethodHandlerAdapter" /> 
... 
... 
     <lang:groovy script-source="classpath:com/example/mysample.groovy refresh-check-delay="1000" /> 
</beans> 

इसके अलावा वसंत विन्यास एक्सएमएल एक SAX पार्सर (घटना घटना के आधार पर) का उपयोग कर फ़ाइल को पार्स करता है। इसलिए, वसंत के लिए ग्रोवी स्क्रिप्ट के भीतर एनोटेशन को समझने के लिए, ग्रोवी बीन्स (टैग का उपयोग करके) ProxyAwareAnnotationMethodHandlerAdapter के बाद बनाया जाना चाहिए।

आशा से मदद करता है

संदर्भ: http://forum.springsource.org/showthread.php?47271-Groovy-Controller

+0

बहुत बढ़िया! उस वर्ग ने मेरा दिन बनाया। अब मेरे पास ग्रोवी नियंत्रक और सेवाएं हैं। धन्यवाद – Jason

संबंधित मुद्दे