SpringBoot 解决 ajax application/octet-stream not supported

版本

SpringBoot 2.1.3.RELEASE

思路

  • 搜索引擎查询之后,没有找到和我类似情况的解决方案,但是发现 Request 的解析应该和 HttpMessageConverters 有关
  • 定位到了 SpringBoot 关于 HttpMessageConverters 的自动配置类 HttpMessageConvertersAutoConfiguration
SpringBoot 解决 ajax application/octet-stream not supported
  • 由于 SpringBoot 默认是 Jackson 做解析,我们直奔 JacksonHttpMessageConvertersConfiguration
SpringBoot 解决 ajax application/octet-stream not supported
  • 我们看一下这个构造方法里面是什么
SpringBoot 解决 ajax application/octet-stream not supported
  • 可以看到解析协议中并没有支持 application/octet-stream

解决

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
 
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(new CustomHttpMessageConverter());
    }
 
    private class CustomHttpMessageConverter extends AbstractJackson2HttpMessageConverter {
        @Nullable
        private String jsonPrefix;
 
 
        public CustomHttpMessageConverter() {
            this(Jackson2ObjectMapperBuilder.json().build());
        }
 
        public CustomHttpMessageConverter(ObjectMapper objectMapper) {
            super(objectMapper,
                    MediaType.APPLICATION_JSON,
                    new MediaType("application", "*+json"),
                    MediaType.APPLICATION_OCTET_STREAM);
        }
 
 
        /**
         * Specify a custom prefix to use for this view's JSON output.
         * Default is none.
         *
         * @see #setPrefixJson
         */
        public void setJsonPrefix(String jsonPrefix) {
            this.jsonPrefix = jsonPrefix;
        }
 
        /**
         * Indicate whether the JSON output by this view should be prefixed with ")]}', ". Default is false.
         * <p>Prefixing the JSON string in this manner is used to help prevent JSON Hijacking.
         * The prefix renders the string syntactically invalid as a script so that it cannot be hijacked.
         * This prefix should be stripped before parsing the string as JSON.
         *
         * @see #setJsonPrefix
         */
        public void setPrefixJson(boolean prefixJson) {
            this.jsonPrefix = (prefixJson ? ")]}', " : null);
        }
 
 
        @Override
        protected void writePrefix(JsonGenerator generator, Object object) throws IOException {
            if (this.jsonPrefix != null) {
                generator.writeRaw(this.jsonPrefix);
            }
        }
 
    }
 
}

@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new CustomHttpMessageConverter());
}

private class CustomHttpMessageConverter extends AbstractJackson2HttpMessageConverter {
@Nullable
private String jsonPrefix;

public CustomHttpMessageConverter() {
this(Jackson2ObjectMapperBuilder.json().build());
}

public CustomHttpMessageConverter(ObjectMapper objectMapper) {
super(objectMapper,
MediaType.APPLICATION_JSON,
new MediaType("application", "*+json"),
MediaType.APPLICATION_OCTET_STREAM);
}

/**
* Specify a custom prefix to use for this view's JSON output.
* Default is none.
*
* @see #setPrefixJson
*/
public void setJsonPrefix(String jsonPrefix) {
this.jsonPrefix = jsonPrefix;
}

/**
* Indicate whether the JSON output by this view should be prefixed with ")]}', ". Default is false.
* <p>Prefixing the JSON string in this manner is used to help prevent JSON Hijacking.
* The prefix renders the string syntactically invalid as a script so that it cannot be hijacked.
* This prefix should be stripped before parsing the string as JSON.
*
* @see #setJsonPrefix
*/
public void setPrefixJson(boolean prefixJson) {
this.jsonPrefix = (prefixJson ? ")]}', " : null);
}

@Override
protected void writePrefix(JsonGenerator generator, Object object) throws IOException {
if (this.jsonPrefix != null) {
generator.writeRaw(this.jsonPrefix);
}
}

}

}

CustomHttpMessageConverter 代码和 MappingJackson2HttpMessageConverter 一致,只不过在构造方法中添加了 MediaType.APPLICATION_OCTET_STREAM

备注

  • 修改之后,只可以使用 @RequestBody XXBean data,使用 @RequestBody String data 会报错
  • 由于缺乏这部分源码的相关阅读,完全靠感觉解决的这次问题,这么做很不靠谱,有时间还是应该多学习底层源码。

作者:殷天文
链接:https://www.jianshu.com/p/491ee2df3d02

发表评论

登录后才能评论
关注我们