2010-10-13 3 views
8

Я хочу написать свой тег (extends TagSupport) в моем весеннем каркасе. В моем классе тегов будет использоваться некоторый сервис, который должен автоматически вводиться весной. Но я всегда получаю null, кажется, что Spring не может добавить экземпляр службы в мой класс тегов.Как написать тег в моем весеннем проекте?

код, как следующее:

public class FetchTagNameTag extends TagSupport { 

    @Autowired 
    private TaskService taskService; 
    ... 

taskService всегда нуль.

Как я могу это решить? Спасибо.

ответ

4

Объекты тегов JSP не управляются весной, они управляются контейнером сервлетов. В результате вы не можете автоувеличивать материал в своих тегах.

Если вам нужно достать бобы из весеннего контекста приложения, то ваш контроллер Spring MVC должен установить компонент в качестве атрибута запроса (используя request.setAttribute()), чтобы объект тега мог его удержать.

+0

Спасибо, вы ответили на мой вопрос. – Tom

0

Проверьте эти пружинные пакеты в весеннем справочных материалах и в источнике пружинной:

  • org.springframework.web.servlet.tags
  • org.springframework.web.servlet.tags.form
  • Если ничего другого, это покажет вам, как весенние разработчики писали весенние теги.

    +0

    Спасибо, я проверю позже. – Tom

    1

    Аннотируйте свою реализацию тегов с помощью @Configurable и добавьте <context:component-scan base-package="your.webapp"> в конфигурацию Spring.

    +0

    Извините, ваш подход не работает для меня. Вы уверены в этом методе? – Tom

    15

    Попробуйте использовать RequestContextAwareTag. Он предложит вам методы получения RequestContext, а затем WebApplicaitonContext. Посмотрите на here.

    +0

    Это так просто и просто работает. Я не знаю, почему проголосовали за использование MVC-контроллера в autwire. – checklist

    +0

    Не только это просто и работает - это лучший ответ. Другой ответ, связанный с контроллером, устанавливающим атрибут запроса, требует документации в taglib и дополнительном коде любым, кто использует этот taglib на страницах, которые не используют один и тот же контроллер. У него также есть побочные эффекты неработоспособности, если кто-то забыл установить атрибут запроса на новой, несвязанной странице. –

    +1

    'getRequestContext(). GetWebApplicationContext(). GetBean (MyBean.class)'. В заключение!! – Michele

    0

    Что вы могли бы сделать, это создать статический метод, как это:

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

    , а затем для тега вы могли бы сделать

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

    Очевидным недостатком такого подхода является то, что вы должны сделать это для каждого конструктора, но поскольку TagSupport имеет только один, это не должно быть проблемой. Вы можете пойти еще один шаг дальше и создать вспомогательный суперкласс, который всегда гарантирует: автоматическое связывание

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

    Остальное этот так же легко, как распространяющиеся классы от SpringTagSupport.

    +0

    Привет, спасибо. Где статический метод autowireAllFor должен быть? – Tom

    +0

    Не имеет значения - просто сохраните его в каком-то классе. В этом примере показано, что находится внутри 'YourHelperClass'. – mindas

    0

    Сначала я пишу это:

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

    И использование:

    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"); 
    
    } 
    } 
    

    Это работа. Но чем я нашел это: Spring supported Tag Libraries. Правда в моем проекте я все еще использую собственное решение.

    0

    Использование: -

    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; 
        } 
    
    Смежные вопросы