繁体   English   中英

Spring REST API中自定义接受/标题和返回类型的406 HTTP状态

[英]406 HTTP Status for custom accept/header and return type in Spring REST API

我有一个Spring REST API,它必须响应自定义的'accept:project / xml'标头。 此外,我从REST方法返回了自己的Response对象,然后应将其转换为XML(以便将所有响应包装在标记内)。 因此,控制器看起来像:

@Controller("Project Controller")
@RequestMapping(value = "/wa", produces = "project/xml; charset=utf-8")
@ResponseBody
public class ProjectController {

    private final IProjectService projectService;

    @Autowired
    public ProjectController(IProjectService projectService) {
        this.projectService = projectService;
    }

    @RequestMapping(method = RequestMethod.GET)
    public Response projectInfo() {
        return new Response(projectService.listProjects());
    }

    @RequestMapping(value = "/start", method = RequestMethod.GET)
    public Response start() {
        return new Response(new JAXBElement<>(new QName("resource"), 
String.class, StaticConstants.STRING_START_TAG));
    }

    @RequestMapping(value = "/end", method = RequestMethod.GET)
    public ResponseEntity<String> end() {
        return ResponseEntity.ok(StaticConstants.STRING_END_TAG);
    }
}

这是Response类的样子:

@XmlRootElement(name = "response")
@XmlAccessorType(XmlAccessType.FIELD)
@Data
@NoArgsConstructor
public class Response {

   @XmlAnyElement(lax=true)
   private List<Object> body;

   public Response(Object single) {
      if (body == null) {
          body = new ArrayList<>(1);
      }
      body.add(single);
   }
}

包裹在Response中的所有Bean类在所有地方都带有@XmlRootElement和@XmlElement注释。

我还包括了所有fastxml依赖项(即使不是必需的):

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>${com.fasterxml.jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>${com.fasterxml.jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
        <version>${com.fasterxml.jackson.version}</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>${com.fasterxml.jackson.version}</version>
    </dependency>

另外,我还向Spring配置中添加了必要的bean,如下所示:

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.project")
public class BeanConfiguration {

    ...

    @Bean
    public HttpMessageConverter jsonMessageConverter() {
        return new MappingJackson2HttpMessageConverter();
    }
}

问题是我收到/ start端点的406不可接受状态,但没有收到/ end端点的状态。 我从Postman发送的请求当然包含“ Accept:project / xml”标头。

因此,如果我从Postman请求中删除Controller中的“ produces”和“ Accept”标头,则一切正常。 如果我将'produces'更改为'application / xml'并且将请求标头更改为'application / xml'或不包含任何标头,则它也可以工作。

但是使用自定义标头仅适用于ResponseEntity类,不适用于我自己的Response类。

我也尝试过使Response类扩展ResponseEntity,但没有效果。

我已经浏览了许多解决方案和类似问题-没有任何帮助。 而且没有其他人使用自己的自定义“ Accept”标头。

我最终设法以另一种方式解决了此问题。 首先,添加了自己的消息转换器,该消息转换器扩展了Jaxb2RootElementHttpMessageConverter并调用setSupportedMediaTypes方法:

public class ProjectXmlMessageConverter extends Jaxb2RootElementHttpMessageConverter {

    public ProjectXmlMessageConverter() {
        super();
        setSupportedMediaTypes(Collections.singletonList(MediaType.valueOf("project/xml")));
}

}

其次,以这种方式将我的转换器添加到已定义的转换器列表中:

@EnableWebMvc
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

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

现在它可以工作了,并且我的API使用“ Accept:project / xml”标头响应请求。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM