Weitere ähnliche Inhalte
Ähnlich wie quickguide-einnovator-7-spring-mvc
Ähnlich wie quickguide-einnovator-7-spring-mvc (20)
Mehr von jorgesimao71 (7)
quickguide-einnovator-7-spring-mvc
- 1. Asynchronous Processing
SpringMVC
© EInnovator.org
Spring MVC is a Web and REST-WS framework part of
Spring Framework. It uses a simple request-processing
workflow, it is highly configurable and flexible, and allows
the web components – Controllers – to be written as
simple Java classes (POJOs) with request handler
methods with flexible signatures. Spring MVC is mostly
agnostic about the View Description Language (VDL)
used, and supports out-of-the-box integration with several
view rendering technology. It also provides abstractions
that make it a very convenient REST-WS framework,
building on the features available for web apps.
Spring MVC uses a single HttpServlet – the
DispatcherServlet – that is responsible to dispatch each
HTTP request to an handler method in an web-layer
component (controller) – defined as a Spring managed
bean. An handler method role is to select a view to render
and provide the objects needed to support the rendering
of the dynamic parts of the view – the Model objects. To
support different view technologies a configurable
ViewResolver strategy object is used to map the
symbolic/logical name of the view returned by the handler
method, to an actual view-resource in the file-system.
Figure below depicts the architecture of Spring MVC and
its request-processing life-cycle.
The DispatcherServlet always creates on initialization a
Spring ApplicationContext – the bean container, which
contains the controllers and optionally the configuration
strategies for Spring MVC – such as the ViewResolver. A
separated root ApplicationContext is also created,
commonly, to hold components of lower layers – such as
services, repositories, and infrastructure beans – created
by a ContextLoaderListener (implementing the
ServletContextListener interface). The Spring MVC
created ApplicationContext is made a child of the root
container, which allows the lower-layer beans to be
injected in web-layer controllers. In the web environment
the Spring containers are enhanced with additional
features, such as support for request and session scope
attributes. Figure below depicts the relationship between
containers in a web environment.
In Servlet 3.0+ containers, the DispatcherServlet can be
initialized in Java by defining a class implementing
interface WebInitializer. For convenience, the abstract
class can be extended and the root and MVC
ApplicationContext initialized by specifying the
configuration classes.
» Example: WebApp & MVC Initialization in Java
public class WebAppInitializer extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses()
{ return new Class[] { AppConfig.class }; }
@Override
protected Class<?>[] getServletConfigClasses()
{ return new Class[] { WebConfig.class }; }
@Override
protected String[] getServletMappings()
{ return new String[] { "/mvc/*" }; }
}
Alternatively, the web app can be configured with XML in
the WEB-INF/web.xml file, to define explicitly the
DispatcherServlet and the ContextLoaderListener.
Global and servlet parameter named
contextConfigLocation is used to define, respectively,
the XML spring bean files for the root and MVC
WebApplicationContext.
© EInnovator.org
++QuickGuides»EInnovator.org
7
Software Engineering School
Content
» Spring MVC Architecture
» Web & REST Controllers
» Data Binding & Validation
» Configuration
» File Uploading
» Asynchronous Processing
Jorge Simão, Ph.D.
Spring MVC
Spring MVC Overview
Spring MVC Architecture & Setup
- 2. © EInnovator.org
Spring MVC
Web-layer components – the Controllers – are defined as
Spring managed beans commonly annotated with stereotype
annotation @Component to facilitate @ComponentScan.
Controllers define request handler methods each responsible
to handle a particular family of requests. Annotation
@RequestMapping is used to define the dispatching rules,
such as based on URL pattern and HTTP method. Annotations
@{Get|Post|Put|Delete|Path}Mapping are equivalent to
@RequestMapping entailing a specific HTTP method (since
Spring 4.3).
The main responsibility of an handler method is to select a
view to render and to capture and expose model objects. A
common approach is for handlers to return a String value with
the name of the view to render, and define an out-parameter of
type Model whose Map like API is used to expose model
objects.
Since Spring beans are Java POJOs, the handler methods
can have flexible signatures. Many different types and
conventions are supported for the parameters of the handler
methods. Several annotations are also used to instruct Spring
MVC how/which value should be injected.
Annotation @RequestParameter specifies the name of
request parameter to inject (from the URL query string – part
after ?). Annotation @PathVariable specifies a named URL
segment to inject. When the names match the corresponding
Java parameter names, the names can be omitted in both
annotations (assuming debug or parameter information is
being generated – i.e. no -g option or -p option for compiler).
Type conversion is carried out automatically as needed.
» Example: Controller with Handler for Listing Resource
@Controller
@RequestMapping(value = "/book")
public class BookController {
@Autowired
private BookService service;
@RequestMapping(method = RequestMethod.GET)
public String topSelling(Model model,
@RequestParam(value="n", defaultValue="100") Long n) {
List<Book> books = findTopSellingBooks(n);
model.addAttribute("books", books);
return "book/list";
}
}
» Example: Handler Method to Retrieve Resource
@GetMapping("/book/{id}")
public String show(@PathVariable("id") Long id, Model model) {
Book book = service.findBookById(id);
if (book==null) {
throw new NotFoundException(Book.class, id);
}
model.addAttribute("book", book);
return "book/show";
}
Table below summarizes the class and method level
annotations supported by Spring MVC:
Type/Annotation Description
@Controller Web Component Stereotype
(detected with @ComponentScan)
@RestController REST-WS Component Stereotype
@ControllerAdvice Common Behavior across Controllers
@RequestMapping Defines dispatching/mapping rule
@GetMapping
@PostMapping
@PutMapping
@DeleteMapping
@PatchMapping
Similar to @RequestMapping but implying
a specific HTTP method
@ResponseStatus Set HTTP response status
@ExceptionHandler Handler for throw exception
@ModelAttribute Name for model attribute
@InitBinder Initialize DataBinder
@SessionAttribute Declares names of session attributes
Table below summarizes the types and annotation supported
in Spring MVC for the handler method parameters. Some of
them are described in more detail in following sections.
Type/Annotation Description
Model,Map,ModelMap Container for model objects (out param)
@RequestParam A named request/query parameter
@PathVariable A named URL path segment
@ModelAttribute Name for model attribute
@Valid Validate Form Model Object
Errors, BindingResult Collector of binding/validation errors
@HeaderAttribute Inject value of HTTP request header
@MatrixAttribute Inject parameter – matrix syntax
@DateTimeFormat Parse format for Dates
@NumberFormat Parse format for Numbers
@RequestBody Map parameter from request body
@ResponseBody Map object to response body
HttpEntity<?> Descriptor for request headers&body
@SessionAttribute
@RequestAttribute
Lookup session/request attribute
Locale Locale for request
Software Engineering School
2
Controllers
- 3. © EInnovator.org
Spring MVC
TimeZone/ZoneId+Java8
Timezone for request
Theme Theme for request
Principal Authenticated user for request
@RequestPart Uploaded part of multipart/form-data
WebRequest
WebNativeRequest
Request/response descriptor (Spring)
HttpMethod HTTP method for request
HttpServletRequest
HttpServletResponse
Request & response descriptors (Servlet
API)
HttpSession Session descriptor
SessionStatus Handler for session (attributes)
InputStream/Reader Request (socket) input stream
OutputStrem/Writer (Socket) output stream for response
Spring MVC supports several view rendering technologies –
such as JSP, FreeMarker, Velocity, and ThymeLeaf – and
can be extended to support more. View resources are
represented by objects of type View, which are able to render
its content to the socket output stream. Handlers can return
View objects directly, or values of type ModelAndView
combining two pieces of information. More commonly,
however, they to return a logical view name as a String –
which is mapped to a View object by a ViewResolver strategy.
This allow controllers to be written completely independent of
the view technology in use.
To configure a ViewResolver it should be defined as a Spring
bean in the MVC WebApplicationContext. For JSP pages,
this is the InternalResourceViewResolver which can be
configured with a simple prefix–suffix rule to map logical view
names to file-system locations.
» Example: Java Config – InternalResourceViewResolver
@Configuration
public class WebConfig {
@Bean
public ViewResolver viewResolver() {
return new InternalResourceViewResolver("/WEB-INF/views/",
".jsp");
}
}
Form processing is an integral part of web apps. In Spring
MVC two handler methods are used to implement the form
processing workflow – one handler mapped to HTTP GET
used to retrieve the form page, and another handler to process
the form submission – mapped to an HTTP POST, when
creating a new resource, or HTTP PUT when updating an
existing resource.
Domain or form objects can be used as parameters of handler
methods. This triggers a DataBinder (set up by Spring MVC)
to map request/form parameters to the value of the
corresponding (same name) properties in the domain/form
object. Type conversion errors occurred during data-binding
are captured and added to an object of type BindingResult.
Annotation @Valid is used to validate property values after
binding, often according to JSR-330 Java bean validation
annotations. Validation errors are also captured and added to
the BindingResult. If BindingResult is declared as
parameter of the handler, the handler is still called even when
an error occurred. (BindingResult parameter should
immediately follow the domain/form parameter.)
A common pattern is to redirect the browser after the form
POST/PUT to the page showing the details of the resource just
created/modified. This is done by returning a string with prefix
"redirect:" , rather than a view name.
» Example: Form Retrieval & Submission
@GetMapping("/book")
public String createGET(Book book) {
return "book/create";
}
@PostMapping("/book")
public String createPOST(@Valid Book book, BindingResult
errors) {
if (errors.hasErrors()) {
return "book/create";
}
book = service.addBook(book);
return "redirect:book/show/" + book.getId();
}
» Example: Validation Annotations in Form Object
public class BookForm {
@Length(min=1, max=256)
private String title;
@Length(min=2, max=256)
private String author;
@Pattern(regexp="^(97(8|9))?d{9}(d|X)$")
private String isbn;
@Min(0)
private Integer pageCount;
@Past
private Date publishDate;
}
Spring MVC is also an effective REST-WS framework – and
only a few extra mechanisms are needed beyond what is used
to build web apps. The HttpMessageConverter abstraction is
Software Engineering School
3
Views
Forms – Data Binding & Validation
Rest Controllers
- 4. © EInnovator.org
Spring MVC
used to support automatic decoding&encoding of content sent
in requests/responses, according to the MIME types specified
in the HTTP content-negotiation headers. (Accept on GET
requests, and Content-Type on POST/PUT requests and GET
responses.)
The annotation @RequestBody is used in handler parameters
to decoded the request body and map it to a Java object using
a matching HttpMessageConverter. Similarly, the annotation
@ResponseBody is used in handlers to encode the returned
object to the HTTP response body. Stereotype annotation
@RestController can be used to make the semantics of
@ResponseBody the default for a controller. HTTP status
codes for responses can be convenient set with annotation
@ResponseStatus.
» Example: Rest Controller for Resource Retreival
@RestController
@RequestMapping("/api/book")
public class BookRestController {
@Autowired
private BookService service;
@GetMapping("/")
public Object topSelling(@RequestParam(value="n") Long n) {
return service.findTopSellingBooks(n);
}
@GetMapping("/{id}")
public Object details(@PathVariable("id") Long id) {
Book book = service.findBookById(id);
if (book==null) {
throw new NotFoundException(Book.class, id);
}
return book;
}
}
» Example: Resource Creation REST Endpoint
@PostMapping("/book/")
@ResponseStatus(HttpStatus.CREATED)
public HttpEntity<Void> create(@Valid @RequestBody Book book,
HttpServletRequest request) throws URISyntaxException {
book = service.addBook(book);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(new URI(request.getRequestURI()
+"/"+book.getId()));
return new HttpEntity<Void>(headers);
}
Controllers can declare exception handling methods to deal
with errors that occurred during the execution of request
handler methods (e.g. to set HTTP status codes, encode and
send error descriptors in REST-WS, or render error views in
web apps). The annotation @ExceptionHandler declares a
method as an exception handler. Attribute exception()
specifies the base class of the exception to be handled. The
signature of exception handler methods can be a flexible as a
regular request handler method.
A complementary approach for error handling is to annotate
custom Exception with annotation @ResponseStatus.
Spring MVC will set the specified HTTP status code if that
exception is thrown and no matching exception handler is
found. This approach is not fully general however, as it
requires the definition of custom Exceptions.
It is also possible to configure globally how Spring MVC deals
with exceptions by defining a bean of type
HandlerExceptionResolver, and implementing method
resolveException(). The implementation
SimpleMappingExceptionResolver is used to map specific
Java exception to errors view.
» Example: ExceptionHandler in Controller
@ResponseBody
@ExceptionHandler
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Object handleError(RuntimeException e) {
return new ErrorResponse(e);
}
» Example: Custom Exception w/ HTTP Status Code
@SuppressWarnings("serial")
@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException
{
public NotFoundException(Class<?> type, Long id) {..}
}
Stereotype annotation @ControllerAdvice defines classes
that contain definitions that apply to all (or a sub-set) of
controllers, including: common model attributes – methods
annotated with @ModelAttribute, data-binder initialization –
methods annotated with @InitBinder. and exception handlers
– method annotated with @ExceptionHandler.
» Example: ControllerAdvice for WebApps
@ControllerAdvice
public class WebAdvice {
@Autowired
private UserService userService;
@ModelAttribute
public Object currentUser(Principal principal) {
return userService.findByUsername(principal.getName());
}
@ExceptionHandler
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String handleError(RuntimeException e) {
return "error";
}
@InitBinder
Software Engineering School
4
Controller Advise
Error Handling
- 5. © EInnovator.org
Spring MVC
public void initBinder(WebDataBinder binder) {
binder.addCustomFormatter(new DateFormatter("yyyy-MM-dd"));
}
}
» Example: Controller Advice for REST-WS
@ControllerAdvice(basePackageClasses=BookRestController.class)
public class RestAdvice {
@ResponseBody
@ExceptionHandler
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public Object handleError(RuntimeException e) {
return new ErrorResponse(e);
}
}
Spring MVC can be configured with wide-range of strategies,
such as: ViewResolver, HttpMessageConverter, and many
other. Using annotation @EnableWebMvc in a configuration
class makes several built-in strategies to be automatically
installed, including several HttpMessageConverter for
common MIME types (e.g. XML, JSON, etc.). Same effect can
be achieve with XML configuration with element
<mvc:annotation-config>.
» Example: Enabling Built-in Configuration Strategies
@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
...
}
Applications can customize Spring MVC by defining the
strategy objects as Spring beans. An additional convenient
approach is to make the configuration class annotated with
@EnableWebMvc implement interface WebMvcConfigurer
(or extend abstract class WebMvcConfigurerAdapter ), and
override the callback methods to set up the configuration
strategies.
» Example: Configuring a Global Formatter
@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
...
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new DateFormatter("yyyy-MM-dd"));
}
}
Table below summarizes the strategy beans used by Spring
MVC. Some of them are discussed in following sections.
Bean Type Description
HandlerMapping Selects the handler (method) to
invoke
HandlerAdapter Invokes handler (method)
HandlerExceptionResolver Maps Exceptions to error views
ViewResolver Maps view names to View objects
LocaleResolver &
LocaleContextResolver
Retrieve the Locale for request
ThemeResolver Retrieve the Theme for request
MultipartResolver Managed for File Uploads
FlashMapManager Manager for Flash Scope Map
Spring MVC allows static resource for web apps (e.g. images,
CSS, JavaScript files) to be loaded from locations other than
the default location supported by the Servlet container (i.e. the
root "/" of the app). This is set up by configuring an
ResourceHttpRequestHandler as a bean, or by implementing
WebMvcConfigurerAdapter .addResourceHandlers().
» Example: Defining Static Resource Handlers
@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
...
@Override
public void addResourceHandlers(ResourceHandlerRegistry
registry) {
registry.addResourceHandler("/**")
.addResourceLocations("/", "classpath:/static/");
}
}
Some views don't require model objects to be collected by a
dedicated handler method (e.g. only renders template
markup/text, or use common model objects captured by a
@ControllerAdvice or HandlerInterceptor). In this case, the
mapping between an URL pattern and a view name can be
defined using a ViewController, set up in configuration
method addViewControllers(). XML element <mvc:view-
controller> can also be used for the same purpose.
» Example: Defining Direct View-Controller Mappings
@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
...
@Override
public void addViewControllers(ViewControllerRegistry
Software Engineering School
5
View Controllers
Static ResourcesSpring MVC Configuration
- 6. © EInnovator.org
Spring MVC
registry) {
registry.addViewController("/").setViewName("home");
registry.addViewController("/about").setViewName("about");
registry.addViewController("/login").setViewName("login");
}
}
It is possible to render multiple types of views (e.g. HTML,
XLS, PDF) by defining multiple ViewResolvers. They are used
by Spring MVC in order of priority, and the first one to return a
non-null View object is used. Additionally, a “composite”
ContentNegotiatingViewResolver can be defined to map
view names to View object based on the details of the request
(e.g. file extension, Accept header, or request parameter).
This allows handler methods to return pure logical view names,
and still match and work several view types. The details how
the response MIME type is determined can be configure with a
ContentNegotiationManager, or corresponding configuration
method.
» Example: Configuration of ContentNegotiationManager
@Override
public void
configureContentNegotiation(ContentNegotiationConfigurer
configurer) {
configurer.parameterName("_fmt").mediaType("json",
MediaType.APPLICATION_JSON);
}
Message rendering and (date-time&number) formatting is
locale (language/region) sensitive. The locale for each request
is determined by a bean of type LocaleResolver. By default,
the request header Accept-Language determines the locale
(i.e. the browser settings define the locale). To allow users (or
the app) to change the locale, an alternative LocaleResolver
supporting locale change and persistence should be used –
such as CookieLocaleResolver or SessionLocaleResolver.
The interceptor LocaleChangeInterceptor should also be
configured to change the locale when a defined request
parameter is set. Similar approach can be used to change the
look&fell of a pages by changing the Theme.
» Example: Configuration of Cookie LocaleResolver
@Bean
public LocaleContextResolver localeResolver() {
CookieLocaleResolver resolver = new CookieLocaleResolver();
resolver.setCookieName("LOCALE");
return resolver;
}
» Example: Register Locale&Theme Change Interceptors
@EnableWebMvc
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
...
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LocaleChangeInterceptor());
registry.addInterceptor(new ThemeChangeInterceptor())
.addPathPatterns("/**").excludePathPatterns("/admin/**");
}
}
CORS (Cross-Origin Resource Sharing) is a W3C standard to
“by pass” the same-orign policy of browsers in a secured way
– e.g. as long as requests come from trusted sites. Spring
MVC +4.2 has built in support for CORS. Controller or handler
method specific CORS configuration is set with annotation
@CrossOrigin. Global CORS configuration can be defined in
configuration method addCorsMappings().
» Example: Controller Local CORS Configuration
@CrossOrigin(origins="http://myotherapp.com")
@Controller
public class PortfolioController { ... }
» Example: Global CORS Configuration
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowCredentials(true)
.allowedOrigins("myotherapp.dashboard.com");
}
File uploading in web apps is done through submission of an
HTTP request with MIME type multipart/form-data (e.g. in a
browser by setting attribute entype of an HTML <form>). In
Spring MVC, processing of multi-part requests is done by a
bean type MultipartResolver, that decodes the request body
and makes it available wrapped in object of type MultipartFile.
Two implementation are available out-of-the-box:
CommonsMultipartResolver – based on Apache commons
library for multi-part file uploading, and
StandardServletMultipartResolver – supported natively by
the Servlet +3.0 containers.
Access to the uploaded file content can be done by injecting
the MultipartFile in a parameter of an handler method
annotated with @RequestParam. Alternatively, use annotation
@RequestPart which further invokes an
Software Engineering School
6
Internationalization & Personalization
Content Negotiation
CORS
Multi-Part File Uploading
- 7. Spring MVC
HttpMesageConverter to map the request body.
» Example: Handling File Upload
@PostMapping("/upload")
public String uploadPhoto(@RequestParam("name") String name,
@RequestParam("file") MultipartFile file) throws IOException {
if (!file.isEmpty()) {
saveToFile(storeFolder + name, file.getBytes());
}
return "redirect:photoalbum";
}
» Example: Configuring a MultipartResolver as a Bean
@Bean
public MultipartResolver multipartResolver() {
return new CommonsMultipartResolver();
}
Spring MVC support asynchronous request processing for
Servlet +3.0 containers. In asynchronous request processing
the thread that deliver the request is released quickly, and
another thread is used to complete the request. This is useful
in cases where processing takes long to complete. Two idioms
are supported by Spring MVC. In the simplest, handler
methods return an instance of a Callable – the Java interface
used to model a concurrent task that computes and returns a
value. In this case, Spring MVC schedules a separated
thread, to invoke the Callable and send the response to the
client.
In the second idiom, the handler method returns an instance of
a DeferredResult. In this case, the application is responsible
save the request for processing, and to schedule/manage the
thread that completes the processing (using a TaskExecutor).
The concurrent thread signals the completion of the processing
by calling method DeferredResult.setResult().
» Example: Asynchronous Processing w/ Callable
@GetMapping("/report")
public Callable<ModelAndView> generateReport(
final @RequestParam(required=false) Date since) {
return new Callable<ModelAndView>() {
public ModelAndView call() throws Exception {
List<Order> orders = reportService.findAllSince(since);
return new ModelAndView("report/show", "orders", orders);
}
};
}
• Spring Framework Project home page: http://projects.spring.io/spring-
framework/
• Spring MVC Documentation [in Spring Framework Reference Manual]:
http://docs.spring.io/spring/docs/current/spring-framework-
reference/htmlsingle/#mvc
About the Author
Jorge Simão is a software engineer and IT Trainer, with
two decades long experience on education delivery both in
academia and industry. Expert in a wide range of
computing topics, he his an author, trainer, and director
(Education & Consulting) at EInnovator. He holds a B.Sc.,
M.Sc., and Ph.D. in Computer Science and Engineering.
Spring Web Training
Spring Web is a 4-day trainer lead course that teaches how
to use Spring MVC and the Spring Framework to build
modern web applications. Cover Spring MVC essentials and
advanced topics and techniques. Completion of this training
entitles each student to receive a free voucher to schedule
an exam to become a Pivotal Certified Spring Web
Developer.
Book for a training event in a date&location of your choice:
www.einnovator.org/course/spring-web
++ QuickGuides » EInnovator.org
» Java 8, Spring Dependency-Injection
» RabbitMQ, Redis
» Cloud Foundry, Spring Cloud
» and much more...
++ Courses » EInnovator.org
» Core Spring, Spring Web, Enterprise Spring
» RabbitMQ, Redis, CloudFoundry
» BigData and Hadoop, Spring XD, Spark
» and much more...
EInnovator – Software Engineering School
EInnovator.org offers the best Software Engineering resources and education, in partnership with the most
innovative companies in the IT-world. Focusing on both foundational and cutting-edge technologies and
topics, at EInnovator software engineers and data-scientists can get all the skills needed to become top-of-
the-line on state-of-the-art IT professionals.
Training – Bookings & Inquiries
training@einnovator.org
Consultancy – Partnerships & Inquiries
consulting@einnovator.org
General Info
info@einnovator.org
Software Engineering School
7
Copyright © 2014 EInnovator.org. All rights reserved.
Asynchronous Request Processing
Resources
Contacts