How to get a random integer in Freemarker template?
Is it possible to generate a random integer in Freemarker templ开发者_JAVA技巧ate?
Freemarker does not provide a random number generator at the moment. You can implement a naive random number generator using the time ( .now ) as a seed, but it should never be a critical part of your program.
You can generate a random integer in Java and pass this integer to the Freemarker template.
Here's a simple implementation of random generation using time, like Kayhadrin suggests. I didn't have the time to test if it actually works, but may be of help to someone.
http://v01ver-howto.blogspot.fi/2011/07/howto-generate-random-integer-in.html
Another option would actually be to create your own Freemarker method and inject it into the data model.
Here is an example on how to do this in Java 8:
public String generate(Map<String, Object> data, String templateLocation) throws IOException, TemplateException {
try (StringWriter writer = new StringWriter()) {
Template template = configuration.getTemplate(templateLocation);
data.put("uuid", (TemplateMethodModelEx) (list) -> UUID.randomUUID());
Random r = new Random();
// Adding method for generation of random number
data.put("randomNumber", (TemplateMethodModelEx) (list) -> r.nextInt(200));
template.process(data, writer);
return writer.toString();
}
}
In the Freemarker template you will then be able to use this method using:
${randomNumber()}
Let's say you want to add a random image out of some set to each listed item. So get a seed, and then rotate that seed in some way.
<#assign photos>
DSC_0005.jpg
DSC_0008.jpg
DSC_0013.jpg
DSC_0020.jpg
</#assign>
<#assign photos = photos?split('\\n', 'rmc') >
<#assign nextRandom = .now?string["HHmmssSSS"]?number>
<#list posts as post>
<div class="banner divider" style="background-image: url(photos/panoramas/${photos[nextRandom % photos?size]});"></div>
<#assign nextRandom = nextRandom * 13 % 104729>
</#list>
I chose nextRandom = nextRandom * 13 % 104729
, but I bet that's very not-random in statistical terms. Also make sure that 104729 is larger than the collection you iterate.
See Freemarker special variables reference.
Better approach, at least for HTML, would be to put that collection to JavaScript and pick it from there:
<script type="text/javascript">
var photos = [ <#list photos as photo> '${photo}', </#list> ];
var randomPhoto = photos[Math.floor(photos.length * Math.random())];
</script>
See e.g. Math.random() at MDN.
I just threw a relatively random number generator together. It takes the milliseconds of .now?long
and multiplies it by your seed salt (in this case 7) and divides by three. In my case I only needed 5 numbers but it can go up to the 13 digits of the milliseconds for the day. Or more if you want to add more multipliers, addends, etc.
<#function randomNumber salt>
<#local str= .now?long />
<#assign str = (str * salt)/3 />
<#return str[(str?string?length-5)..]/>
</#function>
<#assign rnd = randomNumber(7)/>
If you don't want a salt, you can just remove the parameter and hard code it for the salt variable in the calculation and just call randomNumber()
精彩评论