我可以使用 Freemarker 从 Dropwizard 视图创建电子邮件吗?

Ros*_*iar 1 freemarker dropwizard

我有一个.ftl资源文件,用于通过 RESTful 端点显示它,我还想通过电子邮件将此表示发送给用户。Dropwizard 对视图做了一些魔术,允许将填充的模板主体返回到我的 REST 端点(我假设为 aString或类似 a 的更高级的东西StringBuilder)。

有没有办法在View不使用其余客户端的情况下请求 a 的主体?我也不想让我的电子邮件表示依赖于HTMLREST 客户端中使用的内容,所以没有建议只将电子邮件路由到wget点击端点的内容。

dropwizard source来看,似乎我需要ViewRenderer从某个地方获取 a ,可能是通过使用ServiceLoader.load()- 因为这是ViewBundle获取副本的方式(如果您不提供任何副本)。

pan*_*adb 5

正如评论中指出的那样,Rossiar 是完全正确的。

实现这一点的方法是使用与ViewRendererDW相同的方法。不必使用 ServiceLocator 模式,因为它们所做的只是调用构造函数。

一个小例子:

public class MyView extends View {

    private TestPerson person;

    protected MyView(TestPerson person) {
        super("TestView.ftl");
        this.person = person;
    }

    public TestPerson getPerson() {
        return person;
    }

    public static class TestPerson {

        public String getName() {
            return "PandaaDb";
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

这是我们要渲染的视图类。注意:Freemaker 希望这些方法是公开的,否则它会拒绝访问它们。

对应的ftl文件:

<#-- @ftlvariable name="" type="viewTest.Two.MyView" -->
<html>
    <body>
        <h1>Hello, ${person.name?html}</h1>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

然后,在我的主要内容中,我们可以执行以下操作:

public class ViewTestMain {

    public static void main(String[] args) throws UnsupportedEncodingException {
        FreemarkerViewRenderer render = new FreemarkerViewRenderer();

        TestPerson p = new TestPerson();
        MyView v = new MyView(p);

        ByteArrayOutputStream st = new ByteArrayOutputStream();

        try {
            render.render(v, Locale.getDefault(), st);
        } catch (IOException e) {
            e.printStackTrace();
        }

        String string = st.toString("UTF-8");
        System.out.println(string);
    }
}
Run Code Online (Sandbox Code Playgroud)

或者,我们可以通过查询服务定位器并检查每个 ViewRenderer(是否适用)来重用 DW 为我们布置的模式。

public class ViewTestMain {

    public static void main(String[] args) throws UnsupportedEncodingException {
        ServiceLoader<ViewRenderer> load = ServiceLoader.load(ViewRenderer.class);
        TestPerson p = new TestPerson();
        MyView v = new MyView(p);

        ByteArrayOutputStream st = new ByteArrayOutputStream();

        ViewRenderer r = null;
        for(ViewRenderer vr : load) {
            if(vr.isRenderable(v)) {
                r = vr;
            }
        }

        try {
            r.render(v, Locale.getDefault(), st);
        } catch (IOException e) {
            e.printStackTrace();
        }

        String string = st.toString("UTF-8");
        System.out.println(string);
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,您可以通过简单地将实现添加到服务来添加自己的 ServiceRenderer。这是通过将具有 ServiceRender 接口名称(完全限定)的文件放入

src/main/resources/META-INF/services
Run Code Online (Sandbox Code Playgroud)

然后将完全限定的实现名称添加到该文件中。这将使它可被发现。

这将打印:

<html>
    <body>
        <h1>Hello, PandaaDb</h1>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

现在,我假设您已将 DAO/Service 层与 jersey 层分开。在这种情况下,您可以编写一个客户端来简单地访问相同的模型对象,以 DW 通常的方式实例化视图,然后简单地通过渲染运行它们。

希望有所帮助,

阿图尔