【问题标题】:How to write tag in my spring project?如何在我的春季项目中编写标签?
【发布时间】:2011-04-24 21:44:04
【问题描述】:

我想在我的 spring 框架中编写我的标签(扩展 TagSupport)。在我的标签类中,将使用一些应该由 spring 自动注入的服务。但我总是得到 null,似乎 spring 无法在我的标签类中注入服务实例。

代码如下:

public class FetchTagNameTag extends TagSupport {

   @Autowired
   private TaskService taskService;
   ...

taskService 始终为空。

我该如何解决这个问题? 谢谢。

【问题讨论】:

    标签: java spring jsp spring-mvc jsp-tags


    【解决方案1】:

    使用:-

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

    【讨论】:

      【解决方案2】:

      首先我写这个:

      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。在我的项目中,我仍然使用自己的解决方案。

      【讨论】:

        【解决方案3】:

        你可以做的是创建一个这样的静态方法:

        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扩展你的类一样简单。

        【讨论】:

        • 没关系 - 只需将其保存在某个实用程序类中即可。在这个例子中,它被描绘在 YourHelperClass 内部。
        【解决方案4】:

        尝试使用RequestContextAwareTag。它将为您提供获取 RequestContext 和 WebApplicaitonContext 的方法。看看here

        【讨论】:

        • 这很简单,而且很有效。我不知道为什么使用MVC控制器自动装配的答案被投票。
        • 这不仅简单而且有效 - 这是更好的答案。涉及控制器设置请求属性的另一个答案需要标记库中的文档以及在不使用相同控制器的页面上使用此标记库的任何人的额外代码。如果有人忘记在新的、不相关的页面上设置请求属性,它还会产生无法工作的副作用。
        • getRequestContext().getWebApplicationContext().getBean(MyBean.class)。终于!!
        【解决方案5】:

        使用@Configurable 注释您的标签实现并将&lt;context:component-scan base-package="your.webapp"&gt; 添加到您的Spring 配置中。

        【讨论】:

        • 对不起,你的方法对我不起作用。你确定这个方法吗?
        【解决方案6】:

        在 spring 参考文档和 spring 源代码中查看这些 spring 包:

      • org.springframework.web.servlet.tags
      • org.springframework.web.servlet.tags.form
      • 如果不出意外,这些将向您展示 Spring 开发人员如何编写 Spring 标签。

        【讨论】:

        • 谢谢,我稍后再看看。
        【解决方案7】:

        JSP 标签对象不由 Spring 管理,它们由 servlet 容器管理。因此,您无法将内容自动连接到您的标签中。

        如果您需要从 spring appcontext 中获取 bean,那么您的 Spring MVC 控制器需要将 bean 设置为请求属性(使用request.setAttribute()),以便标记对象可以获取它。

        【讨论】:

        • 谢谢,你回答了我的问题。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-09-07
        • 2013-06-27
        • 1970-01-01
        • 1970-01-01
        • 2015-04-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多