I am trying to write a controller with Spring MVC 3.2 that consumes/produces both JSON and HTML. I have two handler methods that produce different content types:
@Controller
public class FooController {
@RequestMapping(value="/foo", produces="text/html")
public String fooHTML() {
// ...
}
@RequestMapping(value="/foo", produces="application/json")
public String fooJSON() {
// ...
}
}
This works splendidly if the Accept
header from the client contains either text/html
or application/json
,
...but then there was Internet Explorer. As noted here, IE's Accept
header varies, but it never contains text/html
and always has */*
at the end. When Spring receives a request from IE, it sees no content types directly equal to the ones produced by my controller, but, latching on to the */*
wildcard, it (correctly) decides that both mappings would apply.
Faced with multiple matching handler mappings, Spring (in the RequestMappingHandlerMapping bean) sorts the mappings by what essentially amounts to lexicographic order, picks the first one, and moves on. The problem, from my perspective, is that this process prioritizes application/json
over text/html
. I would much rather return text/html
unless the client specifically requests application/json
— that way, I can serve HTML to dumb clients like IE, and JSON to content-type-savvy clients like users of my API.
Does anyone know of a way to do this that doesn't require extending RequestMappingHandlerMapping to sort the handlers differently? Do you have any simple workarounds?
NOTE: I've tried setting a default content type in the ContentNegotiationManager as described on the Spring blog. It doesn't solve my problem, because that setting only goes into effect when no Accept header is specified.