弹簧靴;Jquery 415(不支持的媒体类型)
我试图在安全上下文中对SpringRESTWeb服务api进行ajax跨域post调用。 从Jquery中,我无法设置contentType属性,因为这样我就有了安全上下文的问题。 但是如果没有来自spring的contentType,我将收到以下响应:415(不支持的媒体类型) 弹簧控制器:弹簧靴;Jquery 415(不支持的媒体类型),jquery,ajax,spring-boot,rest,cross-domain,Jquery,Ajax,Spring Boot,Rest,Cross Domain,我试图在安全上下文中对SpringRESTWeb服务api进行ajax跨域post调用。 从Jquery中,我无法设置contentType属性,因为这样我就有了安全上下文的问题。 但是如果没有来自spring的contentType,我将收到以下响应:415(不支持的媒体类型) 弹簧控制器: @RequestMapping(value = "/all", method = RequestMethod.POST) @PreAuthorize("hasAnyAuthority('PROF1
@RequestMapping(value = "/all", method = RequestMethod.POST)
@PreAuthorize("hasAnyAuthority('PROF1','SUDO')")
Jquery:
function getAllUsers(){
var obj = {"limit":10,"page":0};
$.ajax({
url:"https://webServerSite/myService/api/v1/user/all",
dataType: 'json',
xhrFields: {
withCredentials: true
},
crossDomain: true,
data:obj,
type: "post",
success:function(json){
var str = JSON.stringify(json);
console.log(str);
},
error:function(xhr, status, error) {
alert(xhr.responseText);
}
});
}
有一种方法可以禁用Spring上的contentType检查吗?
我的所有数据都是json,我希望将其设置为默认值,以避免内容类型头检查。
我尝试定义自定义消息转换器,但使用以下代码无法工作:
@Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
//set path extension to true
configurer.favorPathExtension(true).
//set favor parameter to false
favorParameter(false).
//ignore the accept headers
ignoreAcceptHeader(true).
//dont use Java Activation Framework since we are manually specifying the mediatypes required below
useJaf(false).
defaultContentType(MediaType.APPLICATION_JSON).
mediaType("xml", MediaType.APPLICATION_XML).
mediaType("json", MediaType.APPLICATION_JSON);
}
谢谢您可以使用
@RequestMapping
注释和consumes
字段指定控制器方法接受的内容类型。对于用例,您可以考虑接受以下内容的所有内容类型:
import org.springframework.http.MediaType;
@RequestMapping(value = "/all", method = RequestMethod.POST, consumes = {MediaType.ALL_VALUE})
更新:
您不应该禁用标头检查,否则,服务器不知道传入的内容类型以及如何正确解析它
考虑到堆栈跟踪,我认为错误来自不同的来源。您尝试解析传入的应用程序/x-www-form-urlencoded;charset=UTF-8
到@RequestBody
,这在Spring中是不可能的
这个问题已经在另一个地方得到了回答:我解决了在spring boot应用程序中添加以下转换器的问题:
import java.io.IOException;
import java.io.PushbackInputStream;
import java.lang.reflect.Type;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonInputMessage;
import org.springframework.lang.Nullable;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
public class CustomMappingJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {
@Nullable
private String jsonPrefix;
public CustomMappingJackson2HttpMessageConverter() {
this(Jackson2ObjectMapperBuilder.json().build());
}
public CustomMappingJackson2HttpMessageConverter(ObjectMapper objectMapper) {
super(objectMapper, MediaType.APPLICATION_FORM_URLENCODED,MediaType.TEXT_PLAIN,MediaType.APPLICATION_JSON, new MediaType("application", "*+json"));
}
public void setJsonPrefix(String jsonPrefix) {
this.jsonPrefix = jsonPrefix;
}
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
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
JavaType javaType = getJavaType(clazz, null);
return readJavaType(javaType, inputMessage);
}
@Override
public Object read(Type type, @Nullable Class<?> contextClass, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
JavaType javaType = getJavaType(type, contextClass);
return readJavaType(javaType, inputMessage);
}
private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) throws IOException {
try {
if (inputMessage instanceof MappingJacksonInputMessage) {
Class<?> deserializationView = ((MappingJacksonInputMessage) inputMessage).getDeserializationView();
if (deserializationView != null) {
return this.objectMapper.readerWithView(deserializationView).forType(javaType).
readValue(inputMessage.getBody());
}
}
PushbackInputStream pIs = new PushbackInputStream (inputMessage.getBody());
return this.objectMapper.readValue(pIs, javaType);
}
catch (InvalidDefinitionException ex) {
throw new HttpMessageConversionException("Type definition error: " + ex.getType(), ex);
}
catch (JsonProcessingException ex) {
throw new HttpMessageNotReadableException("JSON parse error: " + ex.getOriginalMessage(), ex, inputMessage);
}
}
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(customConverters());
}
public HttpMessageConverter customConverters() {
HttpMessageConverter<Object> converter = new CustomMappingJackson2HttpMessageConverter(new ObjectMapper());
return converter;
}
import java.io.IOException;
导入java.io.PushbackInputStream;
导入java.lang.reflect.Type;
导入org.springframework.http.HttpInputMessage;
导入org.springframework.http.MediaType;
导入org.springframework.http.converter.HttpMessageConversionException;
导入org.springframework.http.converter.httpmessagenoteradableexception;
导入org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
导入org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
导入org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
导入org.springframework.http.converter.json.MappingJacksonInputMessage;
导入org.springframework.lang.Nullable;
导入com.fasterxml.jackson.core.JsonGenerator;
导入com.fasterxml.jackson.core.JsonProcessingException;
导入com.fasterxml.jackson.databind.JavaType;
导入com.fasterxml.jackson.databind.ObjectMapper;
导入com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
公共类CustomMappingJackson2HttpMessageConverter扩展了AbstractJackson2HttpMessageConverter{
@可空
私有字符串jsonPrefix;
公共CustomMappingJackson2HttpMessageConverter(){
这是(Jackson2ObjectMapperBuilder.json().build());
}
公共CustomMappingJackson2HttpMessageConverter(ObjectMapper ObjectMapper){
super(objectMapper,MediaType.APPLICATION\u FORM\u URLENCODED,MediaType.TEXT\u PLAIN,MediaType.APPLICATION\u JSON,新MediaType(“APPLICATION”,“*+JSON”);
}
公共void setJsonPrefix(字符串jsonPrefix){
this.jsonPrefix=jsonPrefix;
}
public void setPrefixJson(布尔前缀JSON){
this.jsonPrefix=(prefixJson?)]}',“:null);
}
@凌驾
受保护的void writePrefix(JsonGenerator生成器,对象对象)引发IOException{
if(this.jsonPrefix!=null){
generator.writeRaw(this.jsonPrefix);
}
}
@凌驾
受保护对象readInternal(类clazz,HttpInputMessage inputMessage)
抛出IOException、HttpMessageNodeReadableException{
JavaType JavaType=getJavaType(clazz,null);
返回readJavaType(javaType,inputMessage);
}
@凌驾
公共对象读取(类型类型,@Nullable Class contextClass,HttpInputMessage inputMessage)
抛出IOException、HttpMessageNodeReadableException{
JavaType JavaType=getJavaType(类型,contextClass);
返回readJavaType(javaType,inputMessage);
}
私有对象readJavaType(JavaType JavaType,HttpInputMessage inputMessage)引发IOException{
试一试{
if(映射JacksonInputMessage的inputMessage实例){
类反序列化视图=((MappingJacksonInputMessage)inputMessage).getDeserializationView();
if(反序列化视图!=null){
返回此.objectMapper.readerWithView(反序列化视图).forType(javaType)。
readValue(inputMessage.getBody());
}
}
PushbackInputStream pIs=新的PushbackInputStream(inputMessage.getBody());
返回this.objectMapper.readValue(pIs,javaType);
}
捕获(InvalidDefinitionException ex){
抛出新的HttpMessageConversionException(“类型定义错误:+ex.getType(),ex”);
}
捕获(JsonProcessingException ex){
抛出新的HttpMessageNodeReadableException(“JSON解析错误:+ex.getOriginalMessage(),ex,inputMessage”);
}
}
}
在我的申请中:
import java.io.IOException;
import java.io.PushbackInputStream;
import java.lang.reflect.Type;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonInputMessage;
import org.springframework.lang.Nullable;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
public class CustomMappingJackson2HttpMessageConverter extends AbstractJackson2HttpMessageConverter {
@Nullable
private String jsonPrefix;
public CustomMappingJackson2HttpMessageConverter() {
this(Jackson2ObjectMapperBuilder.json().build());
}
public CustomMappingJackson2HttpMessageConverter(ObjectMapper objectMapper) {
super(objectMapper, MediaType.APPLICATION_FORM_URLENCODED,MediaType.TEXT_PLAIN,MediaType.APPLICATION_JSON, new MediaType("application", "*+json"));
}
public void setJsonPrefix(String jsonPrefix) {
this.jsonPrefix = jsonPrefix;
}
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
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
JavaType javaType = getJavaType(clazz, null);
return readJavaType(javaType, inputMessage);
}
@Override
public Object read(Type type, @Nullable Class<?> contextClass, HttpInputMessage inputMessage)
throws IOException, HttpMessageNotReadableException {
JavaType javaType = getJavaType(type, contextClass);
return readJavaType(javaType, inputMessage);
}
private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) throws IOException {
try {
if (inputMessage instanceof MappingJacksonInputMessage) {
Class<?> deserializationView = ((MappingJacksonInputMessage) inputMessage).getDeserializationView();
if (deserializationView != null) {
return this.objectMapper.readerWithView(deserializationView).forType(javaType).
readValue(inputMessage.getBody());
}
}
PushbackInputStream pIs = new PushbackInputStream (inputMessage.getBody());
return this.objectMapper.readValue(pIs, javaType);
}
catch (InvalidDefinitionException ex) {
throw new HttpMessageConversionException("Type definition error: " + ex.getType(), ex);
}
catch (JsonProcessingException ex) {
throw new HttpMessageNotReadableException("JSON parse error: " + ex.getOriginalMessage(), ex, inputMessage);
}
}
}
@Override
public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(customConverters());
}
public HttpMessageConverter customConverters() {
HttpMessageConverter<Object> converter = new CustomMappingJackson2HttpMessageConverter(new ObjectMapper());
return converter;
}
@覆盖
公共无效扩展消息转换器(ListHi rieckpil,谢谢你的回复。我试着像你说的那样,但我也收到了来自spring的415响应。当你向后端发出HTTP请求并发布所有请求头时,你可以检查浏览器中的网络选项卡吗?Hi rieckpil,这里是头请求:Content Type:application/x-www-form-urlencoded;charset=UTF-8。来自spring日志我可以看到已解析的[org.springframework.web.HttpMediaTypeNotSupportedException:Content type'application/x-www-form-urlencoded;charset=UTF-8'不受支持]。但我想禁用标头检查ad(如果可能),从url参数检查内容类型。但ignoreAcceptHeader(true)不起作用。