Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 42 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
42
Dung lượng
557,66 KB
Nội dung
Summary Tiles is a rich technology for creating components in your web pages, and our overview of Spring’s Tiles support doesn’t scratch the surface of what can be achieved with this view type. If you’re new to Tiles, or if you’d like further information on Spring’s Tiles support, see Pro Spring (Apress, 2004), which has a much more in-depth examination. Velocity and FreeMarker Velocity (http://jakarta.apache.org/velocity) and FreeMarker (http://www.freemarker.org) are both templating technologies. They are purely text-based engines, and both are in wide- spread use in applications of all kinds that produce text output. Obviously, web applications are one such subset. As our topic is Web MVC applications, though, we’re going to consider just that aspect of them both. CHOOSING A TEMPLATING LANGUAGE Choosing between Velocity and FreeMarker is a discussion beyond the scope of this book. The only real dif- ferences from a technical point of view in applying these engines in a Spring application is in their respective templating languages. If you have no experience of either but would like to try them, we suggest perusing the documentation for both at their respective websites and deciding which suits you and your team best. Templating Pros and Cons Unlike JSP, Velocity and FreeMarker templates are not compiled into Java classes; rather, they are interpreted by their respective template engines. This makes them more akin to XSLT than JSP. Despite this, there seems to be no performance penalty in applying either of them in place of JSP. In fact in many benchmarks, Velocity outperforms JSP as the view layer. This is because, although not compiled to byte code, the templates are cached in an efficient binary format by the template engines when they are first read. An advantage of both over JSP is that you can’t easily break out of the templating language and start coding Java, so there’s less danger that domain logic will leak into the view layer with either of these solutions. The disadvantages are that you need a little extra configuration to integrate them smoothly into your application, your preferred IDE may not have good support for them, and, of course, your developers or designers may need to learn an unfamiliar template language. The relevant JAR files will need to be added to your WEB-INF/lib (they ship with Spring in case you need them), and for Velocity, you will also need to add commons-collections.jar to your application. To be frank, however, the additional configuration is trivial, and the template lan- guages are both significantly simpler than something like Java. In our opinion, the advantages probably just outweigh the disadvantages. CHAPTER 8 ■ SUPPORTED VIEW TYPES 235 584X_Ch08_FINAL 1/30/06 1:34 PM Page 235 ■Note The Eclipse IDE (and consequently IBM’s WSAD) can be extended with support for both Velocity and FreeMarker template editing through the use of two open-source plugins. See http://veloedit. sourceforge.net and http://freemarker.sourceforge.net/eclipse.html, respectively.Your mileage may vary with other IDEs. Basic Configuring for Template Engines The Velocity (or FreeMarker) engine needs to be configured using one of the Spring-supplied classes. This usually happens in the servlet context file. Listing 8-17 shows you how. Listing 8-17. Configuring the Velocity Engine <bean id="velocityConfigurer" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer" <property name="resourceLoaderPath" value="WEB-INF/velocity"/> </bean> ■Note For FreeMarkerConfigurer the property name for the template loading path is templateLoaderPath, although from Spring version 1.3 that may be deprecated and you should use resourceLoaderPath for either. VelocityConfigurer (and FreeMarkerConfigurer) wrap access to the actual template engine (VelocityEngine and Configuration,respectively). The most important property to set on these objects is the one highlighted in the example. The resourceLoaderPath determines where Velocity will look for your template files. As with JSP, it’s a good idea to make these inac- cessible to web clients by placing them somewhere inside the WEB-INF directory. There are many important properties that can be set on the respective configurer beans, some of which we’ll explore later. For now, let’s complete the integration by setting up a ViewResolver. Spring’s general ViewResolvers (ResourceBundleViewResolver and XmlViewResolver) are perfectly adequate for any kind of View, template views included. But often, when your appli- cation consists of only one view type it makes sense to take advantage of a specific resolver to keep things a little simpler. For Velocity and FreeMarker, Spring offers VelocityViewResolver and FreeMarkerViewResolver. Figure 7-5 in the previous chapter showed where these resolvers fit into the general hierarchy. Listing 8-18 shows a simple configuration of them. Listing 8-18. ViewResolver Configuration <bean id="velocityResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"> <property name="prefix" value="" /> <property name="suffix" value=".vm"/> </bean> CHAPTER 8 ■ SUPPORTED VIEW TYPES236 584X_Ch08_FINAL 1/30/06 1:34 PM Page 236 <bean id="freemarkerResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"> <property name="prefix" value="" /> <property name="suffix" value=".ftl"/> </bean> ■Caution The prefix property on the ViewResolver is relative to the resourceLoaderPath. When set- ting the resourceLoaderPath to WEB-INF/velocity, as we did earlier, we then needed to ensure that the ViewResolver prefix was empty. This differs a little from the way InternalResourceViewResolver is usually configured for JSPs. As you’ll remember from the discussions on InternalResourceViewResolver, your Controllers need only specify the View key—in this case home—and the resolver will do the rest. With Velocity, for example, the resolver looks in the specified template directory (WEB-INF/velocity, which we set on the VelocityConfigurer bean) for a file with a prefix of "", a name of home, and a suffix of .vm. In other words, WEB-INF/velocity/home.vm. In the simplest cases you need do no more. Your templates are placed in WEB-INF/velocity, and you’ve defined the engine configuration and ViewResolver beans that form the basis of Spring’s integration for these template languages. For the sample application home page this is fine. Figure 8-3 shows the file system layout. Figure 8-3. WEB-INF directory with several view layers and the libraries required CHAPTER 8 ■ SUPPORTED VIEW TYPES 237 584X_Ch08_FINAL 1/30/06 1:34 PM Page 237 Exposing the Model As always, the specific View implementation is responsible for knowing what to do with a model generated by your Controllers. For VelocityView, each object in the model is added to a VelocityContext instance, which is what the Velocity engine uses to merge with the template. FreeMarker works happily with Map objects as models, and so no conversion is necessary. The Template Language Before moving on, let’s take a sneak peek at the actual template files used for the home page. Listing 8-19 shows an example of Velocity Template Language (VTL). In fact, it’s the familiar home page of the sample application converted from the JSP example in Listing 8-5. Listing 8-19. Sample Home Page in VTL <body> <h1>Welcome to the Flight Booking Service</h1> <p>We have the following specials now:</p> <ul> #foreach ($special in $specials) <li> ${special.departFrom.name} - ${special.arriveAt.name} from $${special.cost} </li> #end </ul> <p><a href="search">Search for a flight.</a></p> </body> Listing 8-20 shows the FreeMarker equivalent for completeness. From here on, we’ll mostly show just Velocity examples unless there are noteworthy differences in FreeMarker handling. Listing 8-20. The Home Page Again—This Time in FTL <body> <h1>Welcome to the Flight Booking Service</h1> <p>We have the following specials now:</p> <ul> <#list specials as special> <li> ${special.departFrom.name} - ${special.arriveAt.name} from CHAPTER 8 ■ SUPPORTED VIEW TYPES238 584X_Ch08_FINAL 1/30/06 1:34 PM Page 238 $${special.cost} </li> </#list> </ul> <p><a href="search">Search for a flight.</a></p> </body> As you can see, it’s not terribly difficult to get a basic templating solution in place as the view layer. Let’s go a little deeper and look at some of the more advanced configurations and also what Spring offers in the way of bind support for Velocity and FreeMarker. Advanced Configuration Options Many properties and settings can be used to affect the way your templating engine operates. Certain properties will determine how templates are loaded and cached, how locales are man- aged, how macros are handled, and more. All of these are beyond the scope of this book, but if you are looking at Velocity or FreeMarker for the first time, we strongly recommend that you familiarize yourself with all these options. To hook into these advanced options, you can specify the location of an external proper- ties file (you may have one of these if you’ve previously used Velocity or FreeMarker outside of a Spring application). On the configurer object, set the property named configLocation to wherever the configuration file may be found. The value of configLocation is interpreted as a Spring Resource,which means you can use classpath, file, or URL-based locations. See the Spring reference documentation for information about Spring Resources. You can alternatively set such properties locally on the configurer instance if you have no need to use those proper- ties outside of your MVC application. Listing 8-21 shows an example of both options. Listing 8-21. Setting Engine-Specific Properties via the Configurer Bean <bean id="velocityConfigurer" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer"> <property name="resourceLoaderPath" value="/WEB-INF/velocity"/> <! inline velocity properties > <property name="velocityProperties"> <props> <prop key="velocimacro.library.autoreload">true</prop> </props> </property> </bean> <bean id="freemarkerConfigurer" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"> <property name="templateLoaderPath" value="/WEB-INF/freemarker"/> <! load freemarker props from the classpath > <property name="configLocation" value="classpath:com/apress/expertspringmvc/fm.properties"/> </bean> CHAPTER 8 ■ SUPPORTED VIEW TYPES 239 584X_Ch08_FINAL 1/30/06 1:34 PM Page 239 ■Note Check the relevant Velocity and FreeMarker documentation at their respective websites to see the range of properties and settings that can be configured on the two engines. By default, Spring doesn’t expose request or session attributes to your template engines. If you want to access those values in your templates, you need to tell Spring to make them avail- able. This is the same mechanism for both Velocity and FreeMarker, as the relevant properties are part of a common superclass (shown in Figure 8-4). Figure 8-4. AbstractTemplateView detail Listing 8-22 has an example of exposing request and session attributes for a VelocityView instance. Listing 8-22. Exposing Session and Request Attributes on a View attributeView.class=org.springframework.web.servlet.view.velocity.VelocityView attributeView.exposeRequestAttributes=true attributeView.exposeSessionAttributes=true AbstractTemplateView + SPRING MACRO REQUEST CONTEXT ATTRIBUTE : String - exposeRequestAttributes : boolean - exposeSessionAttributes : boolean - exposeSpringMacroHelpers : boolean - allowRequestOverride : boolean - allowSessionOverride : boolean + setExposeRequestAttributes(exposeRequestAttributes : boolean) + setExposeSessionAttributes(exposeSessionAttributes : boolean) + setAllowRequestOverride(allowRequestOverride : boolean) + setAllowSessionOverride(allowSessionOverride : boolean) + setExposeSpringMacroHelpers(exposeSpringMacroHelpers : boolean) # renderMergedOutputModel(model : Map, request : , response : HttpServletResponse) # renderMergedTemplateModel(model : Map, request : , response : HttpServletResponse) FreeMarkerView VelocityView CHAPTER 8 ■ SUPPORTED VIEW TYPES240 584X_Ch08_FINAL 1/30/06 1:34 PM Page 240 ■Tip You can specify exactly the same values on either FreeMarkerViewResolver or VelocityViewResolver. All Views resolved by the resolver will have those properties set accordingly. Forms and the SpringBind Macros Spring’s bind support, made available to JSPs via the tag library, has also been extended to Velocity and FreeMarker. This makes either an excellent solution for displaying forms, valida- tion results, and localized messages in your Spring MVC application. To make the bind support and the Spring macros available to your template, you must configure the relevant View. You do this exactly the same way we handled the request and session attribute exposure earlier. On either a View or the ViewResolver, set the property exposeSpringMacroHelpers to true. ■Tip Spring’s Velocity and FreeMarker macros are shipped as part of the spring.jar file that you place in your WEB-INF/lib folder of your application. They are also copied to the dist directory if you build Spring from source. However you don’t need to copy those files into your application’s template directories as Spring configures the template engine to load the macros directly from the spring.jar file. Listing 8-23 shows the VelocityViewResolver definition enhanced to make the Spring bind macros available to all of the Views that it will resolve. Listing 8-23. Making Spring Macros Available to All Velocity Views <bean id="velocityResolver" class="org.springframework.web.servlet.view.velocity.VelocityViewResolver"> <property name="prefix" value="" /> <property name="suffix" value=".vm"/> <property name="exposeSpringMacroHelpers" value="true"/> </bean> We covered general bind support in our overview of the JSP tag libraries earlier, so let’s get straight to the heart of the templating versions with another Velocity example. Listing 8-24 demonstrates a basic form using the #springBind macro, which is the equivalent of the <spring:bind> tag in JSP. Listing 8-24. Binding to a Command Object Field in a Velocity Template <html> <body> <h1>Form Submission</h1> <p>Please tell us your first name.</p> <form action="" method="POST"> CHAPTER 8 ■ SUPPORTED VIEW TYPES 241 584X_Ch08_FINAL 1/30/06 1:34 PM Page 241 #springBind("command.firstName") <input type="text" name="$status.expression" value="$!status.value" /><br> #foreach($error in $status.errorMessages) <b>$error</b> <br> #end <input type="submit" value="submit"/> </form> </body> </html> ■Caution Velocity imports macro definitions into a global namespace, which means all macros are avail- able from all your templates once they have been loaded. FreeMarker, on the other hand, allows macros to be subdivided into separate namespaces. When using the Spring macros in FreeMarker you have to import them into each template that you wish to use them in. Add the following line to the top of your FreeMarker templates: <#import "spring.ftl" as spring />. The binding behavior is exactly the same as we outlined for JSP bind support. It uses the same code under the covers. If you submit a valid form, the command object will have its cor- responding field set to the user-submitted value. Conversely, if validation errors occur such as the field being left blank, the form will be redisplayed, and each error in the status.errorMessages field can be highlighted to the user. If a value had been submitted in the field, the original incorrect value will be redisplayed in the input field. So far, so simple. It’s no different from JSP’s <spring:bind> tag behavior, other than the syntactical differences in the template language. For Velocity and FreeMarker, however, you have (since Spring 1.1) been able to enjoy an additional suite of macros that build upon #springBind and generate a lot of the form field content for you based on optional parameters that you supply. Table 8-2 shows the full range of macros available to your templates. ■Tip In FreeMarker, the two macros marked (*) in the following table exist but are not actually required, as you can use the normal formInput macro, specifying hidden or password as the value for the fieldType parameter. It’s a fairly comprehensive set of form-handling functionality. We’ll look at a few common examples and leave you to explore the remainder within your own applications. Listing 8-25 shows a fragment of the beginSearch.vm template in the example application. It uses the basic #springFormInput macro to generate a couple of input fields. CHAPTER 8 ■ SUPPORTED VIEW TYPES242 584X_Ch08_FINAL 1/30/06 1:34 PM Page 242 Table 8-2. Template Macros Available for Velocity and FreeMarker Macro Description Velocity FreeMarker bind #springBind($path) <@spring.bind path> message (output a string from #springMessage($code) <@spring.message code/> a resource bundle based on the code parameter) messageText (output a string #springMessageText($code $default) <@spring.messageText code, default/> from a resource bundle based on the code parameter, falling back to the value of the default parameter) url (prefix a relative URL with #springUrl($relativeUrl) <@spring.url relativeUrl/> the application’s context root) formInput (standard input #springFormInput($path $attributes) <@spring.formInput path, attributes, field for gathering user input) fieldType/> formHiddenInput* (hidden #springFormHiddenInput($path $attributes) <@spring.formHiddenInput path, input field for submitting attributes/> non-user input) formPasswordInput* (standard #springFormPasswordInput($path $attributes) <@spring.formPasswordInput path, input field for gathering attributes/> passwords; note that no value will ever be populated in fields of this type) formTextarea (large text field for #springFormTextarea($path $attributes) <@spring.formTextarea path, gathering long, freeform text input) attributes/> formSingleSelect (drop-down #springFormSingleSelect( $path $options $attributes) <@spring.formSingleSelect path, box of options allowing a single options, attributes/> required value to be selected) formMultiSelect (a list box of #springFormMultiSelect($path $options $attributes) <@spring.formMultiSelect path, options allowing the user to options, attributes/> select 0 or more values) (Continued) CHAPTER 8 ■ SUPPORTED VIEW TYPES 243 584X_Ch08_FINAL 1/30/06 1:34 PM Page 243 Table 8-2. Continued Macro Description Velocity FreeMarker formRadioButtons #springFormRadioButtons($path $options $separator $attributes) <@spring.formRadioButtons path, (a set of radio buttons options separator, attributes/> allowing a single selection to be made from the available choices) formCheckboxes #springFormCheckboxes($path $options $separator $attributes) <@spring.formCheckboxes path, options, (a set of check boxes separator, attributes/> allowing 0 or more values to be selected) showErrors (simplify #springShowErrors($separator $classOrStyle) <@spring.showErrors separator, display of validation classOrStyle/> errors for the bound field) CHAPTER 8 ■ SUPPORTED VIEW TYPES244 584X_Ch08_FINAL 1/30/06 1:34 PM Page 244 [...]... model.get("specials"); Document doc = DocumentBuilderFactory newInstance() newDocumentBuilder() newDocument(); Element rootEl = doc. createElement(root); doc. appendChild(rootEl); for (SpecialDeal deal : specials) { Element dealEl = doc. createElement("deal"); Element fromEl = doc. createElement("from"); fromEl.appendChild( doc. createTextNode(deal.getDepartFrom().getName())); Element toEl = doc. createElement("to");... add-on to core Spring In fact, validation is not even considered part of Spring MVC Validators are implementations of the org.springframework.validation.Validator interface They are stateless singleton classes that are configured in the Spring ApplicationContext and injected into your Controllers and test objects and their property values Validators are stateless objects just like Spring MVC Controllers... getModel(); model.put("format", reportFormat); return new ModelAndView("report", model); } With proper configuration of the request URIs in your dispatcher’s context file, this method can now be used to serve multiple format reports For example, a request of /ExpertSpringMVC/app/home.pdf will result in a PDF version of the report, and /ExpertSpringMVC/app/home.xls will generate an Excel spreadsheet–based... all those great features to your Spring MVC applications Creating New Views That pretty much concludes our tour of supported view technologies in Spring applications— and there was a lot of information to cover and take in But what do you do in the unlikely event that Spring has no first-class support for your favorite view technology? Write it yourself, of course! Spring is highly extensible in all... VIEW TYPES Summary In this chapter we’ve looked at the various technologies that can be used within your Spring Web MVC application, including JSP templating technologies, XSLT, and document-based , views We also covered how to create your own view types that fit within the Spring architecture and that allow your application to display models in unusual ways We’ve presented a lot of information in... that we want to use and the URL pointing to the template we want to use Listing 8-42 has the details Listing 8-42 views.properties Configuration for Excel Home Page home.class=com.apress.expertspringmvc.flight .web. view.HomePageExcel home.url= /WEB- INF/excel/home When we hit the home page of our application now, the spreadsheet is created on the fly from a combination of the model and the template Either... up through an org.springframework.context.MessageSource instance; by default this is the ApplicationContext Let’s extend the Address domain class Validator See Listing 9-3 Listing 9-3 More Elaborate Validator for Address Objects package com.apress.expertspringmvc.validation; import org.springframework.validation.Validator; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils;... Home Page home.class=org.springframework .web. servlet.view.jasperreports.JasperReportsPdfView home.url= /WEB- INF/jasper/home.jrxml The file home.jrxml is the report design itself Jasper reports are natively XML, which is great if you need to get in and do low-level editing of a report, but coding one by hand can be quite laborious A few GUI designers are available that will read and write Jasper’s report... text entered by the user prior to submitting the form ■ In Spring 1.2.6 the macros will also add an id attribute to the form fields that will have the same Tip value as the name attribute This makes the fields more accessible to JavaScript, for example #springFormHiddenInput and #springFormPasswordInput are basically similar to the standard #springFormInput macro The only difference being that the input... home.class=org.springframework .web. servlet.view.jasperreports.JasperReportsPdfView home.reportDataKey=jasperData home.url= /WEB- INF/jasper/home.jrxml In Listing 8-46, the Controller returns a model consisting of multiple objects, one of which is keyed under the name specified as the report data key in the View Listing 8-46 A Model Containing the Report Data and Other Attributes public ModelAndView handleReport( . model.get("specials"); Document doc = DocumentBuilderFactory .newInstance() .newDocumentBuilder() .newDocument(); Element rootEl = doc. createElement(root); doc. appendChild(rootEl); for. View home.class=com.apress.expertspringmvc.flight .web. view.HomePage home.stylesheetLocation= /WEB- INF/xsl/home.xslt Interestingly, the View class is obviously not provided by Spring but belongs to. we suggest perusing the documentation for both at their respective websites and deciding which suits you and your team best. Templating Pros and Cons Unlike JSP, Velocity and FreeMarker templates