Skip to content

Commit 4b2a047

Browse files
committed
Revised documentation for PDF, Excel and JSON views
Issue: SPR-17180 Issue: SPR-17182 (cherry picked from commit c0c9e08)
1 parent 7894ecf commit 4b2a047

File tree

2 files changed

+43
-171
lines changed

2 files changed

+43
-171
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package org.springframework.web.servlet.view.json;
1818

1919
import java.io.IOException;
20-
import java.util.Arrays;
2120
import java.util.Collections;
2221
import java.util.HashMap;
2322
import java.util.LinkedHashSet;
@@ -224,7 +223,7 @@ protected boolean isValidJsonpQueryParam(String value) {
224223
* Filter out undesired attributes from the given model.
225224
* The return value can be either another {@link Map} or a single value object.
226225
* <p>The default implementation removes {@link BindingResult} instances and entries
227-
* not included in the {@link #setModelKeys renderedAttributes} property.
226+
* not included in the {@link #setModelKeys modelKeys} property.
228227
* @param model the model, as passed on to {@link #renderMergedOutputModel}
229228
* @return the value to be rendered
230229
*/

src/docs/asciidoc/web/webmvc-view.adoc

Lines changed: 42 additions & 169 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ extensive set of features that will make such a transition easier. Thymeleaf is
2222
developed and maintained. For a more complete introduction see the
2323
http://www.thymeleaf.org/[Thymeleaf] project home page.
2424

25-
The Thymeleaf integration with Spring MVC is managed by the Thymeleaf project. The
26-
configuration involves a few bean declarations such as
25+
The Thymeleaf integration with Spring MVC is managed by the Thymeleaf project.
26+
The configuration involves a few bean declarations such as
2727
`ServletContextTemplateResolver`, `SpringTemplateEngine`, and `ThymeleafViewResolver`.
2828
See http://www.thymeleaf.org/documentation.html[Thymeleaf+Spring] for more details.
2929

@@ -941,9 +941,8 @@ The preceding JSP assumes that the variable name of the form backing object is
941941
==== The input tag
942942

943943
This tag renders an HTML 'input' tag using the bound value and type='text' by default.
944-
For an example of this tag, see <<mvc-view-jsp-formtaglib-formtag>>. Starting with Spring
945-
3.1 you can use other types such HTML5-specific types like 'email', 'tel', 'date', and
946-
others.
944+
For an example of this tag, see <<mvc-view-jsp-formtaglib-formtag>>. You may also use
945+
HTML5-specific types like 'email', 'tel', 'date', and others.
947946

948947

949948
[[mvc-view-jsp-formtaglib-checkboxtag]]
@@ -1563,12 +1562,12 @@ The corresponding `@Controller` method is shown below:
15631562
[[mvc-view-jsp-formtaglib-html5]]
15641563
==== HTML5 tags
15651564

1566-
Starting with Spring 3, the Spring form tag library allows entering dynamic attributes,
1567-
which means you can enter any HTML5 specific attributes.
1565+
The Spring form tag library allows entering dynamic attributes, which means you can
1566+
enter any HTML5 specific attributes.
15681567

1569-
In Spring 3.1, the form input tag supports entering a type attribute other than 'text'.
1570-
This is intended to allow rendering new HTML5 specific input types such as 'email',
1571-
'date', 'range', and others. Note that entering type='text' is not required since 'text'
1568+
The form input tag supports entering a type attribute other than 'text'. This is
1569+
intended to allow rendering new HTML5 specific input types such as 'email', 'date',
1570+
'range', and others. Note that entering type='text' is not required since 'text'
15721571
is the default type.
15731572

15741573

@@ -1801,7 +1800,6 @@ Similar requirements apply for implementing `AbstractRssFeedView`, as shown belo
18011800
HttpServletRequest request, HttpServletResponse response) throws Exception {
18021801
// implementation omitted
18031802
}
1804-
18051803
}
18061804
----
18071805

@@ -1822,7 +1820,7 @@ https://spring.io/blog/2009/03/16/adding-an-atom-view-to-an-application-using-sp
18221820

18231821

18241822
[[mvc-view-document-intro]]
1825-
=== Introduction
1823+
=== Introduction to document views
18261824

18271825
Returning an HTML page isn't always the best way for the user to view the model output,
18281826
and Spring makes it simple to generate a PDF document or an Excel spreadsheet
@@ -1843,166 +1841,45 @@ vulnerability for untrusted PDF content.
18431841

18441842

18451843

1846-
[[mvc-view-document-config]]
1847-
=== Configuration
1848-
1849-
Document based views are handled in an almost identical fashion to XSLT views, and the
1850-
following sections build upon the previous one by demonstrating how the same controller
1851-
used in the XSLT example is invoked to render the same model as both a PDF document and
1852-
an Excel spreadsheet (which can also be viewed or manipulated in Open Office).
1853-
1854-
1855-
1856-
[[mvc-view-document-configviews]]
1857-
=== View definition
1858-
1859-
First, let's amend the views.properties file (or xml equivalent) and add a simple view
1860-
definition for both document types. The entire file now looks like this with the XSLT
1861-
view shown from earlier:
1862-
1863-
[literal]
1864-
[subs="verbatim,quotes"]
1865-
----
1866-
home.(class)=xslt.HomePage
1867-
home.stylesheetLocation=/WEB-INF/xsl/home.xslt
1868-
home.root=words
1869-
1870-
xl.(class)=excel.HomePage
1871-
1872-
pdf.(class)=pdf.HomePage
1873-
----
1874-
1875-
__If you want to start with a template spreadsheet or a fillable PDF form to add your
1876-
model data to, specify the location as the 'url' property in the view definition__
1877-
1878-
1879-
1880-
[[mvc-view-document-configcontroller]]
1881-
=== Controller
1882-
1883-
The controller code we'll use remains exactly the same from the XSLT example earlier
1884-
other than to change the name of the view to use. Of course, you could be clever and
1885-
have this selected based on a URL parameter or some other logic - proof that Spring
1886-
really is very good at decoupling the views from the controllers!
1887-
1888-
1889-
1890-
[[mvc-view-document-configsubclasses]]
1891-
=== Excel views
1892-
1893-
Exactly as we did for the XSLT example, we'll subclass suitable abstract classes in
1894-
order to implement custom behavior in generating our output documents. For Excel, this
1895-
involves writing a subclass of
1896-
`org.springframework.web.servlet.view.document.AbstractExcelView` (for Excel files
1897-
generated by POI) or `org.springframework.web.servlet.view.document.AbstractJExcelView`
1898-
(for JExcelApi-generated Excel files) and implementing the `buildExcelDocument()` method.
1899-
1900-
Here's the complete listing for our POI Excel view which displays the word list from the
1901-
model map in consecutive rows of the first column of a new spreadsheet:
1902-
1903-
[source,java,indent=0]
1904-
[subs="verbatim,quotes"]
1905-
----
1906-
package excel;
1907-
1908-
// imports omitted for brevity
1909-
1910-
public class HomePage extends AbstractExcelView {
1911-
1912-
protected void buildExcelDocument(Map model, HSSFWorkbook wb, HttpServletRequest req,
1913-
HttpServletResponse resp) throws Exception {
1914-
1915-
HSSFSheet sheet;
1916-
HSSFRow sheetRow;
1917-
HSSFCell cell;
1918-
1919-
// Go to the first sheet
1920-
// getSheetAt: only if wb is created from an existing document
1921-
// sheet = wb.getSheetAt(0);
1922-
sheet = wb.createSheet("Spring");
1923-
sheet.setDefaultColumnWidth((short) 12);
1924-
1925-
// write a text at A1
1926-
cell = getCell(sheet, 0, 0);
1927-
setText(cell, "Spring-Excel test");
1928-
1929-
List words = (List) model.get("wordList");
1930-
for (int i=0; i < words.size(); i++) {
1931-
cell = getCell(sheet, 2+i, 0);
1932-
setText(cell, (String) words.get(i));
1933-
}
1934-
}
1935-
1936-
}
1937-
----
1844+
[[mvc-view-document-pdf]]
1845+
=== PDF views
19381846

1939-
And the following is a view generating the same Excel file, now using JExcelApi:
1847+
A simple PDF view for a word list could extend
1848+
`org.springframework.web.servlet.view.document.AbstractPdfView` and implement the
1849+
`buildPdfDocument()` method as follows:
19401850

19411851
[source,java,indent=0]
19421852
[subs="verbatim,quotes"]
19431853
----
1944-
package excel;
1854+
public class PdfWordList extends AbstractPdfView {
19451855
1946-
// imports omitted for brevity
1947-
1948-
public class HomePage extends AbstractJExcelView {
1949-
1950-
protected void buildExcelDocument(Map model, WritableWorkbook wb,
1856+
protected void buildPdfDocument(Map<String, Object> model, Document doc, PdfWriter writer,
19511857
HttpServletRequest request, HttpServletResponse response) throws Exception {
19521858
1953-
WritableSheet sheet = wb.createSheet("Spring", 0);
1954-
1955-
sheet.addCell(new Label(0, 0, "Spring-Excel test"));
1956-
1957-
List words = (List) model.get("wordList");
1958-
for (int i = 0; i < words.size(); i++) {
1959-
sheet.addCell(new Label(2+i, 0, (String) words.get(i)));
1859+
List<String> words = (List<String>) model.get("wordList");
1860+
for (String word : words) {
1861+
doc.add(new Paragraph(word));
19601862
}
19611863
}
19621864
}
19631865
----
19641866

1965-
Note the differences between the APIs. We've found that the JExcelApi is somewhat more
1966-
intuitive, and furthermore, JExcelApi has slightly better image-handling capabilities.
1967-
There have been memory problems with large Excel files when using JExcelApi however.
1968-
1969-
If you now amend the controller such that it returns `xl` as the name of the view (
1970-
`return new ModelAndView("xl", map);`) and run your application again, you should find
1971-
that the Excel spreadsheet is created and downloaded automatically when you request the
1972-
same page as before.
1867+
A controller may return such a view either from an external view definition
1868+
(referencing it by name) or as a `View` instance from the handler method.
19731869

19741870

19751871

1976-
[[mvc-view-document-configsubclasspdf]]
1977-
=== PDF views
1978-
1979-
The PDF version of the word list is even simpler. This time, the class extends
1980-
`org.springframework.web.servlet.view.document.AbstractPdfView` and implements the
1981-
`buildPdfDocument()` method as follows:
1982-
1983-
[source,java,indent=0]
1984-
[subs="verbatim,quotes"]
1985-
----
1986-
package pdf;
1987-
1988-
// imports omitted for brevity
1989-
1990-
public class PDFPage extends AbstractPdfView {
1991-
1992-
protected void buildPdfDocument(Map model, Document doc, PdfWriter writer,
1993-
HttpServletRequest req, HttpServletResponse resp) throws Exception {
1994-
List words = (List) model.get("wordList");
1995-
for (int i=0; i<words.size(); i++) {
1996-
doc.add( new Paragraph((String) words.get(i)));
1997-
}
1998-
}
1872+
[[mvc-view-document-pdf]]
1873+
=== Excel views
19991874

2000-
}
2001-
----
1875+
Since Spring Framework 4.2,
1876+
`org.springframework.web.servlet.view.document.AbstractXlsView` is provided as a base
1877+
class for Excel views based on POI, with specialized subclasses `AbstractXlsxView`
1878+
and `AbstractXlsxStreamingView`, superseding the outdated `AbstractExcelView` class.
20021879

2003-
Once again, amend the controller to return the `pdf` view with `return new
2004-
ModelAndView("pdf", map);`, and reload the URL in your application. This time a PDF
2005-
document should appear listing each of the words in the model map.
1880+
The programming model is similar to `AbstractPdfView`, with `buildExcelDocument()`
1881+
as the central template method and controllers being able to return such a view from
1882+
an external definition (by name) or as a `View` instance from the handler method.
20061883

20071884

20081885

@@ -2014,16 +1891,16 @@ document should appear listing each of the words in the model map.
20141891

20151892

20161893
[[mvc-view-json-mapping]]
2017-
=== JSON
1894+
=== Jackson-based JSON views
20181895
[.small]#<<web-reactive.adoc#webflux-view-httpmessagewriter,Same in Spring WebFlux>>#
20191896

20201897
The `MappingJackson2JsonView` uses the Jackson library's `ObjectMapper` to render the response
20211898
content as JSON. By default, the entire contents of the model map (with the exception of
20221899
framework-specific classes) will be encoded as JSON. For cases where the contents of the
20231900
map need to be filtered, users may specify a specific set of model attributes to encode
2024-
via the `RenderedAttributes` property. The `extractValueFromSingleKeyModel` property may
2025-
also be used to have the value in single-key models extracted and serialized directly
2026-
rather than as a map of model attributes.
1901+
via the `modelKeys` property. The `extractValueFromSingleKeyModel` property may also be
1902+
used to have the value in single-key models extracted and serialized directly rather than
1903+
as a map of model attributes.
20271904

20281905
JSON mapping can be customized as needed through the use of Jackson's provided
20291906
annotations. When further control is needed, a custom `ObjectMapper` can be injected
@@ -2038,7 +1915,7 @@ Spring Framework 5.1, <<mvc-cors,CORS>> should be used instead.
20381915

20391916

20401917
[[mvc-view-xml-mapping]]
2041-
=== XML
1918+
=== Jackson-based XML views
20421919
[.small]#<<web-reactive.adoc#webflux-view-httpmessagewriter,Same in Spring WebFlux>>#
20431920

20441921
The `MappingJackson2XmlView` uses the
@@ -2056,11 +1933,11 @@ serializers/deserializers need to be provided for specific types.
20561933

20571934

20581935
[[mvc-view-xml-marshalling]]
2059-
== XML
1936+
== XML marshalling
20601937

20611938
The `MarshallingView` uses an XML `Marshaller` defined in the `org.springframework.oxm`
20621939
package to render the response content as XML. The object to be marshalled can be set
2063-
explicitly using ``MarhsallingView``'s `modelKey` bean property. Alternatively, the view
1940+
explicitly using ``MarshallingView``'s `modelKey` bean property. Alternatively, the view
20641941
will iterate over all model properties and marshal the first type that is supported
20651942
by the `Marshaller`. For more information on the functionality in the
20661943
`org.springframework.oxm` package refer to the chapter
@@ -2070,7 +1947,7 @@ by the `Marshaller`. For more information on the functionality in the
20701947

20711948

20721949
[[mvc-view-xslt]]
2073-
== XSLT
1950+
== XSLT views
20741951

20751952
XSLT is a transformation language for XML and is popular as a view technology within web
20761953
applications. XSLT can be a good choice as a view technology if your application
@@ -2089,9 +1966,8 @@ document ready for transformation.
20891966
[[mvc-view-xslt-beandefs]]
20901967
=== Beans
20911968

2092-
Configuration is standard for a simple Spring application.
2093-
The MVC configuration has to define a `XsltViewResolver` bean and
2094-
regular MVC annotation configuration.
1969+
Configuration is standard for a simple Spring web application: The MVC configuration
1970+
has to define an `XsltViewResolver` bean and regular MVC annotation configuration.
20951971

20961972
[source,java,indent=0]
20971973
[subs="verbatim,quotes"]
@@ -2108,7 +1984,6 @@ public class WebConfig implements WebMvcConfigurer {
21081984
viewResolver.setSuffix(".xslt");
21091985
return viewResolver;
21101986
}
2111-
21121987
}
21131988
----
21141989

@@ -2120,7 +1995,7 @@ And we need a Controller that encapsulates our word generation logic.
21201995
=== Controller
21211996

21221997
The controller logic is encapsulated in a `@Controller` class, with the
2123-
handler method being defined like so...
1998+
handler method being defined as follows:
21241999

21252000
[source,java,indent=0]
21262001
[subs="verbatim,quotes"]
@@ -2130,7 +2005,6 @@ handler method being defined like so...
21302005
21312006
@RequestMapping("/")
21322007
public String home(Model model) throws Exception {
2133-
21342008
Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
21352009
Element root = document.createElement("wordList");
21362010
@@ -2145,7 +2019,6 @@ handler method being defined like so...
21452019
model.addAttribute("wordList", root);
21462020
return "home";
21472021
}
2148-
21492022
}
21502023
----
21512024

0 commit comments

Comments
 (0)