Allow to specify AbstractHttpMessageConverter default charset

Before this commit, specifying the charset to use with produces or
consumes @RequestMapping attributes resulted in default charset
loss. That was really annoying for JSON for example, where using
UTF-8 charset is mandatory in a lot of use cases.

This commit adds a defaultCharset property to
AbstractHttpMessageConverter in order to avoid losing the
default charset when specifying the charset with these
@RequestMapping attributes.

It changes slightly the default behavior (that's why we have waited
4.3), but it is much more error prone, and will match with most
user's expectations since the charset loss was accidental in most
use cases (users usually just want to limit the media type supported
by a specific handler method).

Issue: SPR-13631
This commit is contained in:
Sebastien Deleuze
2016-02-23 10:27:39 +01:00
parent 61824b1ade
commit c385427397
15 changed files with 114 additions and 42 deletions

View File

@@ -1356,7 +1356,7 @@ public class ServletAnnotationControllerTests {
request.addHeader("Accept", "application/json, text/javascript, */*");
MockHttpServletResponse response = new MockHttpServletResponse();
servlet.service(request, response);
assertEquals("Invalid response status code", "application/json", response.getHeader("Content-Type"));
assertEquals("Invalid response status code", "application/json;charset=ISO-8859-1", response.getHeader("Content-Type"));
}
@Test
@@ -1770,7 +1770,7 @@ public class ServletAnnotationControllerTests {
servlet.service(request, response);
assertEquals(200, response.getStatus());
assertEquals("application/json", response.getHeader("Content-Type"));
assertEquals("application/json;charset=ISO-8859-1", response.getHeader("Content-Type"));
assertEquals("homeJson", response.getContentAsString());
}

View File

@@ -653,6 +653,22 @@ public class RequestResponseBodyMethodProcessorTests {
assertTrue(content.contains("\"name\":\"bar\""));
}
@Test // SPR-13631
public void defaultCharset() throws Exception {
Method method = JacksonController.class.getMethod("defaultCharset");
HandlerMethod handlerMethod = new HandlerMethod(new JacksonController(), method);
MethodParameter methodReturnType = handlerMethod.getReturnType();
List<HttpMessageConverter<?>> converters = new ArrayList<>();
converters.add(new MappingJackson2HttpMessageConverter());
RequestResponseBodyMethodProcessor processor = new RequestResponseBodyMethodProcessor(converters);
Object returnValue = new JacksonController().defaultCharset();
processor.handleReturnValue(returnValue, methodReturnType, this.container, this.request);
assertEquals("UTF-8", this.servletResponse.getCharacterEncoding());
}
private void assertContentDisposition(RequestResponseBodyMethodProcessor processor,
boolean expectContentDisposition, String requestURI, String comment) throws Exception {
@@ -921,6 +937,13 @@ public class RequestResponseBodyMethodProcessorTests {
bar.setName("bar");
return Arrays.asList(foo, bar);
}
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String defaultCharset() {
return "foo";
}
}
private static class EmptyRequestBodyAdvice implements RequestBodyAdvice {

View File

@@ -1011,7 +1011,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
request.addHeader("Accept", "application/json, text/javascript, */*");
MockHttpServletResponse response = new MockHttpServletResponse();
getServlet().service(request, response);
assertEquals("Invalid content-type", "application/json", response.getHeader("Content-Type"));
assertEquals("Invalid content-type", "application/json;charset=ISO-8859-1", response.getHeader("Content-Type"));
}
@Test
@@ -1531,7 +1531,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
getServlet().service(request, response);
assertEquals(200, response.getStatus());
assertEquals("application/json", response.getHeader("Content-Type"));
assertEquals("application/json;charset=ISO-8859-1", response.getHeader("Content-Type"));
assertEquals("homeJson", response.getContentAsString());
}
@@ -1652,7 +1652,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
getServlet().service(request, response);
assertEquals(200, response.getStatus());
assertEquals("text/html", response.getContentType());
assertEquals("text/html;charset=ISO-8859-1", response.getContentType());
assertEquals("inline;filename=f.txt", response.getHeader("Content-Disposition"));
assertArrayEquals(content, response.getContentAsByteArray());
}
@@ -1678,7 +1678,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
getServlet().service(request, response);
assertEquals(200, response.getStatus());
assertEquals("text/html", response.getContentType());
assertEquals("text/html;charset=ISO-8859-1", response.getContentType());
assertNull(response.getHeader("Content-Disposition"));
assertArrayEquals(content, response.getContentAsByteArray());
}
@@ -1704,7 +1704,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
getServlet().service(request, response);
assertEquals(200, response.getStatus());
assertEquals("text/html", response.getContentType());
assertEquals("text/html;charset=ISO-8859-1", response.getContentType());
assertNull(response.getHeader("Content-Disposition"));
assertArrayEquals(content, response.getContentAsByteArray());
}
@@ -1730,7 +1730,7 @@ public class ServletAnnotationControllerHandlerMethodTests extends AbstractServl
getServlet().service(request, response);
assertEquals(200, response.getStatus());
assertEquals("text/css", response.getContentType());
assertEquals("text/css;charset=ISO-8859-1", response.getContentType());
assertNull(response.getHeader("Content-Disposition"));
assertArrayEquals(content, response.getContentAsByteArray());
}