background
- One change in Spring Boot from 2.2.4 is when json is returned
content-type
byapplication/json; charset=UTF-8
Into theapplication/json;
- This can cause garbled characters in applications whose default encoding is not UTF-8
why
- So why? Returning to
Jackson2CodecSupport
的DEFAULT_MIME_TYPES
In addition to theCharset
Option, so there is no outputCharset
了
- So how does Spring determine that
Content-Type
? Can you add it halfway through? - Analyzing the call link, it can be found that the
EncoderHttpMessageWriter
Did the updateContentType
- So how to update?
- MessageHeader = MessageHeader = MessageHeader = MessageHeader = MessageHeader
AbstractMessageWriterResultHandler
Select the best MediaType - So what’s the default?
- Which is the first MimeType of Encoder, which is Encode by default for Json
Jackson2JsonEncoder
soJackson2CodecSupport
The removed charset will affect the actual request output
solution
- Add a custom Encoder to the default MIME Type of the custom Encoder. Add charset to the default MIME Type of the custom Encoder.
- However, this method costs too much, custom Encoder also need to improve the test, more trouble
- So the second one, in the Response Header, plus
Content-Type
Become the preferred, this is also relatively easy, add a WebFilter can be
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import reactor.core.publisher.Mono;
/ * * *@author Lambda.J
*/
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class ContentTypeFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
exchange.getResponse().getHeaders().setContentType(MediaType.APPLICATION_JSON_UTF8);
returnchain.filter(exchange); }}Copy the code
- After adding, the normal output has a Charset, but the test run found abnormal link is still a problem, there is no Charset, this is why?
- Tracking source, found that turned out to be RequestMappingHandlerAdapter exception handling will remove all Content related to the head, and now through the filter chain, want to rewrite, autotype HandlerResultHandler only
- Copying HandlerResultHandler is cumbersome and expensive to do for every output
- So I didn’t think of a good way to use a Hack method, by reflection rewrite
Jackson2CodecSupport
的DEFAULT_MIME_TYPES
// Add to the SpringBootApplication startup class
static {
// Utf8 backpocket scheme, webfilter before the resultHandler, error will delete the content-type, so abnormal link needs this backpocket
addCharsetToJsonContentType();
}
public static void addCharsetToJsonContentType(a) {
Field defaultMimeTypeField = null;
try {
defaultMimeTypeField = Jackson2CodecSupport.class.getDeclaredField("DEFAULT_MIME_TYPES");
defaultMimeTypeField.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(defaultMimeTypeField, defaultMimeTypeField.getModifiers() & ~Modifier.FINAL);
defaultMimeTypeField.set(null,
Collections.unmodifiableList(Arrays.asList(new MimeType("application"."json", Charsets.UTF_8),
new MimeType("application"."*+json", Charsets.UTF_8))));
defaultMimeTypeField.setAccessible(false);
modifiersField.setInt(defaultMimeTypeField, defaultMimeTypeField.getModifiers() | Modifier.FINAL);
System.out.println("Already Add Charset To Jackson");
}
catch(NoSuchFieldException | IllegalAccessException e) { e.printStackTrace(); }}Copy the code
Association knowledge – Request processing links under WebFlux
- According to the Spring document, the most core under WebFLux is
HttpHandler
andWebHandler
The network framework (Netty, Tomcat, or whatever) sends the request to an HttpHandler which calls the final WebHandler
- So how is HttpHandelr built?
- It can be seen that it first takes the final webHandler and filter chain to construct a Decorated, then wraps exceptionHandlers, and finally becomes an HttpWebHandlerAdapter directly connected to the network framework
- When the network framework responds to a channel state change, the HttpWebHandlerAdapter handler method is called, which is then called in the responsibility chain
- As shown in the figure above, when walking to
RequestMappingHandlerAdapter
thehandleException
“, we have already gone through the filter chain, so our ContentTypeFilter is invalidated
The resources
- Webflux document