< Day Day Up > |
8.5 PresentationIn most places, the Spring framework doesn't reinvent working technologies. In the area of presentation logic, though, Spring introduces a simple model-view-controller framework called MVC Web that has many competing architectures, like Struts and Java Server Faces (JSF). Take solace, though. You don't have to use MVC Web to use Spring. But if you decide to do so, you will find a few advantages:
If you've ever used Struts, you're familiar with the basic paradigm of MVC Web. Figure 8-4 shows how it works. Controllers basically handle all incoming requests from input views. If the input request is a submitted form, the controller calls a business validation routine, created and configured by the programmer, and sends either the associated error view or success view back to the user, based on results. Figure 8-4. The MVC Web framework works much like Struts8.5.1 ConfigurationAs with other elements of the Spring framework, when you're trying to understand a new application, start with the configuration files and drill down from there. In this example, the user interface is configured in the petstore-servlet.xml file. Consider HTML pages that search for products in a category, and search for products based on keywords. The configuration file needs two controllers to the application context file. Each entry specifies a controller and the model object, like in Example 8-10. Example 8-10. Excerpt from web.xml<bean name="/shop/searchProducts.do" class="jpetstore.web.spring.SearchProductsController"> <property name="petStore"><ref bean="petStore"/></property> </bean> <bean name="/shop/viewProduct.do" class="org.springframework.samples.jpetstore.web. spring.ViewProductController"> <property name="petStore"><ref bean="petStore"/></property> </bean> Recall that all access to our data layer goes through the façade. As you'd expect, these bean ID entries specify the façade, called petstore. Each form in the application works in the same way. Let's drill down further and look at the controller for searchProducts. 8.5.2 ControllersFor MVC Web, each form generally shares a single instance of a controller, which routes all requests related to a given form. It also marshals the form to the correct validation logic and returns the appropriate view to the user. Example 8-11 shows the controller for the searchProducts view. Example 8-11. SearchProductsController.javapublic class SearchProductsController implements Controller { [1] private PetStoreFacade petStore; public void setPetStore(PetStoreFacade petStore) { this.petStore = petStore; } [2] public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { [3] if (request.getParameter("search") != null) { String keyword = request.getParameter("keyword"); if (keyword == null || keyword.length( ) == 0) { return new ModelAndView("Error", "message", "Please enter a keyword to search for, then press the search button."); } else { [4] PagedListHolder productList = new PagedListHolder( this.petStore.searchProductList(keyword.toLowerCase( ))); productList.setPageSize(4); request.getSession( ).setAttribute( "SearchProductsController_productList", productList); [5] return new ModelAndView("SearchProducts", "productList", productList); } } else { [6] String page = request.getParameter("page"); PagedListHolder productList = (PagedListHolder) request.getSession( ). getAttribute("SearchProductsController_productList"); if ("next".equals(page)) { productList.nextPage( ); } else if ("previous".equals(page)) { productList.previousPage( ); } return new ModelAndView("SearchProducts", "productList", productList); } } } Here's what the annotations mean:
8.5.3 FormsJust like Struts, Spring can map HTML forms onto Java objects. Example 8-12 is the Java bean that's returned when a Pet Store user registers an account. Example 8-12. AccountForm.javapublic class AccountForm { private Account account; private boolean newAccount; private String repeatedPassword; public AccountForm(Account account) { this.account = account; this.newAccount = false; } public AccountForm( ) { this.account = new Account( ); this.newAccount = true; } public Account getAccount( ) { return account; } public boolean isNewAccount( ) { return newAccount; } public void setRepeatedPassword(String repeatedPassword) { this.repeatedPassword = repeatedPassword; } public String getRepeatedPassword( ) { return repeatedPassword; } } Each of these bean fields corresponds directly to an HTML input field or control. The Spring framework translates a submit request to the form, which can then be accessed as a POJO for validation, mapping input data, or other purposes. With Spring, unlike Struts, form objects can be any Java bean. There's no need to extend ActionForm. That's important, because you don't need to copy properties from an ActionForm to a domain object or value object. 8.5.4 ValidationYou may have noticed validation logic within the original applciationContext.xml. These beans are generally considered business logic, but they've got a tight relationship to the user interface and they're invoked directly by the Spring framework. When a user submits a form, Spring fires the validation logic. Based on the result, Spring routes control to the appropriate page. Example 8-13 shows the AccountValidator class, which validates the account form. Example 8-13. AccountValidator.javapublic class AccountValidator implements Validator { public boolean supports(Class clazz) { return Account.class.isAssignableFrom(clazz); } public void validate(Object obj, Errors errors) { ValidationUtils.rejectIfEmpty(errors, "firstName", "FIRST_NAME_REQUIRED", ValidationUtils.rejectIfEmpty(errors, "lastName", "LAST_NAME_REQUIRED", ValidationUtils.rejectIfEmpty(errors, "email", "EMAIL_REQUIRED", ValidationUtils.rejectIfEmpty(errors, "phone", "PHONE_REQUIRED", ValidationUtils.rejectIfEmpty(errors, "address1", "ADDRESS_REQUIRED", ValidationUtils.rejectIfEmpty(errors, "city", "CITY_REQUIRED", ValidationUtils.rejectIfEmpty(errors, "state", "STATE_REQUIRED", ValidationUtils.rejectIfEmpty(errors, "zip", "ZIP_REQUIRED", "ZIP is required."); ValidationUtils.rejectIfEmpty(errors, "country", "COUNTRY_REQUIRED", } } In this example, the Spring framework makes life easier for developers in several ways. The developer does not need to write validation methods by hand. Also, many prepackaged methods exist. The framework takes care of validation and routing. The framework takes care of routing control based on success or failure. One chapter on the Spring framework cannot do it justice, but you've seen the overall gist of it. The advantages of the framework—and more importantly, this coding style—should jump off the page at you if you haven't seen it before. In particular, notice the clarity and simplicity that a cleanly layered architecture provides. You can probably imagine how easy it is to incorporate business logic with a transparent framework like Spring. |
< Day Day Up > |