2010-10-13 12 views
8

Chcę napisać mój tag (rozszerza się TagSupport) w mojej wiosennej ramie. W mojej klasie tagów będzie używana usługa, która powinna automatycznie wstrzykiwać wiosną. Ale zawsze otrzymuję wartość null, wydaje się, że wiosna nie może wstrzyknąć instancji usługi w mojej klasie znaczników.Jak napisać tag w moim projekcie wiosennym?

Kod jest jak poniżej:

public class FetchTagNameTag extends TagSupport { 

    @Autowired 
    private TaskService taskService; 
    ... 

taskService zawsze ma wartość null.

Jak mogę rozwiązać ten problem? Dzięki.

Odpowiedz

4

Obiekty znaczników JSP nie są zarządzane przez Spring, są zarządzane przez kontener serwletu. W rezultacie nie można automatycznie wyposażyć treści w swoje tagi.

Jeśli chcesz zdobyć ziarna z wiosennego kontekstu aplikacji, twój kontroler Spring MVC musi ustawić komponent bean jako atrybut żądania (używając request.setAttribute()), aby obiekt znacznika mógł go uzyskać.

+0

Dzięki, odpowiedziałeś na moje pytanie. – Tom

0

Sprawdź te pakiety Wiosna w Dokumentach referencyjnych wiosną i źródła wiosny:

  • org.springframework.web.servlet.tags
  • org.springframework.web.servlet.tags.form
  • Jeśli nic więcej, te pokażą ci, jak programiści wiosną napisali tagi sprężyn.

    +0

    Dzięki, sprawdzę to później. – Tom

    1

    Opisz swoją implementację tagu za pomocą @Configurable i dodaj <context:component-scan base-package="your.webapp"> do konfiguracji Spring.

    +0

    Niestety, twoje podejście nie działa dla mnie. Czy jesteś pewny co do tej metody? – Tom

    15

    Spróbuj, korzystając z RequestContextAwareTag. Oferuje metody uzyskiwania RequestContext, a następnie WebApplicaitonContext. Spójrz na here.

    +0

    to jest takie proste i po prostu działa. Nie wiem, dlaczego głosowano za odpowiedzią na używanie kontrolera MVC do autowirowania. – checklist

    +0

    Nie tylko jest to proste i działa - to lepsza odpowiedź. Druga odpowiedź, w której kontroler ustawia atrybut żądania, wymaga dokumentacji w taglib i dodatkowego kodu przez każdego, kto używa tego taglib na stronach, które nie używają tego samego kontrolera. Ma również efekty uboczne, które nie działają, gdyby ktoś zapomniał ustawić atrybut żądania na nowej, niepowiązanej stronie. –

    +1

    'getRequestContext(). GetWebApplicationContext(). GetBean (MyBean.class)'. Wreszcie!! – Michele

    0

    Co można zrobić, to utworzyć statyczną metodę tak:

    public static void autowireAllFor(Object target) { 
        AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor(); 
        bpp.setBeanFactory(...yourBeanFactory...); 
        bpp.processInjection(target); 
    } 
    

    a następnie dla tagu można zrobić

    public class YourTag extends TagSupport { 
    
        @Autowired 
        private SomeBean someBean; 
    
        public YourTag() { 
         YourHelperClass.autowireAllFor(this); 
        } 
    } 
    

    Oczywistą wadą tego podejścia jest to, że trzeba zrobić to dla każdego konstruktora, ale jako TagSupport ma tylko jeden, nie powinno to stanowić problemu. Można pójść jeszcze krok dalej i stworzyć superklasę pomocnika, który zawsze gwarantuje autowiring:

    public class SpringTagSupport extends TagSupport { 
        public SpringTagSupport() { 
         super(); 
         YourHelperClass.autowireAllFor(this); 
        } 
    } 
    

    reszta jest tak proste, jak rozszerzenie swoich klas z SpringTagSupport.

    +0

    Cześć, dzięki. Gdzie powinna być statyczna metoda autowireAllFor? – Tom

    +0

    Nie ma znaczenia - po prostu zatrzymaj go w klasie użytkowej. W tym przykładzie jest to pokazane w "YourHelperClass". – mindas

    0

    Pierwszy to piszę:

    public abstract class SpringSuportedTag extends SimpleTagSupport{ 
    
    protected WebApplicationContext _applicationContext; 
    
    protected WebApplicationContext getSpringContext(){ 
        PageContext pageContext = (PageContext) getJspContext(); 
        if(_applicationContext==null){ 
         _applicationContext = RequestContextUtils.getWebApplicationContext(
           pageContext.getRequest(), 
           pageContext.getServletContext() 
          ); 
         initCustomBeans(); 
        } 
        return _applicationContext; 
    } 
    
    protected abstract void initCustomBeans(); 
    
    /** 
    * Deprecated for inserting extra logic. Use {@link #doTagWithSpring()} instead. 
    */ 
    @Override 
    @Deprecated 
    public void doTag() throws JspException, IOException { 
        getSpringContext(); 
        doTagWithSpring(); 
    } 
    
    
    abstract void doTagWithSpring() throws JspException, IOException; 
    } 
    

    i użytkowania:

    public class SlotTag extends SpringSuportedTag { 
    
    // @Resource(name="userDetailHolder") 
    // not work here 
    UserDetailHolder userDetail; 
    
    private String slotname; 
    
    public String getSlotname() { 
        return slotname; 
    } 
    
    public void setSlotname(String slotname) { 
        this.slotname = slotname; 
    } 
    
    @Override 
    void doTagWithSpring() throws JspException, IOException { 
        PageContext pageContext = (PageContext) getJspContext(); 
        String userDetailCode = pageContext.getAttribute(InitWidgetUserTag.KAY_USERDETAIL, PageContext.PAGE_SCOPE).toString(); 
        userDetail.init(userDetailCode); 
        String pageID = pageContext.getAttribute(InitWidgetUserTag.KAY_PAGEID, PageContext.PAGE_SCOPE).toString(); 
    
        getJspContext().getOut().println("<b>slot for user:"+userDetail.getUserId()+"</b>"); 
    } 
    
    @Override 
    protected void initCustomBeans() { 
        userDetail = (UserDetailHolder) getSpringContext().getBean("userDetailHolder"); 
    
    } 
    } 
    

    To praca. Ale niż znalazłem to: Spring supported Tag Libraries. Prawda w moim progresie nadal korzystam z własnego rozwiązania.

    0

    Zastosowanie: -

    import org.springframework.web.servlet.tags.RequestContextAwareTag; 
    
    public class FetchTagNameTag extends RequestContextAwareTag { 
    
    // @Autowired 
    
        // private TaskService taskService; 
    
        @Override 
    
        protected int doStartTagInternal() throws Exception { 
    
    TaskService taskService= getRequestContext().getWebApplicationContext().getBean(TaskService.class); 
    
    
        return 0; 
        } 
    
    Powiązane problemy