From c0c9e08bf9b0844fdfd05cb96cbc74a7b83e7c52 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 14 Aug 2018 20:36:29 +0200 Subject: [PATCH] Revised documentation for PDF, Excel and JSON views Issue: SPR-17180 Issue: SPR-17182 --- .../view/json/MappingJackson2JsonView.java | 2 +- src/docs/asciidoc/web/webmvc-view.adoc | 211 ++++-------------- 2 files changed, 43 insertions(+), 170 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java index bb1f533613c2..b19c84adeceb 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/view/json/MappingJackson2JsonView.java @@ -149,7 +149,7 @@ public void setExtractValueFromSingleKeyModel(boolean extractValueFromSingleKeyM * Filter out undesired attributes from the given model. * The return value can be either another {@link Map} or a single value object. *

The default implementation removes {@link BindingResult} instances and entries - * not included in the {@link #setModelKeys renderedAttributes} property. + * not included in the {@link #setModelKeys modelKeys} property. * @param model the model, as passed on to {@link #renderMergedOutputModel} * @return the value to be rendered */ diff --git a/src/docs/asciidoc/web/webmvc-view.adoc b/src/docs/asciidoc/web/webmvc-view.adoc index c2e43cea5131..fea8bc5d7a3a 100644 --- a/src/docs/asciidoc/web/webmvc-view.adoc +++ b/src/docs/asciidoc/web/webmvc-view.adoc @@ -22,8 +22,8 @@ extensive set of features that will make such a transition easier. Thymeleaf is developed and maintained. For a more complete introduction see the http://www.thymeleaf.org/[Thymeleaf] project home page. -The Thymeleaf integration with Spring MVC is managed by the Thymeleaf project. The -configuration involves a few bean declarations such as +The Thymeleaf integration with Spring MVC is managed by the Thymeleaf project. +The configuration involves a few bean declarations such as `ServletContextTemplateResolver`, `SpringTemplateEngine`, and `ThymeleafViewResolver`. See http://www.thymeleaf.org/documentation.html[Thymeleaf+Spring] for more details. @@ -941,9 +941,8 @@ The preceding JSP assumes that the variable name of the form backing object is ==== The input tag This tag renders an HTML 'input' tag using the bound value and type='text' by default. -For an example of this tag, see <>. Starting with Spring -3.1 you can use other types such HTML5-specific types like 'email', 'tel', 'date', and -others. +For an example of this tag, see <>. You may also use +HTML5-specific types like 'email', 'tel', 'date', and others. [[mvc-view-jsp-formtaglib-checkboxtag]] @@ -1563,12 +1562,12 @@ The corresponding `@Controller` method is shown below: [[mvc-view-jsp-formtaglib-html5]] ==== HTML5 tags -Starting with Spring 3, the Spring form tag library allows entering dynamic attributes, -which means you can enter any HTML5 specific attributes. +The Spring form tag library allows entering dynamic attributes, which means you can +enter any HTML5 specific attributes. -In Spring 3.1, the form input tag supports entering a type attribute other than 'text'. -This is intended to allow rendering new HTML5 specific input types such as 'email', -'date', 'range', and others. Note that entering type='text' is not required since 'text' +The form input tag supports entering a type attribute other than 'text'. This is +intended to allow rendering new HTML5 specific input types such as 'email', 'date', +'range', and others. Note that entering type='text' is not required since 'text' is the default type. @@ -1801,7 +1800,6 @@ Similar requirements apply for implementing `AbstractRssFeedView`, as shown belo HttpServletRequest request, HttpServletResponse response) throws Exception { // implementation omitted } - } ---- @@ -1822,7 +1820,7 @@ https://spring.io/blog/2009/03/16/adding-an-atom-view-to-an-application-using-sp [[mvc-view-document-intro]] -=== Introduction +=== Introduction to document views Returning an HTML page isn't always the best way for the user to view the model output, and Spring makes it simple to generate a PDF document or an Excel spreadsheet @@ -1843,166 +1841,45 @@ vulnerability for untrusted PDF content. -[[mvc-view-document-config]] -=== Configuration - -Document based views are handled in an almost identical fashion to XSLT views, and the -following sections build upon the previous one by demonstrating how the same controller -used in the XSLT example is invoked to render the same model as both a PDF document and -an Excel spreadsheet (which can also be viewed or manipulated in Open Office). - - - -[[mvc-view-document-configviews]] -=== View definition - -First, let's amend the views.properties file (or xml equivalent) and add a simple view -definition for both document types. The entire file now looks like this with the XSLT -view shown from earlier: - -[literal] -[subs="verbatim,quotes"] ----- -home.(class)=xslt.HomePage -home.stylesheetLocation=/WEB-INF/xsl/home.xslt -home.root=words - -xl.(class)=excel.HomePage - -pdf.(class)=pdf.HomePage ----- - -__If you want to start with a template spreadsheet or a fillable PDF form to add your -model data to, specify the location as the 'url' property in the view definition__ - - - -[[mvc-view-document-configcontroller]] -=== Controller - -The controller code we'll use remains exactly the same from the XSLT example earlier -other than to change the name of the view to use. Of course, you could be clever and -have this selected based on a URL parameter or some other logic - proof that Spring -really is very good at decoupling the views from the controllers! - - - -[[mvc-view-document-configsubclasses]] -=== Excel views - -Exactly as we did for the XSLT example, we'll subclass suitable abstract classes in -order to implement custom behavior in generating our output documents. For Excel, this -involves writing a subclass of -`org.springframework.web.servlet.view.document.AbstractExcelView` (for Excel files -generated by POI) or `org.springframework.web.servlet.view.document.AbstractJExcelView` -(for JExcelApi-generated Excel files) and implementing the `buildExcelDocument()` method. - -Here's the complete listing for our POI Excel view which displays the word list from the -model map in consecutive rows of the first column of a new spreadsheet: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package excel; - - // imports omitted for brevity - - public class HomePage extends AbstractExcelView { - - protected void buildExcelDocument(Map model, HSSFWorkbook wb, HttpServletRequest req, - HttpServletResponse resp) throws Exception { - - HSSFSheet sheet; - HSSFRow sheetRow; - HSSFCell cell; - - // Go to the first sheet - // getSheetAt: only if wb is created from an existing document - // sheet = wb.getSheetAt(0); - sheet = wb.createSheet("Spring"); - sheet.setDefaultColumnWidth((short) 12); - - // write a text at A1 - cell = getCell(sheet, 0, 0); - setText(cell, "Spring-Excel test"); - - List words = (List) model.get("wordList"); - for (int i=0; i < words.size(); i++) { - cell = getCell(sheet, 2+i, 0); - setText(cell, (String) words.get(i)); - } - } - - } ----- +[[mvc-view-document-pdf]] +=== PDF views -And the following is a view generating the same Excel file, now using JExcelApi: +A simple PDF view for a word list could extend +`org.springframework.web.servlet.view.document.AbstractPdfView` and implement the +`buildPdfDocument()` method as follows: [source,java,indent=0] [subs="verbatim,quotes"] ---- - package excel; + public class PdfWordList extends AbstractPdfView { - // imports omitted for brevity - - public class HomePage extends AbstractJExcelView { - - protected void buildExcelDocument(Map model, WritableWorkbook wb, + protected void buildPdfDocument(Map model, Document doc, PdfWriter writer, HttpServletRequest request, HttpServletResponse response) throws Exception { - WritableSheet sheet = wb.createSheet("Spring", 0); - - sheet.addCell(new Label(0, 0, "Spring-Excel test")); - - List words = (List) model.get("wordList"); - for (int i = 0; i < words.size(); i++) { - sheet.addCell(new Label(2+i, 0, (String) words.get(i))); + List words = (List) model.get("wordList"); + for (String word : words) { + doc.add(new Paragraph(word)); } } } ---- -Note the differences between the APIs. We've found that the JExcelApi is somewhat more -intuitive, and furthermore, JExcelApi has slightly better image-handling capabilities. -There have been memory problems with large Excel files when using JExcelApi however. - -If you now amend the controller such that it returns `xl` as the name of the view ( -`return new ModelAndView("xl", map);`) and run your application again, you should find -that the Excel spreadsheet is created and downloaded automatically when you request the -same page as before. +A controller may return such a view either from an external view definition +(referencing it by name) or as a `View` instance from the handler method. -[[mvc-view-document-configsubclasspdf]] -=== PDF views - -The PDF version of the word list is even simpler. This time, the class extends -`org.springframework.web.servlet.view.document.AbstractPdfView` and implements the -`buildPdfDocument()` method as follows: - -[source,java,indent=0] -[subs="verbatim,quotes"] ----- - package pdf; - - // imports omitted for brevity - - public class PDFPage extends AbstractPdfView { - - protected void buildPdfDocument(Map model, Document doc, PdfWriter writer, - HttpServletRequest req, HttpServletResponse resp) throws Exception { - List words = (List) model.get("wordList"); - for (int i=0; i># The `MappingJackson2JsonView` uses the Jackson library's `ObjectMapper` to render the response content as JSON. By default, the entire contents of the model map (with the exception of framework-specific classes) will be encoded as JSON. For cases where the contents of the map need to be filtered, users may specify a specific set of model attributes to encode -via the `RenderedAttributes` property. The `extractValueFromSingleKeyModel` property may -also be used to have the value in single-key models extracted and serialized directly -rather than as a map of model attributes. +via the `modelKeys` property. The `extractValueFromSingleKeyModel` property may also be +used to have the value in single-key models extracted and serialized directly rather than +as a map of model attributes. JSON mapping can be customized as needed through the use of Jackson's provided annotations. When further control is needed, a custom `ObjectMapper` can be injected @@ -2033,7 +1910,7 @@ serializers/deserializers need to be provided for specific types. [[mvc-view-xml-mapping]] -=== XML +=== Jackson-based XML views [.small]#<># The `MappingJackson2XmlView` uses the @@ -2051,11 +1928,11 @@ serializers/deserializers need to be provided for specific types. [[mvc-view-xml-marshalling]] -== XML +== XML marshalling The `MarshallingView` uses an XML `Marshaller` defined in the `org.springframework.oxm` package to render the response content as XML. The object to be marshalled can be set -explicitly using ``MarhsallingView``'s `modelKey` bean property. Alternatively, the view +explicitly using ``MarshallingView``'s `modelKey` bean property. Alternatively, the view will iterate over all model properties and marshal the first type that is supported by the `Marshaller`. For more information on the functionality in the `org.springframework.oxm` package refer to the chapter @@ -2065,7 +1942,7 @@ by the `Marshaller`. For more information on the functionality in the [[mvc-view-xslt]] -== XSLT +== XSLT views XSLT is a transformation language for XML and is popular as a view technology within web applications. XSLT can be a good choice as a view technology if your application @@ -2084,9 +1961,8 @@ document ready for transformation. [[mvc-view-xslt-beandefs]] === Beans -Configuration is standard for a simple Spring application. -The MVC configuration has to define a `XsltViewResolver` bean and -regular MVC annotation configuration. +Configuration is standard for a simple Spring web application: The MVC configuration +has to define an `XsltViewResolver` bean and regular MVC annotation configuration. [source,java,indent=0] [subs="verbatim,quotes"] @@ -2103,7 +1979,6 @@ public class WebConfig implements WebMvcConfigurer { viewResolver.setSuffix(".xslt"); return viewResolver; } - } ---- @@ -2115,7 +1990,7 @@ And we need a Controller that encapsulates our word generation logic. === Controller The controller logic is encapsulated in a `@Controller` class, with the -handler method being defined like so... +handler method being defined as follows: [source,java,indent=0] [subs="verbatim,quotes"] @@ -2125,7 +2000,6 @@ handler method being defined like so... @RequestMapping("/") public String home(Model model) throws Exception { - Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); Element root = document.createElement("wordList"); @@ -2140,7 +2014,6 @@ handler method being defined like so... model.addAttribute("wordList", root); return "home"; } - } ----