Spring MVC 和 Mustache - 更改 Mustache 的编译器默认空值

Spring MVC and Mustache - change Mustache's compiler default null value

我在为 Spring MVC 在我的项目中找到 here 覆盖 Mustache 默认配置时遇到了一些问题。

我的理解是 mustache.java 默认情况下会在模板找到解析为 null 的变量时引发 MustacheException。我希望 Mustache 编译器将此类值解析为空字符串。

我尝试使用 nullValue(String nullValue) 函数设置适当的行为,如下面的代码所示,但它似乎没有任何效果。我知道明显的解决方案是将 phoneNumber 属性设置为空值,但我真的很想了解为什么这个特定代码不起作用。

您会在下面找到我用来测试此行为的代码,其中包括一个 Employee 实体,该实体故意不在其构造函数和相关代码片段中实例化其 phoneNumber 成员值.

提前致谢!

pom.xml

<dependency>
  <groupId>com.github.sps.mustache</groupId>
  <artifactId>mustache-spring-view</artifactId>
  <version>1.3</version>
</dependency>
<!-- jmustache -->
<dependency>
  <groupId>com.samskivert</groupId>
  <artifactId>jmustache</artifactId>
  <version>1.10</version>
</dependency>
<!-- mustache.java -->
<dependency>
  <groupId>com.github.spullara.mustache.java</groupId>
  <artifactId>compiler</artifactId>
  <version>0.8.17</version>
</dependency>

Employee.java

public class Employee {
  protected String firstName;
  protected String lastName;
  protected String phoneNumber;

  public Employee() { }
  public Employee(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  // Getter and Setters for all attributes
}

getViewResolver

@Bean
public ViewResolver getViewResolver(ResourceLoader resourceLoader) {
  MustacheViewResolver mustacheViewResolver = new MustacheViewResolver();
  mustacheViewResolver.setPrefix("/src/main/resources/templates/");
  mustacheViewResolver.setSuffix(".html");
  mustacheViewResolver.setCache(false);
  mustacheViewResolver.setContentType("text/html;charset=utf-8");

  JMustacheTemplateLoader mustacheTemplateLoader = new JMustacheTemplateLoader();
  mustacheTemplateLoader.setResourceLoader(resourceLoader);

  JMustacheTemplateFactory mustacheTemplateFactory = new JMustacheTemplateFactory();
  mustacheTemplateFactory.setTemplateLoader(mustacheTemplateLoader);

  mustacheTemplateFactory.setCompiler(Mustache.compiler().nullValue(" "));

  mustacheViewResolver.setTemplateFactory(mustacheTemplateFactory);
  return mustacheViewResolver;
}

员工控制人

@Autowired
private EmployeeRepository repository;

...

@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public String viewEmployee(@PathVariable Long id, Model model) {
  model.addAttribute("employee", repository.findOne(id));
  return "employee_view";
}

employee_view.html

<!DOCTYPE html>
<html>
  <body>
  <ul>
    {{#employee}}
    <li> First Name: {{firstName}}
    <li> Last Name: {{lastName}}
    <li> Phone Number: {{phoneNumber}}
    {{/employee}}
  </ul>
  </body>
</html>

我现在正在使用 spring-boot.1.2.5.RELEASE。

如果你查看了org.springframework.boot.autoconfigure.mustache.MustacheAutoConfiguration的源代码(line73~78),你打电话告诉你defaultValue是不可配置的!!!

也许您应该自己制作一个新的 spring-boot-starter 来修复它。 或者您可以使用 freemarkervelocity 来代替它。

或者您可以在 ApplicationContext 启动时通过 BeanPostProcessor 破解它。

像这样:

@Bean
public BeanPostProcessor mutacheHackerBeanPostProcessor() {
    return new BeanPostProcessor() {
        private static final String BEAN_NAME = "mustacheCompiler";

        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if (ClassUtils.isAssignable(bean.getClass(), Mustache.Compiler.class) || BEAN_NAME.equals(beanName)) {
                System.out.println("----------");
                System.out.println("hack ok!!!");
                System.out.println("----------");
                Mustache.Compiler compiler = (Mustache.Compiler) bean;
                return compiler.defaultValue("").nullValue("");
            }

            return bean;
        }
    };
}

祝你好运!

你试过吗?

<!DOCTYPE html>
<html>
<body>
<ul>
{{#employee}}
  <li> First Name: {{firstName}}
  <li> Last Name: {{lastName}}
  <li> Phone Number:{{#phoneNumber}} {{phoneNumber}} {{/phoneNumber}}     {{^phoneNumber}} NA {{/phoneNumber}}
{{/employee}}
</ul>
</body>

我设法通过创建自定义 Mustache 自动配置来做到这一点。首先排除默认的 MustacheAutoConfiguration。

@SpringBootApplication
@EnableAutoConfiguration(exclude = MustacheAutoConfiguration.class)
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

然后为 Mustache 创建新的自动配置。

@Configuration
@EnableConfigurationProperties({MustacheProperties.class})
public class LayoutAutoConfiguration extends MustacheAutoConfiguration {

    public LayoutAutoConfiguration(MustacheProperties mustache, Environment environment, ApplicationContext applicationContext) {
        super(mustache, environment, applicationContext);
    }

    @Override
    public Mustache.Compiler mustacheCompiler(Mustache.TemplateLoader mustacheTemplateLoader) {
        return super.mustacheCompiler(mustacheTemplateLoader).defaultValue("");
    }
}

Spring 引导 1.5.1.RELEASE 与 jmustache 1.13.