Web Resources
AcrossWebModule allows for programatically registering web resources through the use of a WebResourceRegistry
.
A new WebResourceRegistry
is attached to every request and can be accessed as a request attribute or a handler method parameter.
Resources can be added in a bucket and AcrossWebModule supports 3 buckets by default: css
, javascript
and meta
.
A bucket can be used for retrieval of resources, for example when rendering inside a thymeleaf template.
You can add your own rendering to a specific bucket, see custom bucket to implement this.
Resources can be identified with a unique key, ensuring they are added only once.
Javascript bucket
You can add a javascript resource to the WebResourceRegistry
by using following syntax:
@Controller
public class MyController
{
@ModelAttribute
public void registerWebResources( WebResourceRegistry webResourceRegistry ) {
Map<String, String> statics = new HashMap<String, String>()
{{
put( "static", "@static:/" );
put( "admin", "@adminWeb:/" );
}};
Map<String, Object> vars = new HashMap<String, Object>()
{{
put( "rootPaths", statics );
put( "language", "nl" );
}};
webResourceRegistry.apply(
WebResourceRule.add( WebResource.javascript( "//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js").defer().async() ).withKey( "bootstrap-min-js" ).toBucket( WebResource.JAVASCRIPT ), (1)
WebResourceRule.add( WebResource.javascript( "@static:/adminweb/js/file.js") ).withKey( "static-file-js" ).toBucket( WebResource.JAVASCRIPT ), (2)
WebResourceRule.add( WebResource.javascript().inline( "alert('hello world');") ).withKey( "inline-hello-world-min-js" ).toBucket( WebResource.JAVASCRIPT_PAGE_END ), (3)
WebResourceRule.add( WebResource.javascript().data( vars ).snippet( ( data ) -> {
return "(function ( Across ) {\n" +
"var data=" + new ObjectMapper().writeValueAsString( data ) + ";\n" +
"for(var key in data) Across[key] = data[key];\n" +
" })( window.Across = window.Across || {} );\n"; (4)
} ) ).withKey( "alert-page-top" ).toBucket( "javascript_vars" )
);
}
}
1 | This adds an external Javascript file to the javascript bucket, it will put the attributes defer and async on it. |
2 | This adds a Javascript file located under the default static folder. See Links and URLs for a list of prefixes that are supported. |
3 | This inlines Javascript directly into a script tag. |
4 | This inlines a data object with a snippet into the script tag. |
You can render the javascript bucket, with the following snippet:
<html>
<head>
<across:view element="${webResourceRegistry.getBucketResources('javascript')}" />
</head>
<body>
...
<across:view element="${webResourceRegistry.getBucketResources('javascript-page-end')}" />
</body>
</html>
<html>
<head>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js" type="text/javascript" defer="defer" async="async"></script>
<script src="/static/adminweb/js/file.js" type="text/javascript"></script>
<script type="text/javascript">(function ( Across ) {
var data={"rootPaths":{"static":"@static:/","admin":"@adminWeb:/"},"language":"nl"};
for(var key in data) Across[key] = data[key];
})( window.Across = window.Across || {} );
</script>
</head>
<body>
...
<script type="text/javascript">alert('hello world()');</script>
</body>
</html>
CSS bucket
You can add a css resource to the WebResourceRegistry
by using following syntax:
@Controller
public class MyController
{
@ModelAttribute
public void registerWebResources( WebResourceRegistry webResourceRegistry ) {
webResourceRegistry.apply(
WebResourceRule.add( WebResource.css( "//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" ) ).withKey( "bootstrap-min-css" ).toBucket( WebResource.CSS ), (1)
WebResourceRule.add( WebResource.css().url("@static:/adminweb/css/print.css").rel("stylesheet").media( "print" ) ).withKey( "admin-web-print-css" ).toBucket( WebResource.CSS ), (2)
WebResourceRule.add( WebResource.css().inline( "body {background-color: powderblue;}" ) ) (3)
);
}
}
1 | This adds an external CSS file to the css bucket. |
2 | This adds a CSS file located under the default static folder, it will put the attributes media and rel on it.
See Links and URLs for a list of prefixes that are supported. |
3 | This inlines CSS directly into a style tag. |
You can render the css bucket, with the following snippet:
<html>
<head>
<across:view element="${webResourceRegistry.getBucketResources('css')}" />
</head>
<body>
...
</body>
</html>
<html>
<head>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" type="text/css" rel="stylesheet"></script>
<link href="/static/adminweb/css/print.css" type="text/css" rel="stylesheet" media="print"></script>
<style>
body {background-color: powderblue;}
</style>
</head>
<body>
...
</body>
</html>
Meta bucket
You can add a meta resource to the WebResourceRegistry
by using following syntax:
@Controller
public class MyController
{
@ModelAttribute
public void registerWebResources( WebResourceRegistry webResourceRegistry ) {
webResourceRegistry.apply(
WebResourceRule.add( WebResource.meta().metaName( "keywords" ).content( "HTML, CSS, XML, HTML" ) ).withKey( "meta-keywords" ).toBucket( "meta" ), (1)
WebResourceRule.add( WebResource.meta().refresh("30;URL='https://www.foreach.be/'") ).withKey( "meta-refresh" ).toBucket( "meta" ) (2)
);
}
}
1 | This will generate a META tag and will put the attributes name and content on it. |
2 | This generate a http-equiv META tag with a refresh timer of 30 seconds, towards https://www.foreach.be. |
You can render the meta bucket, with the following snippet:
<html>
<head>
<across:view element="${webResourceRegistry.getBucketResources('meta')}" />
</head>
<body>
...
</body>
</html>
<html>
<head>
<meta name="keywords" content="HTML, CSS, XML, HTML"></meta>
<meta http-equiv="refresh" content="30;URL=https://www.foreach.be/"></meta>
</head>
<body>
...
</body>
</html>
Custom bucket
It is possible to register your own bucket by using following syntax:
base
resources@Controller
public class MyController
{
@ModelAttribute
public void registerWebResources( WebResourceRegistry webResourceRegistry ) {
webResourceRegistry.apply(
WebResourceRule.add( new ViewElementBuilderSupport()
{
@Override
protected MutableViewElement createElement( ViewElementBuilderContext builderContext ) {
NodeViewElement element = new NodeViewElement( "base" );
element.setAttribute( "href", builderContext.buildLink( "https://www.w3schools.com/images/" ) ); (1)
element.setAttribute( "target", "_blank" );
return element;
}
} ).withKey( "base-href" ).toBucket( "base" ) (2)
);
}
}
1 | Using the buildLink will ensure that path prefixes are correctly resolved. |
2 | Generates a base tag with the href attribute. |
You can render the custom bucket, with the following snippet:
<html>
<head>
<across:view element="${webResourceRegistry.getBucketResources('base')}" />
</head>
<body>
...
</body>
</html>
<html>
<head>
<base href="https://www.w3schools.com/images/" />
</head>
<body>
...
</body>
</html>
Linking to webjars
You can use a path prefix in your url
to generate an url pointing to a webjar.
@Controller
public class MyController
{
@ModelAttribute
public void registerWebResources( WebResourceRegistry webResourceRegistry ) {
webResourceRegistry.apply(
WebResourceRule.add( WebResource.css( "@webjars:/bootstrap/3.3.5/css/bootstrap.min.css" ) ).withKey( "bootstrap-min-css" ).toBucket( WebResource.CSS ) (1)
);
}
}
1 | Using the @webjars will generate the link to the registered webjar. See path prefixes for a list of other supported prefixes. |
<html>
<head>
<link href="/webjars/bootstrap/3.3.5/css/bootstrap.min.css" type="text/css" rel="stylesheet"></script>
</head>
<body>
...
</body>
</html>
Make sure you have registered your webjar in the pom.xml
if you wish to use it.
<dependency>
<groupId>org.webjars</groupId>
<artifactId>jquery</artifactId>
<version>3.3.0</version>
</dependency>
This will expose the webjar under the base url /webjars/jquery/3.3.0/
for example /webjars/jquery/3.3.0/jquery.js
.
Ordering of web resources
Every AddWebResourceRule
supports several ordering parameters. The following is an example of ordering web resources.
Sorting is handled per bucket when the rendering of the view elemement is done.
@Controller
public class MyController
{
@ModelAttribute
public void registerWebResources( WebResourceRegistry webResourceRegistry ) {
webResourceRegistry.apply(
WebResourceRule.add( WebResource.css( "/css/1.css" ) ).order( 1 ).withKey( "first-css" ).toBucket( WebResource.CSS ), (1)
WebResourceRule.add( WebResource.css( "/css/4.css" ) ).after( "third-css" ).withKey( "fourth-css" ).toBucket( WebResource.CSS ), (2)
WebResourceRule.add( WebResource.css( "/css/3.css" ) ).withKey( "third-css" ).toBucket( WebResource.CSS ), (3)
WebResourceRule.add( WebResource.css( "/css/2.css" ) ).before( "third-css" ).withKey( "second-css" ).toBucket( WebResource.CSS ) (4)
);
}
}
1 | Web resources will always be ordered by order() first. If no order() is specified, they are sorted after the ones that have an order (lowest precendence). |
2 | The web resource with key fourth-css is placed after the web resource with key third-css . |
3 | The web resource with key third-css has no specific ordering and will depend on other web resources for sorting. |
4 | The web resource with key second-css is placed before the web resource with key `third-css'. |
<html>
<head>
<link rel="stylesheet" href="/css/1.css" type="text/css"></link>
<link rel="stylesheet" href="/css/2.css" type="text/css"></link>
<link rel="stylesheet" href="/css/3.css" type="text/css"></link>
<link rel="stylesheet" href="/css/4.css" type="text/css"></link>
</head>
<body>
...
</body>
</html>