Download presentation
Presentation is loading. Please wait.
1
Spring MVC Part 2 Spencer Uresk
2
This is a training, NOT a presentation Please ask questions
Notes This is a training, NOT a presentation Please ask questions This is being recorded Prerequisites Beginning Spring MVC (and all of its prerequisites)
3
Overview Last time, we showed how to map requests to handler methods, get information about the request, and how to pass information back to the view We’ll see what an HTTP message looks like This week, we’ll look at some of Spring MVC’s RESTful features, including RequestBody, ResponseBody, HttpMessageConverters, HttpEntity objects, and dealing with exceptions These are useful for RESTful web services and normal form-based interactions
4
What does an HTTP message look like? Sample Requests:
GET /view/1 HTTP/1.1 User-Agent: Chrome Accept: application/json [CRLF] Request Line Headers POST /save HTTP/1.1 User-Agent: IE Content-Type: application/x-www-form-urlencoded [CRLF] name=x&id=2 Request Line Headers Request Body
5
HTTP Message (Responses)
Sample Responses HTTP/ OK Content-Type: text/html Content-Length: 1337 [CRLF] <html> Some HTML Content. </html> Status Line Headers Response Body HTTP/ Internal Server Error Status Line HTTP/ Created Location: /view/7 [CRLF] Some message goes here. Status Line Headers Response Body
6
RequestBody Annotating a handler method parameter will bind that parameter to the request body @RequestMapping("/echo/string") public void String input) {} @RequestMapping("/echo/json") public void SomeObject input) {}
7
No view is rendered in this case
ResponseBody Annotating a return type tells Spring MVC that the object returned should be treated as the response body No view is rendered in this case @RequestMapping("/echo/string") String readString() {} @RequestMapping("/echo/json") SomeObject readJson() {}
8
HttpMessageConverters
How does Spring MVC know how to turn a JSON string into SomeObject, or vice-versa? HttpMessageConverters These are responsible for converting a request body to a certain type, or a certain type into a response body Spring MVC figures out which converter to use based on Accept and Content-Type headers, and the Java type Your Accept and Content-Type headers DON’T have to match. For example, you can send in JSON and ask for XML back
9
HttpMessageConverters
A number of HttpMessageConverters are already provided You can define your own, but that is outside the scope of this training You don’t specify which ones are used to convert request/response bodies – they are selected based on the Content-Type/Accept headers
10
HttpMessageConverters make heavy use of MIME types (RFC 2046)
These are the value for Accept and Content-Type headers Two-part identifier for content formats First part is the type. ie, application Second part is the sub-type. ie, json application/json Mention how content negotiation works can be used */*; applicaton/*
11
StringHttpMessageConverter
Reads and writes Strings. Reads text/* Writes text/plain
12
StringHttpMessageConverter
@RequestMapping("/echo/string") String String input) { return “Your Text Was: “ + input; } a POST /echo/string HTTP/1.1 Accept: text/plain Content-Type: text/plain Hello! REQUEST HTTP/ OK Content-Type: text/plain Content-Length: 17 Your Text Was: Hello! RESPONSE DEMO Do a demo of this.
13
MappingJacksonHttpMessageConverter
Maps to/from JSON objects using the Jackson library Reads application/json Writes application/json
14
MappingJacksonHttpMessageConverter
public Person { // String name, int age; } @RequestMapping("/echo/json") Person Person person) { // Upper case name, square age return person; a POST /echo/string HTTP/1.1 Accept: application/json Content-Type: application/json { “name” : “Spencer”, “age” : 5 } REQUEST HTTP/ Created Content-Type: application/json { “name” : “SPENCER”, “age” : 25 } RESPONSE
15
Jaxb2RootElementHttpMessageConverter
Maps to/from XML objects Must have your object at least annotated Reads text/xml, application/xml Writes text/xml, application/xml
16
Jaxb2RootElementHttpMessageConverter
@XmlRootElement public Person {// String name, int age;} @RequestMapping("/echo/xml") Person Person person) { // Upper case name, square age return person; } a POST /echo/string HTTP/1.1 Accept: application/xml Content-Type: application/xml <thing><name>Spencer</name><age>5</age></thing> REQUEST HTTP/ Created Content-Type: application/xml <thing><name>SPENCER</name><age>25</age></thing> RESPONSE
17
ByteArrayHttpMessageConverter
Can read/write byte arrays (useful for dealing with binary data, such as images) Reads */* Writes application/octet-stream
18
ByteArrayHttpMessageConverter
@RequestMapping("/echo/string") String byte[] input) { return new String(input); } a POST /echo/string HTTP/1.1 Accept: text/plain Content-Type: text/plain Hello! REQUEST HTTP/ OK Content-Type: application/octet-stream Content-Length: 6 Hello! RESPONSE
19
Create a handler that takes a request body and echoes it back.
Lab 1 Create a handler that takes a request body and echoes it back. Create a handler that takes a request body, creates an object with it, and returns it as JSON. Create a handler that takes an XML input and echoes it back as JSON. Test all of these with your HttpClient
20
Other parts of the HTTP Message
What if you need to get/set headers? Or set the status code? @RequestMapping("/echo/string") String String input, HttpServletRequest request, HttpServletResponse response) { String requestType = request.getHeader(“Content-Type”); response.setHeader(“Content-Type”, “text/plain”); response.setStatus(200); return input }
21
@ResponseStatus There is a convenient way to set what the default status for a particular handler should be @ResponseStatus @RequestMapping("/create") @ResponseStatus(HttpStatus.CREATED) // CREATED == 201 public void echoString(String input) { }
22
Convenience class for dealing with bodies, headers, and status
HttpEntity Convenience class for dealing with bodies, headers, and status Converts messages with HttpMessageConverters @RequestMapping("/image/upload") public ResponseEntity<String> upload(HttpEntity<byte[]> rEntity) { String t = rEntity.getHeaders().getFirst(“Content-Type”); byte[] data = rEntity.getBody(); // Save the file HttpHeaders responseHeaders = new HttpHeaders(); responseHeaders.set(“Location”, “/image/1”); return new ResponseEntity<String>(“Created”, responseHeaders, HttpStatus.CREATED); }
23
Convert all your String controller method to use HttpEntity
Lab 2 Convert all your String controller method to use HttpEntity Convert the Create Person controller method to use an HttpEntity. Also, return a Location header and a 201 (Created) response code.
24
Dealing with exceptions
By default, Spring MVC will map certain exceptions to status codes You can implement your own HandlerExceptionResolver, which takes an exception and returns a ModelAndView You can register a SimpleMappingExceptionResolver to map exceptions to views You can annotate methods in the controller to handle specific exceptions
25
Default Exception Mappings
These take effect if you have no other configuration ConversionNotSupportedException => 500 NoSuchMethodHandlingException => 404 MissingServletRequestParameterException => 400 HttpRequestMethodNotSupportedException => 405 TypeMismatchException => 400 HttpMediaTypeNotSupportedException => 415 HttpMediaTypeNotAcceptableException => 406
26
HandlerExceptionResolver
Allows you to control how exceptions are resolved Implement HandlerExceptionResolver (but you’ll probably extend AbstractHandlerExceptionResolver) class AnExceptionHandler extends AbstractHandlerExceptionResolver { protected ModelAndView doResolveException( HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { System.out.println("I got an error."); return new ModelAndView("errors/someError"); }
27
SimpleMappingExceptionResolver
Allows you to simply map exceptions to views This is how the Stack comes configured <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key=".DataAccessException">errors/dataAccessFailure</prop> <prop key=".AccessDeniedException">errors/dataAccessFailure</prop> <prop key=".TypeMismatchException">errors/resourceNotFound</prop> </props> </property> <property name="defaultErrorView" value="errors/generalError"/> <property name="warnLogCategory" value="org.lds.stack"/> </bean>
28
ExceptionHandler methods look a lot like normal handler methods
Create a method to handle the exception, annotate it and pass in the exception(s) that method can handle ExceptionHandler methods look a lot like normal handler methods @RequestMapping("/error") public void doSomething() { throw new RecoverableDataAccessException("Unable to access that database."); } @ExceptionHandler(DataAccessException.class) String handleDataAccessError(DataAccessException ex) { return ex.getMessage();
29
We saw this annotation earlier
@ResponseStatus We saw this annotation earlier It can also be placed on Exception classes methods to return a specific status code for a particular exception @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) @ExceptionHandler(DataAccessException.class) public void handleDataAccessError(DataAccessException ex) {} @ResponseStatus(value = HttpStatus.PAYMENT_REQUIRED, message = “I need money.”) public class PaymentRequiredException {}
30
Implement an @ExceptionHandler method
Lab 3 Look at the SimpleMappingExceptionResolver already configured in your project Create a controller that throws one of those exceptions and verify that your request gets redirected to the corresponding view Remove the config, and change your exception to HttpMediaTypeNotSupportedException. Verify that you get a 415 using your Http Client Implement method
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.