Sie sind auf Seite 1von 109

Spring 3 MVC

Basics

Sang Shin
javapassion.com
“Learn with Passion!”

1
Topics
• Introduction to Spring MVC
> DispatchServlet, Context configuration
• Controller
> Annotation-based controllers, Request mapping, URI
template, request mapping with other means,
Handler method arguments, Handler methods return
types
• Handler mapping customization
> Interceptor
• Resolving views
> Spring-provided view resolvers, Chaining view
resolvers
• Spring 3 <mvc:.. > configuration 2
Spring Framework Codecamp
• This topic is one of many topics that are
covered in Spring Framework codecamp
> javapassion.com/codecamps
• Spring framework topics
> Spring DI basics, Spring DI advanced, Spring DI
annotation
> Spring MVC basics, form handling, Ajax, REST, Views
> Spring Webflow
> Spring database access (JDBC, Hibernate, JPA),
transaction
> Spring AOP, Spring security, Spring testing
> Spring JMS, Spring JMX
> Spring Roo
3
What is Spring MVC?
• MVC-based Web application framework that
takes advantage of design principles of Spring
framework
> Dependency Injection
> Interface-driven design
> POJO style everywhere

4
Features
Spring Web MVC
Framework

5
Features of Spring Web MVC
• Clear separation of roles
> Controller, validator, command object, form object,
model object, DispatcherServlet, handler mapping,
view resolver, and so on -- can be fulfilled by a
specialized object and replaceable without affecting
others
• Powerful and straightforward configuration of
both framework and application classes as
JavaBeans
• Adaptability, non-intrusiveness, and flexibility
> Define any controller method signature you need,
possibly using one of the parameter annotations
(such as @RequestParam, @RequestHeader,
@PathVariable, and more) for a given scenario
6
Features of Spring Web MVC (Continued)
• Customizable binding (conversion) and
validation
• Customizable handler mapping and view
resolution
> Handler mapping and view resolution strategies
range from simple URL-based configuration, to
sophisticated, purpose-built resolution strategies.
• Flexible model transfer
> Model transfer with a name/value Map supports easy
integration with any view technology
• Customizable locale and theme resolution
• A simple yet powerful JSP tag library known as
the Spring tag library
7
DispatcherServlet

8
DispatcherServlet
• It plays the role of Front controller in Spring MVC
> Coordinates the HTTP request life-cycle
> Configured in web.xml

9
Sequence of HTTP Request Handling
1. DispatchServlet receives a HTTP request
2. DispatchServlet selects a Controller based on the
URL Handler mapping and pass the request to the
Controller
3. Controller (actually handler in a Controller)
performs the business logic and set values of
Model objects
4. Controller returns a logical view
5. A ViewResolver, which provides a particular view
(JSP, PDF, Excel, etc.), is selected
6. A view gets displayed using values of Model
objects
10
DispatcherServlet Configuration
• Configured in the “web.xml” file as a regular
servlet
<web-app>
<servlet>
<servlet-name>example</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>example</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>

11
Spring Context
Configuration

12
Typical Configuration Setup
• Two Spring bean containers (or
ApplicationContexts) initialized - not mandatory
> 1 “root” context to host “shared resources” required
by servlets/filters/services
> 1 “web” context to host local application
components delegated by the DispatchServlet

13
Example: web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param> Root context
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>
<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Processes application requests -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Web context
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
14
15
Default Location/Name of Web Context File
• The location and name of the Web context file
is typically configured with DispatcherServlet
> As you've seen in the previous slide
• If it is not configured, Spring searches the
default web context file
> /WEB-INF/[servlet-name]-servlet.xml
• Example
<!-- Spring will search for /WEB-INF/appServlet-servlet.xml -->
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class> org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

16
WebApplicationContext File
• Spring MVC beans that can be defined in the
WebApplicationContext file include
> Controllers
> Handler mappings
> View resolvers
> Locale resolvers
> Theme resolvers
> Multipart file resolver
> Hanlder exception resolvers

17
Spring MVC
Interfaces

18
Spring MVC Interfaces

• Key features of the Spring MVC are


modularized through Spring MVC interfaces
> Custom implementations can be created and
configured
> This is how Spring framework itself can be
extended and customized
• Spring framework comes with built-in
implementations of the interfaces
> Default implementation is pre-selected for most
common cases

19
Spring MVC Interfaces

• HandlerMapping
> Routing of requests to handlers (controllers)
• ViewResolver
> Maps symbolic name to view
• HandlerExceptionResolver
> Maps exceptions to error pages
> Similar to standard Servlet, but more flexible
• LocaleResolver
> Selects locale based on HTTP accept header,
cookie

20
Controllers

21
What does a Controller do?
• Controllers provide access to the business logic
> Typically a controller delegates business logic
processing to a set of services
> The services in turn access database through Dao
interface
• Controllers interpret user input and transform it
into a model and set attributes (key/value
pairs) of the model as a result of business logic

22
Controllers:
Annotation-based
Controllers

23
Annotation-based Controllers
• In pre-Spring 2.5, you had to extend Spring-
specific base controller classes
> SimpleFormController, MultiActionController, etc
> Your controller code is tied up with framework - they
are not POJO's
• Spring 2.5 introduced an annotation-based
controllers
> Annotation-based controllers do not have to extend
specific base controller classes or implement specific
interfaces.
> Annotation-based controllers do not usually have
direct dependencies on Servlet or Portlet APIs either
> Annotation-based controllers are POJO's
24
Annotation-based Controller
// Annotation-based Controller do not have
// to extend specific Spring base classes or implement
// specific interfaces.
@Controller
public class HelloWorldController {
// There is no constraint to the method signature either
@RequestMapping("/helloWorld")
public ModelAndView helloWorld() {
ModelAndView mav = new ModelAndView();
mav.setViewName("helloWorld"); // set the view
mav.addObject("message", "Hello World!");
return mav;
}
}

25
Auto-detection of Annotated Controllers
• Through component scanning, all annotated controller
beans are automatically detected - there is no need to
declare them in the context configuration file

<?xml version="1.0" encoding="UTF-8"?>


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan
base-package="org.springframework.samples.petclinic.web"/>
// ...
26
</beans>
Controllers:
Mapping Requests to
Handlers with
@RequestMapping

27
Mapping requests with @RequestMapping
• @RequestMapping annotation is used to map
URLs such as /appointments onto a class (when
used over a class) or a particular handler
method (when used over a method)

28
Mapping requests with @RequestMapping
@Controller
@RequestMapping("/appointments")
public class AppointmentsController {
private final AppointmentBook appointmentBook;
@Autowired
public AppointmentsController(AppointmentBook appointmentBook) {
this.appointmentBook = appointmentBook;
}
// Handle http://locahost:8080/myapp/appointments
@RequestMapping(method = RequestMethod.GET)
public Map<String, Appointment> get() {
return appointmentBook.getAppointmentsForToday();
}
// Handle http://locahost:8080/myapp/appointments/4 or
// http://locahost:8080/myapp/appointments/5
@RequestMapping(value="/{day}", method = RequestMethod.GET)
public Map<String, Appointment> getForDay (
@PathVariable @DateTimeFormat(iso=ISO.DATE) Date day, Model model) {
return appointmentBook.getAppointmentsForDay(day);
} 29
@RequestMapping for Form Handling
// Continued from previous slide
// Handles http://locahost:8080/myapp/appointments/new
// Display initial form
@RequestMapping(value="/new", method = RequestMethod.GET)
public AppointmentForm getNewForm() {
return new AppointmentForm();
}
// Handles http://locahost:8080/myapp/appointments/new
// Handle form submission
@RequestMapping(value="/new", method = RequestMethod.POST)
public String add(@Valid AppointmentForm appointment,
BindingResult result) {
if (result.hasErrors()) {
return "appointments/new";
}
appointmentBook.addAppointment(appointment);
return "redirect:/appointments";
}
}

We will cover “form handling” in detail in another


presentation and hands-on lab - “spring3_mvc_form”. 30
@RequestMapping Only at Method Levels
// A @RequestMapping on the class level is not required. Without it, all paths
// are simply absolute, and not relative.
@Controller
public class ClinicController {
private final Clinic clinic;
@Autowired
public ClinicController(Clinic clinic) {
this.clinic = clinic;
}
// Handles http://locahost:8080/myapp/
@RequestMapping("/")
public void welcomeHandler() {
}
// Handles http://locahost:8080/myapp/vets
@RequestMapping("/vets")
public ModelMap vetsHandler() {
return new ModelMap(this.clinic.getVets());
}
} 31
Controllers:
URI Template

32
What is URI Template?
• A URI Template is a URI-like string, containing
one or more variable names
> Variables are in the form of {nameOfVariable}
@RequestMapping(value="/owners/{ownerId}"))
• When you substitute values for these variables,
the template becomes a concrete URI.
/owners/3
/owners/5

• The request URI is compared to an matching


URI Template

33
URI Template Example #1
// Suppose the request URL is http://locahost:8080/myapp/owners/3,
// the value 3 will be captured as “ownerId” argument in String type.
@RequestMapping(value="/owners/{ownerId}", method=RequestMethod.GET)
public String findOwner(@PathVariable String ownerId, Model model) {
Owner owner = ownerService.findOwner(ownerId);
model.addAttribute("owner", owner);
return "displayOwner";
}

34
URI Template Example #2
// You can use multiple @PathVariable annotations to bind to multiple URI
// Template variables.
// Suppose the request URL is http://locahost:8080/myapp/owners/3/pets/5,
// the value 3 will be captured as “ownerId” argument in String type while
// the value 5 will be captured as “petId” argument in String type.
@RequestMapping(value="/owners/{ownerId}/pets/{petId}",
method=RequestMethod.GET)
public String findPet(@PathVariable String ownerId,
@PathVariable String petId,
Model model) {
Owner owner = ownerService.findOwner(ownderId);
Pet pet = owner.getPet(petId);
model.addAttribute("pet", pet);
return "displayPet";
}

35
URI Template Example #3
// You can use multiple @PathVariable annotations to bind to multiple URI
// Template variables
@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
@RequestMapping("/pets/{petId}")
public void findPet(@PathVariable String ownerId,
@PathVariable String petId, Model model) {
// implementation omitted
}
}

36
Controllers:
Mapping Requests with
Other Means

37
Mappings through parameter conditions
// You can narrow path mappings through parameter conditions: a sequence of
// "myParam=myValue" style expressions, with a request only mapped if each
// such parameter is found to have the given value.
@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
// Handles http://locahost:8080/myapp/owners/3/pets/5?myParam=myValue
@RequestMapping(value = "/pets/{petId}", params="myParam=myValue")
public void findPet(@PathVariable String ownerId, @PathVariable String petId,
Model model) {
// implementation omitted
}
}

38
Mappings through HTTP header conditions
// The addPet() method is only invoked when the content-type matches the
// text/* pattern, for example, text/xml
@Controller
@RequestMapping("/owners/{ownerId}")
public class RelativePathUriTemplateController {
@RequestMapping(value = "/pets", method = RequestMethod.POST,
headers="content-type=text/*")
public void addPet(Pet pet, @PathVariable String ownerId) {
// implementation omitted
}
}

39
Controllers:
Handler Method
Arguments

40
Objects that are auto-created by Spring
• You can simply use these as handler arguments
• Request or response objects (Servlet API)
> ServletRequest or HttpServletRequest
• Session object (Servlet API)
> HttpSession
• java.util.Locale
> For the current request locale, determined by the
most specific locale resolver available
• java.security.Principal
> Currently authenticated user

41
@PathVariable & @RequestParam
• @PathVariable
> Annotated parameters for access to URI template
variables
> Extracts data from the request URI
> http://host/catalog/items/123
> Parameter values are converted to the declared
method argument type
• @RequestParam(“namex”)
> Annotated parameters for access to specific Servlet
request parameters.
> Extracts data from the request URI query parameters
> http://host/catalog/items/?namex=abc
> Parameter values are converted to the declared
method argument type 42
@PathVariable - For URI Path Values
// Use the @PathVariable annotation to bind URI path value to a method
// parameter in your controller.
@Controller
@RequestMapping("/pets")
public class MyPetClass {
// ...
// Will handle ../pets/4 or ../pets/10
@RequestMapping(method = RequestMethod.GET)
public String getData(@PathVariable int petId, ModelMap model) {
Pet pet = this.clinic.loadPet(petId);
model.addAttribute("pet", pet);
return "petForm";
}
// ...

43
@RequestParam - For Query Parameters
// Use the @RequestParam annotation to bind query request parameters to a
// method parameter in your controller.
@Controller
@RequestMapping("/pets")
public class MyPetClass {
// ...
// Will handle ../pets?petId=4 or ../pets?petId=10
@RequestMapping(method = RequestMethod.GET)
public String getData(@RequestParam("petId") int petId, ModelMap model) {
Pet pet = this.clinic.loadPet(petId);
model.addAttribute("pet", pet);
return "petForm";
}
// ...

44
Request Header and Body
• @RequestHeader(“name”)
> Annotated parameters for access to specific Servlet
request HTTP headers
• @RequestBody
> Annotated parameters for access to the HTTP
request body.
> Parameter values are converted to the declared
method argument type using
HttpMessageConverter's

45
@RequestBody
// The @RequestBody method parameter annotation indicates that a method
// parameter should be bound to the value of the HTTP request body.
@RequestMapping(value = "/something", method = RequestMethod.PUT)
public void handle(@RequestBody String body, Writer writer)
throws IOException {
writer.write(body);
}

46
Controllers:
Handler Method
Arguments - Implicit
Models

47
Implicit Models as Handler Arguments
• These are exposed to the view
> View can access these models after attributes of
these models are set in the handler methods
• Model types that are allowed
> java.util.Map
> org.springframework.ui.Model
> Holder of attributes
> org.springframework.ui.ModelMap
> Supports chained calls and auto-generation of model
attribute names.

48
Model object as Handler argument
@RequestMapping(value = "/hotels-search", method = RequestMethod.GET)
public String list(SearchCriteria criteria, Model model) {
// Using the "SearchCriteria", perform the search through
// "bookingService".
List<Hotel> hotels = bookingService.findHotels(criteria);
// Add an attribute to the model. The view now can access
// “hotelList” through ${hotelList} notation
model.addAttribute(“hotelList”, hotels);
// Return logical view name "hotels/list", which results in displaying
// "hotels/list.jsp".
return "hotels/list";
}

49
View that accesses the Model
<table class="summary">
<thead>
<tr>
<th>Name</th>
<th>Address</th>
<th>City, State</th>
<th>Zip</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<c:forEach var="hotel" items="${hotelList}">
<tr>
<td>${hotel.name}</td>
<td>${hotel.address}</td>
<td>${hotel.city}, ${hotel.state}, ${hotel.country}</td>
<td>${hotel.zip}</td>
<td><a href="hotels/${hotel.id}">View Hotel</a></td>
</tr>
</c:forEach>
<c:if test="${empty hotelList}">
<tr>
<td colspan="5">No hotels found</td>
</tr>
</c:if>
</tbody> 50
</table>
ModelMap object as Handler argument
@RequestMapping("/deposit.do")
protected String deposit(
@RequestParam("accountNo") int accountNo,
@RequestParam("amount") double amount,
ModelMap modelMap) {
accountService.deposit(accountNo, amount);
// Chaining is allowed for ModelMap object
modelMap.addAttribute("accountNo", accountNo)
.addAttribute("balance", accountService.getBalance(accountNo));
return "success";
}

51
Controllers:
HttpMessageConverters

52
HttpMessageConverter's
• Behind the scene, a HttpMessageConverter is
involved for reading request body and
generating response body
• Different converters are registered for different
content types
• For @RequestBody, the first converter that can
read the POSTed “Content-Type” into the
desired method parameter type is used
• For @ResponseBody, the first converter that
can write the method return type into one of
the client's “Accept”'ed content type is used
• Default set of HttpMessageConverters are
registered for you 53
Default HttpMessageConverters
• StringHttpMessageConverter
> Reads “text/*” into Strings (for request)
> Writes Strings as “text/plain” (for response)
• FormHttpMessageConverter
> Reads “application/x-www-form-urlencoded” into
MultiValueMap<String, String> (for request)
> Writes MultiValueMap<String, String> into
“application/x-www-form-urlencoded” (for response)
• ByteArrayMessageConverter
> Reads “*/*” into a byte[]
> writes Objects as “application/octet-stream”

54
Controllers:
Handler Method
Return Types

55
ModelAndView Object
public class DisplayShoppingCartController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) {
List cartItems = // get a List of CartItem objects
User user = // get the User doing the shopping
ModelAndView mav =
new ModelAndView("displayShoppingCart"); //logical view name
mav.addObject(cartItems); // look ma, no name, just the object
mav.addObject(user); // and again ma!
return mav;
}

56
String (Logical View Name - Most Popular)
• Is interpreted as the logical view name, with the
model implicitly determined through command
objects and @ModelAttribute annotated
reference data accessor methods
// Logical view is returned as “view/html”
@RequestMapping(value="html", method=RequestMethod.GET)
public String prepare(Model model) {
model.addAttribute("foo", "bar");
model.addAttribute("fruit", "apple");
return "views/html";
}

57
void
• Used in two situations
> #1: when the method handles the response itself (by
writing the response content directly, declaring an
argument of type ServletResponse /
HttpServletResponse for that purpose)
> #2: When the view name is supposed to be implicitly
determined through a
RequestToViewNameTranslator
// #2: The view name is implicitly set to “viewNameX”
@RequestMapping(value="/viewNameX", method=RequestMethod.GET)
public void usingRequestToViewNameTranslator(Model model) {
model.addAttribute("foo", "bar");
model.addAttribute("fruit", "apple");
}

58
@ResponseBody annotated Method
• If the method is annotated with
@ResponseBody, the return type is written to
the response HTTP body

@RequestMapping(value="/response/annotation",
method=RequestMethod.GET)
public @ResponseBody String responseBody() {
return "The String ResponseBody";
}

59
A HttpEntity<?> or ResponseEntity<?>
• Provide access to the Servlet reponse HTTP
headers and contents.
• The entity body will be converted to the
response stream using HttpMessageConverter
@RequestMapping(value="/response/entity/headers",
method=RequestMethod.GET)
public ResponseEntity<String> responseEntityCustomHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);
return new ResponseEntity<String>("The String ResponseBody with
custom header Content-Type=text/plain",
headers, HttpStatus.OK);
}

60
Controllers:
@SessionAttributes

61
@SessionAttributes
• Declares session attributes used by a specific
handler.
• This will typically list the names of model
attributes or types of model attributes which
should be transparently stored in the session or
some conversational storage, serving as form-
backing beans between subsequent requests.

62
@SessionAttributes
@Controller
@RequestMapping("/editPet.do")
@SessionAttributes("pet")
public class EditPetForm {
// ...
}

63
Handler Mapping
Customization

64
DefaultAnnotationHandlerMapping
• In pre-2.5 versions of Spring, users were
required to define HandlerMappings in the web
application context to map incoming web
requests to appropriate handlers.
• From Spring 2.5, the DispatcherServlet enables
the DefaultAnnotationHandlerMapping as a
default
> DefaultAnnotationHandlerMapping searches for
@RequestMapping annotations on @Controllers
> Typically, you do not need to override this default
mapping, unless you need to override the default
property values for customization

65
Handler Mapping Properties
• interceptors
• defaultHandler
> Default handler to use, when this handler mapping
does not result in a matching handler.
• order

66
Handler Mappings:
Interceptor

67
Add an “interceptor” to default mapping
// This example shows how to override the default mapping and add an
// interceptor:
<beans>
<bean id="handlerMapping"
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandle
rMapping">
<property name="interceptors">
<bean class="example.MyInterceptor"/>
</property>
</bean>
<beans>

68
What Do Interceptors Do?
• Interceptors are useful when you want to apply
specific functionality to certain requests
> Authentication, authorization, logging, etc
• Interceptors must implement
HandlerInterceptor interface
> boolean preHandler(..) method - When this method
returns true, the handler execution chain will
continue; when it returns false, the DispatcherServlet
assumes the interceptor itself has taken care of
requests (and, for example, rendered an appropriate
view) and does not continue executing the other
interceptors and the actual handler in the execution
chain
> void postHandler(..) method
69
Interceptor Example #1 - Java Code
public class LoggingInterceptor extends HandlerInterceptorAdapter {
private static final Logger logger =
LoggerFactory.getLogger(LoggingInterceptor.class);
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
logger.info("LoggingInterceptor: preHandle() entered");
return true;
}
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
logger.info("LoggingInterceptor: postHandle() exiting");
}
}

70
Interceptor Example #1 - Configuration
<!-- Interceptors -->
<bean id="elapsedTimeInterceptor"
class="com.javapassion.examples.ElapsedTimeInterceptor" />
<bean id="loggingInterceptor"
class="com.javapassion.examples.LoggingInterceptor" />
<!-- Annotation handlers (Applied by default to ALL @controllers -->
<bean
class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandle
rMapping">
<property name="order" value="1" />
<!-- Interceptors are applied to all annotated controllers -->
<property name="interceptors">
<list>
<ref bean="elapsedTimeInterceptor" />
<ref bean="loggingInterceptor" />
</list>
</property>
</bean>

71
Interceptor Example #2
package samples;
public class TimeBasedAccessInterceptor extends HandlerInterceptorAdapter {
...
public boolean preHandle(
HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
Calendar cal = Calendar.getInstance();
int hour = cal.get(HOUR_OF_DAY);
if (openingTime <= hour < closingTime) {
return true;
} else {
response.sendRedirect("http://host.com/outsideOfficeHours.html");
return false;
}
}
}
72
Interceptor Example #2 - Configuration
<beans>
<bean id="handlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="officeHoursInterceptor"/>
</list>
</property>
<property name="mappings">
<value>
/*.form=editAccountFormController
/*.view=editAccountFormController
</value>
</property>
</bean>
<bean id="officeHoursInterceptor"
class="samples.TimeBasedAccessInterceptor">
<property name="openingTime" value="9"/>
<property name="closingTime" value="18"/>
</bean>
<beans> 73
Views vs.
@ResponseBody

74
Two Schemes of Rendering Response
• Two schemes for rendering response
> ViewResolver + View
> HttpMessageConverter
• They are triggered in different ways
> Render a view by returning a logical view String
> Write a message by returning a @ResponseBody or
ResponseEntity
• Which one to use?
> Use ViewResolver + View to generate documents for
display in a web browser - HTML, PDF, etc
> Use @ResponseBody to exchange data with web
service clients - JSON, XML, etc
75
Resolving Views

76
Resolving Views
• All handler methods in the Spring Web MVC
controllers must resolve to a logical view name
> Explicitly (e.g., by returning a String, View, or
ModelAndView) or
> Implicitly (i.e., based on conventions)
• Views in Spring are addressed by a logical view
name and are resolved by a view resolver
• Spring comes with quite a few view resolvers

77
Resolving Views:
Spring-Provided
ViewResolvers

78
View Resolvers
• UrlBasedViewResolver
• InternalResourceViewResolver
> It is a subclass of UrlBasedViewResolver
• ResourceBundleViewResolver
• AbstractCachingViewResolver
• XmlViewResolver
• ContentNegotiatingViewResolver

79
UrlBasedViewResolver
// A simple implementation of the ViewResolver interface that effects the direct
// resolution of symbolic view names to URLs, without an explicit mapping
// definition. This is appropriate if your symbolic names match the names of
// your view resources in a straightforward manner, without the need for
// arbitrary mappings.
// When returning test as a logical view name, this view resolver forwards
// the request to the RequestDispatcher that will send the request to
// /WEB-INF/jsp/test.jsp.

<bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>

80
InternalResourceViewResolver
// A convenience subclass of UrlBasedViewResolver that supports
// InternalResourceView (i.e. Servlets and JSPs), and subclasses such
// as JstlView and TilesView.
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>

81
ResourceBundleViewResolver
// The ResourceBundleViewResolver inspects the ResourceBundle identified
// by the basename, and for each view it is supposed to resolve, it uses the value
// of the property [viewname].(class) as the view class and the value of the
// property [viewname].url as the view url.
<bean id="viewResolver"
class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basename" value="views"/>
<property name="defaultParentView" value="parentView"/>
</bean>

resource bundle
# views.properties file in the classpath
welcomeRedirect.(class)=org.springframework.web.servlet.view.RedirectView
welcomeRedirect.url=welcome.jsp
reservationSuccessRedirect.
(class)=org.springframework.web.servlet.view.RedirectView
reservationSuccessRedirect.url=reservationSuccess.jsp
reservationSummary.(class)=com.javapassion.examples.views.ExcelReservation
82
Resolving Views:
Chaining
ViewResolvers

83
Chaining ViewResolver's
• You chain view resolvers by adding more than
one resolver to your application context and, if
necessary, by setting the order property to
specify ordering.
> The higher the order property, the later the view
resolver is positioned in the chain
> InternalResourceViewResolver is automatically
positioned as the last ViewResolver
• If a specific view resolver does not result in a
view, Spring continues to inspect them until a
view is resolved

84
Chaining ViewResolver's
// In the following example, the chain of view resolvers consists of two resolvers,
// an InternalResourceViewResolver, which is always automatically positioned as
// the last resolver in the chain, and an XmlViewResolver for specifying Excel
// views. Excel views are not supported by the InternalResourceViewResolver.
<bean id="excelViewResolver"
class="org.springframework.web.servlet.view.XmlViewResolver">
<property name="order" value="1"/>
<property name="location" value="/WEB-INF/views.xml"/>
</bean>
<bean id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>

85
Type Conversion

86
Type Conversion
• Type conversion happens automatically
• A common “ConversionService” used in the
places where type conversion is required
> @RequestParam, JavaBean, @PathVariable
> @RequestHeader, @CookieValue
• HttpMessageConverter used for
> @RequestBody, @ResponseBody, HttpEntity,
ResponseEntity
• All major conversion occur out of the box
> Primitive, String, Date, Collection, Map
• Can declare annotation-based conversion rules
> @NumberFormat, @DateTimeFormat
87
Convention over
Configuration
Support:
Automatic Key
name Generation in
ModelMap
ModeAndView

88
ModelMap & ModelAndView Classes
• The ModelMap class is essentially a glorified
Map that can make adding objects that are to
be displayed in (or on) a View adhere to a
common naming convention
• The ModelAndView class uses a ModelMap class
that is a custom Map implementation that
automatically generates a key for an object
when an object is added to it.

89
Automatic Key Generation for
ModelAndView
public class DisplayShoppingCartController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) {
List cartItems = // get a List of CartItem objects
User user = // get the User doing the shopping
// “displayShoppingCart” is logical view
ModelAndView mav = new ModelAndView("displayShoppingCart");
mav.addObject(cartItems); // “cartList” is automatically generated as a key
mav.addObject(user); //”user” is automatically generated as a key
return mav;
}
}

90
Key Name Generation Strategy
• Scalar object - use the short class name of the
object's class
> x.y.User instance added will have the name user
> x.y.Registration instance added will have the name
registration
• Collection object
> An x.y.User[] array with one or more x.y.User
elements added will have the name userList
> An x.y.Foo[] array with one or more x.y.User
elements added will have the name fooList
> A java.util.ArrayList with one or more x.y.User
elements added will have the name userList

91
Convention over
Configuration
Support:
Logical View Name
Generation

92
Handler Without Setting Logical View
// A request URL of http://localhost/registration.html results in a logical view
// name of registration being generated by the
// DefaultRequestToViewNameTranslator. This logical view name is then
// resolved into the /WEB-INF/jsp/registration.jsp view by the
// InternalResourceViewResolver bean.
public class RegistrationController implements Controller {
public ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response) {
// process the request...
ModelAndView mav = new ModelAndView();
// add data as necessary to the model...
return mav;
// notice that no View or logical view name has been set
}
}

93
Configuration for Logical View Name
Generation (This is done for you)
<beans>
<!-- This bean with the well known name generates view names for us. This gets
automatically configured by Spring. It is configured here for demo purpose. -->
<bean id="viewNameTranslator"
class="org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator"/>
<bean class="x.y.RegistrationController">
<!-- inject dependencies as necessary -->
</bean>
<!-- maps request URLs to Controller names -->
<bean
class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/
>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/"/>
<property name="suffix" value=".jsp"/>
</bean>
</beans>
94
Spring 3 <mvc: ..>
Configuration

95
Spring 3 Enhancement
• Spring 3 introduces a mvc XML configuration
namespace that simplifies the setup of Spring
MVC inside your web application.
> Instead of registering low-level beans such as
AnnotationMethodHandlerAdapter, you can simply
use the namespace and its higher-level constructs.
> This is generally preferred unless you require finer-
grained control of the configuration at the bean
level.

96
Tags in <mvc: ..> Namespace
• <mvc:annotation-driven .. >
• <mvc:interceptors .. >
• <mvc:view-controller .. >
• <mvc:resources ..>
• <mvc:default-servlet-handler ..>

97
<mvc:annotation-driven />
• This tag registers the
DefaultAnnotationHandlerMapping and
AnnotationMethodHandlerAdapter beans that
are required for Spring MVC to dispatch
requests to @Controllers.
• The tag configures those two beans with
sensible defaults based on what is present in
your classpath.

98
<mvc:annotation-driven /> Defaults
• Support for Spring 3's Type ConversionService
in addition to JavaBeans PropertyEditors during
Data Binding.
• Support for formatting Number fields using the
@NumberFormat annotation
• Support for formatting Date, Calendar, Long,
and Joda Time fields using the
@DateTimeFormat annotation, if Joda Time 1.3
or higher is present on the classpath.

99
<mvc-annotation-driven> Defaults
• Support for validating @Controller inputs with
@Valid, if a JSR-303 Provider is present on the
classpath. The validation system can be
explicitly configured by setting the validator
attribute.
• Support for reading and writing XML
• Support for reading and writing JSON

100
<mvc:annotation-driven/> Example
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<!-- JSR-303 support will be detected on classpath and enabled automatically-->
<mvc:annotation-driven/>
</beans>

101
<mvc:view-controller>
• This tag is a shorcut for defining a
ParameterizableViewController that
immediately maps incoming request to a view
• Use it in static cases when there is no Java
Controller logic to execute before the view
generates the response
• Example
<!-- The url “/” immediately maps to “welcome” view -->
<mvc:view-controller path="/" view-name="welcome"/>
<!-- The url “/index.html” immediately maps to “index” view -->
<mvc:view-controller path="/index.html" view-name="index"/>

102
<mvc:resources> from 3.0.4
• Provides a convenient way to serve static
resources from locations other than the web
application root, including locations on the
classpath
• The cache-period property may be used to set
far future expiration headers
• Example
<!-- Serve resource requests with a URL pattern of
/resources/** from a public-resources directory -->
<mvc:resources mapping="/resources/**"
location="/public-resources/" cache-period="31556926"/>

103
<mvc:default-servlet-handler> from 3.0.4
• Allows for mapping the DispatcherServlet to "/"
(thus overriding the mapping of the container's
default Servlet), while still allowing static
resource requests to be handled by the
container's default Servlet.
• It configures a
DefaultServletHttpRequestHandler with a URL
mapping (given a lowest precedence order) of
"/**".
• This handler will forward all requests to the
default Servlet.
• Example
<mvc:default-servlet-handler/>
104
Example
<mvc:default-servlet-handler/>
<mvc:resources mapping="/js/**" location="/js/" cache-period="31556926"/>
<mvc:resources mapping="/style/**" location="/style/" cache-period="31556926"/>
<mvc:resources mapping="/image/**" location="/image/" cache-period="31556926"/>

105
Logging

106
log4j.xml
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%-5p: %c - %m%n" />
</layout>
</appender>
<!-- 3rdparty Loggers -->
<logger name="org.springframework.core">
<level value="info" />
</logger>
<logger name="org.springframework.beans">
<level value="info" />
</logger>
<logger name="org.springframework.context">
<level value="info" />
</logger>
<logger name="org.springframework.web">
<level value="debug" />
</logger>
<!-- Root Logger -->
<root>
<priority value="warn" />
<appender-ref ref="console" />
</root>
107
</log4j:configuration>
log4j.properties
# For JBoss: Avoid to setup Log4J outside $JBOSS_HOME/server/default/deploy/log4j.xml!
# For all other servers: Comment out the Log4J listener in web.xml to activate Log4J.
#log4j.rootLogger=INFO, stdout, logfile
log4j.rootLogger=ERROR, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - <%m>%n
#log4j.appender.logfile=org.apache.log4j.RollingFileAppender
#log4j.appender.logfile.File=${mvc_basics_form.root}/WEB-INF/mvc_basics_form.log
#log4j.appender.logfile.MaxFileSize=512KB
# Keep three backup files.
#log4j.appender.logfile.MaxBackupIndex=3
# Pattern to output: date priority [category] - message
#log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
#log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.logger.org.springframework.web=DEBUG

108
Thank you!

Check JavaPassion.com Codecamps!


http://www.javapassion.com/codecamps
“Learn with Passion!”

109
109

Das könnte Ihnen auch gefallen