Layouts is a Java library for creating HTML content. A layout is a JSP based template that defines the surroundings of an HTML page. Layouts are combined with views to create a full HTML response. For example if the JSP view:
<head>
<title>This Is The Title</title>
</head>
<body>
<h1>This Is The Content</h1>
</body>
Was rendered with the layout:
<html>
<head>
<link href="<%=request.getContextPath() %>/assets/css/bootstrap.min.css"
rel="stylesheet">
${view.yield("head", pageContext)}
</head>
<body>
${view.yield("body", pageContext)}
<script src="<%=request.getContextPath() %>/assets/js/bootstrap.min.js"></script>
</body>
</html>
The resulting HTML page returned to the client would be:
<html>
<head>
<link href="/assets/css/bootstrap.min.css" rel="stylesheet">
<title>This Is The Title</title>
</head>
<body>
<h1>This Is The Content</h1>
<script src="/assets/js/bootstrap.min.js"></script>
</body>
</html>
Layouts uses basic JSP and XHTML and is web framework agnostic.
You can download layouts-1.1.jar directly and place in your project.
Add the following dependency into your Maven project:
<dependency>
<groupId>org.baswell</groupId>
<artifactId>layouts</artifactId>
<version>1.1</version>
</dependency>
Layouts runs within a Java Servlet container at API 2.4 or greater. Layouts has no other external dependencies.
Layouts is used within a Servlet container by configuring the LayoutsFilter.
<filter>
<filter-name>LayoutsFilter</filter-name>
<filter-class>org.baswell.layouts.LayoutsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LayoutsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The LayoutsFilter
must be in the processing chain for all requests you want rendered with a layout. It should be placed before any other filters that might
generate content for the HTTP response.
You can use the filter parameters ONLY and EXCEPT for finer grained control (than url-pattern) over which HTTP requests the LayoutsFilter
is engaged for.
<init-param>
<param-name>ONLY</param-name>
<param-value>/home/.*,/users/.*</param-value>
</init-param>
The ONLY parameter must be a list (comma delimited) of valid Java regular expression. If specified, only request URIs that match one of these patterns will be candidates for layouts. The URI from the HTTP request matched against these patterns will not include the context path of your application.
The other supported parameter is EXCEPT:
<init-param>
<param-name>EXCEPT</param-name>
<param-value>.*\.html$,.*\.htm$</param-value>
</init-param>
The EXCEPT parameter must be a list (comma delimited) of valid Java regular expression. If specified, only request URIs that don't match any of these patterns will be candidates for layouts. The URI from the HTTP request matched against these patterns will not include the context path of your application.
If both ONLY and EXCEPT are specified then a request will only be a candidate for a layout if a match is made one of the ONLY patterns and no match is made on any of the EXCEPT patterns.
Each of your layouts should be a valid JSP file. The name of the layout will be the file name minus the extension (case sensitive). So for example the layout /WEB-INF/jsps/layouts/basic.jsp will have the name basic.
Within the context of a layout, yield
identifies a section where content from the view should be inserted. The simplest way to use this is to have a
single yield, into which the entire contents of the view currently being rendered is inserted:
<html>
<head>
</head>
<body>
${view.yield(pageContext)}
</body>
</html>
You can also create a layout with multiple yielding regions:
<html>
<head>
${view.yield("head", pageContext)}
</head>
<body>
${view.yield("body", pageContext)}
</body>
</html>
The content of the outer most level <head>
element in the view will be rendered inside the <head>
element of the layout.
Likewise the content of the outer most level <body>
element in the view view will be rendered inside the <body>
element of
the layout. You can use any tag element name to create content sections within your view.
You can use the two shortcut yield methods ${view.yieldHead(pageContext)}
and ${view.yieldBody(pageContext)}
which are equivalent to ${view.yield("head", pageContext)}
and ${view.yield("body", pageContext)}
.
By default all your application layouts should go in /WEB-INF/jsps/layouts/. This can be changed by using the LAYOUTS_DIRECTORY init parameter for the LayoutsFilter
.
<init-param>
<param-name>LAYOUTS_DIRECTORY</param-name>
<param-value>/WEB-INF/layouts</param-value>
</init-param>
The default layout used for views is application.jsp. This can be changed by using the DEFAULT_LAYOUT init parameter for the LayoutsFilter
. For example to change the default
layout to basic.jsp:
<init-param>
<param-name>DEFAULT_LAYOUT</param-name>
<param-value>basic</param-value>
</init-param>
A different layout from the default can be specified by setting an HttpServletRequest
attribute for the current request. Use the constant Layouts.LAYOUT with the name
of the layout to use. For example:
httpServletRequest.setAttribute(Layouts.LAYOUT, "rightMenuBase");
The request attribute can be set in the Servlet or controller portion of your code or in the JSP page of the view.
To disable the layout for a view use the HttpServletRequest
attribute Layouts.NO_LAYOUT.
httpServletRequest.setAttribute(Layouts.NO_LAYOUT, true);
Your views can by anything that writes to either the OutputStream
or PrintWriter
of the HttpServletRequest
. This means your views (for example) can be Servlets, JSP files, or static HTML files.
By default any request the LayoutsFilter
processes will be rendered with a layout unless one the following conditions is met:
- The HTTP header Accept is set with a non-HTML mime type.
- The URL ends in a known, non-HTML file extension such as css, js, or png.
- The HTTP header X-Requested-With is set with the value XMLHttpRequest (Ajax request).
- The
HttpServletRequest
attribute Layouts.NO_LAYOUT is set totrue
.
You can override this behavior by implementing the interface UseLayoutDecider. The LayoutsFilter
init parameter USE_LAYOUT_DECIDER should be set with
with the full qualified class name of your implementation.
<init-param>
<param-name>USE_LAYOUT_DECIDER</param-name>
<param-value>com.example.MyUseLayoutDecider</param-value>
</init-param>
Your implementation must have a default constructor that the LayoutsFilter
will call at initialization time.
The full content of your view will be rendered before the layout for the view is executed. This means if your view is a Servlet or JSP file you can set request attributes used in your layout. For example in the JSP view:
<%
request.setAttribute("title", "This Is The Title");
%>
<h1>This Is The Content</h1>
The title attribute is set that can then be used in the layout as:
<html>
<head>
<title><%= request.getAttribute("title") %></title>
</head>
<body>
${view.yield(pageContext)}
</body>
</html>
Corey Baswell - corey.baswell@gmail.com
Copyright 2015 Corey Baswell
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.