spring boot Thymeleaf relative urls

I am now using spring boot 1.3 and thymeleaf.

Here is a piece of my thymeleaf page:

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
    <title>Spring Boot and Thymeleaf demo</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

    <script type="text/javascript" src="" th:src="@{/js/our.min.js}"></script>

As you see, my url is like

<script type="text/javascript" src="" th:src="@{/js/our.min.js}"></script>

That's works fine when my jquery and my code in the same server.

But now my js will be deployed to CDN, and will be add versions, may be like this:

<script type="text/javascript" src="http://s1.cdn.xxx.com/s/js/our.min.js?v=3QxjsKtdfdfsx"></script>

As you see we do three things.

first: add a http url: http://s1.cdn.xxx.com/s/, this url can be read from a config file.

second: add a version suffix v=3QxjsKtdfdfsx

third: combine all of them

http://s1.cdn.xxx.com/s/ + /js/our.min.js + v=3QxjsKtdfdfsx

I wonder if spring boot or thymeleaf provide such functions do these things or functions.



As far as I know, there isn't anything out of the box that will handle this behaviour for you, however its pretty easy to write a custom-tag (Thymeleaf Processor) to encapsulate the logic and make it simple to use everywhere.

I had to do basically the same thing a little while ago:

First, create a simple processor, which is just a class that will handle your custom attribute:

class CdnUrlProcessor extends AbstractStandardSingleAttributeModifierAttrProcessor{

@Autowired UrlService urlService
private final int HIGHEST_PRECEDENCE = Integer.MAX_VALUE

// Here we use a multi attribute matcher - we also link the processor to
// the CDN Dialect - which is just the namespace for the attributes
public CdnUrlProcessor(){
    super( new MultipleAttributeMatcher( CdnDialect, ["src", "href"] ) )

// These are just boilerplate overrides
@Override protected String getTargetAttributeName(Arguments arguments, Element element, String attributeName) {

@Override protected ModificationType getModificationType(Arguments arguments, Element element, String attributeName, String newAttributeName) {

@Override protected boolean removeAttributeIfEmpty(Arguments arguments, Element element, String attributeName, String newAttributeName) {

@Override public int getPrecedence() {

// This is where the magic happens - you can put your logic to build
// the url in here, or you could autowire a service (I did, as I wanted
// the logic available outside of Thymeleaf    
@Override protected String getTargetAttributeValue( Arguments arguments, Element element, String attributeName ){
    urlService.generateCdnUrl( element.getAttributeValue(attributeName) )

Then you need to create the dialect - as mentioned in the code comments above, this is just a namespace/prefix that will be used to group and apply processors:

@Component class CdnDialect extends AbstractDialect {

@Autowired CdnUrlProcessor cdnUrlProcessor

public CdnDialect() {

public String getPrefix() {

@Override public Set<IProcessor> getProcessors() {
    [ cdnUrlProcessor ] as Set


And thats it for Thymeleaf (although check out the testing - you obviously want to add tests for this, which are pretty easy to add).

Then you can use your processor in the HTML template with your custom prefix, just like you would a Thymeleaf "th" attribute as so:

<script type="text/javascript" src="" cdn:src="/js/our.min.js"></script>

(by the way, the above code is copied from my Groovy - so if you are in java you will need to add return keywords and semi-colons)

Need Your Help

should user's avatar be a field in table OR searching through file systems?

database registration avatar

There is a situation in which we can have a VARCHAR field for users's avatar and store their image name in that field like most of the apps.

Left Outer Join SOQL

sql soap salesforce soql

I have the following entities: