VRaptor4 @Named组件在速度模板中

时间:2015-01-19 12:22:33

标签: cdi vraptor

我有一个vraptor4项目,我想使用apache velocity作为模板引擎。

所以我将br.com.caelum.vraptor.view.DefaultPathResolver专门设为

@Specializes
public class VelocityPathResolver extends DefaultPathResolver {

    @Inject
    protected VelocityPathResolver(FormatResolver resolver) {
        super(resolver);
    }

    protected String getPrefix() {
        return "/WEB-INF/vm/";
    }

    protected String getExtension() {
        return "vm";
    }
}

工作正常,但我的模板中没有@Named个组件。

@SessionScoped
@Named("mycmp")
public class MyComponent implements Serializable {
    private static final long serialVersionUID = 1L;

    private String name = "My Component";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

我不能在我的力度模板(.vm)中将其称为${mycmp.name},但如果我使用.jsp,它可以正常工作。

要解决这个问题,我将br.com.caelum.vraptor.core.DefaultResult专门设为

@Specializes
public class VelocityResult extends DefaultResult {

    private final MyComponent mycmp;

    @Inject
    public VelocityResult(HttpServletRequest request, Container container, ExceptionMapper exceptions, TypeNameExtractor extractor,
                      Messages messages, MyComponent mycmp) {

        super(request, container, exceptions, extractor, messages);
        this.mycmp = mycmp;
    }

    @PostConstruct
    public void init() {
        include("mycmp", mycmp);
    }
}

在速度模板中使用@Named组件有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

看起来CDI的@Named不能使用力度模板,但您可以实施Interceptor来完成这项工作。一个例子是:

@Intercepts
public class IncluderInterceptor {

    @Inject private MyComponent mycmp;

    @AfterCall public void after() {
        result.include("mycmp", mycmp);
        // any other bean you want to
    }
}

在一个更灵活的解决方案中思考,您可以创建一个注释并使用它来定义应该包含哪个bean ......就像这样:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Included {
}

因此,您可以在课程中添加@Included

@Included public class MyComponent { ... }

只需在IncluderInterceptor上添加accept方法:

@Intercepts
public class IncluderInterceptor {

    @Inject @Any Instance<Object> allBeans;

    @AfterCall public void after() {
        // foreach allBeans, if has @Included, so
        // include bean.getClass().getSimpleName()
        // with first letter lower case, or something
    }
}

当然,如果你只包含几个豆子,那么应该采用第一种解决方案。最好的问候