1

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

所以我专门化了br.com.caelum.vraptor.view.DefaultPathResolveras

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

我不能像${mycmp.name}在我的速度模板 (.vm) 中那样引用它,但如果我使用 .jsp,它就可以正常工作。

为了解决它,我专门使用br.com.caelum.vraptor.core.DefaultResultas

@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在速度模板中包含组件?

4

1 回答 1

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

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

当然,如果您只包含几个 bean,那么第一个解决方案应该足够了。此致

于 2015-01-20T11:53:17.787 回答