XML 来自 API 的响应带有 PathVariable

XML response from API with PathVariable

我有 API:

@GetMapping(path = "/users/{userId}")
public ResponseEntity<UserDTO> getUserById(@PathVariable(value = "userId") Long userId) {
    //logic here
}

它 returns JSON 响应,这是应该的。

还有另一个我无权访问的应用程序,它调用我的 API 作为例如 GET /users/123.xml 以接收 XML 响应。

但在这种情况下,我的 API 失败并出现 400 错误,因为它无法将 123.xml 解析为 Long

选项 @GetMapping(value = {"/users/{userId}", "/users/{userId}.xml"}) 失败并出现同样的错误。

如何在调用 /{userId}.xml 时用 XML 语法响应,同时在调用 /{userId} 时用 JSON 语法响应?

编辑:

我希望它无需专门添加 'Accept' headers,并且无需编写任何额外的逻辑,它将解析 {userId}.xml,然后设置适当的响应类型。

我马上想到的最简单的解决方案是有一个可选的请求参数 "responseType",默认值为 json,如果有人想要 XML 响应,他们可以像 :GET /users/123?responseType=xml 这样调用 url 由于参数的默认值将为 'json' 并且它将具有 属性 "required= false",因此在需要 json 响应的用例中您无需担心,并且如果有人想要 XML 响应,他们可以添加可选的 RequestParam。另外,我想你需要为控制器指定 json 和 xml return 类型的产品,让 spring-boot 知道它可以产生不同类型的响应,比如-

@RequestMapping(value = "/users/{userid}", method = RequestMethod.GET, 
produces = { MediaType.APPLICATION_JSON_VALUE, 
MediaType.APPLICATION_XML_VALUE }, consumes = MediaType.ALL_VALUE)
public ResponseEntity<User> getuserById(@PathVariable String 
userid,@RequestParam(required= 
false,defaultValue="json",name="responseType"),@RequestHeader ("content-type") String 
contentType)
)

编辑:您可以使用请求参数或请求 header,我在示例中提供了两者供您参考

作为 API 的所有者,您应该声明您能够做出什么样的响应 - 在您的情况下,它是 JSON 或 XML:

@GetMapping(path = "/users/{userId}", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public ResponseEntity<UserDTO> getUserById(@PathVariable(value = "userId") Long userId) {
    return new ResponseEntity<>(userService.get(userId), HttpStatus.OK);
}

API 的任何客户端现在都可以使用 Accept header 选择首选的响应格式 - 例如 Accept: application/xml。 Spring 将尊重这一点,并且 return 以请求的格式响应。

要使其正常工作,您需要添加额外的依赖项,Spring 将使用这些依赖项来生成 XML 响应:

<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
</dependency>

如果你真的需要进入 /users/123.xml 方向,你必须将 userId 类型更改为 String 并像这样自己解析它:

@GetMapping(path = "/users/{userId}")
public ResponseEntity<UserDTO> getUserById(@PathVariable(value = "userId") String userId) {
    if (hasXMLExtension(userId)) {
        return ResponseEntity
                  .ok()
                  .contentType(MediaType.XML)
                  .body(requestdUser);
    } else {
        return ResponseEntity
                  .ok()
                  .contentType(MediaType.JSON)
                  .body(requestdUser);
    }
}

这可以通过使用 ContentNegotiationConfigurer 来完成,您可以按如下方式配置它:

@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer
                .defaultContentType(MediaType.APPLICATION_JSON)
                .mediaType("xml", MediaType.APPLICATION_XML)
                .mediaType("json", MediaType.APPLICATION_JSON);
    }
}

它应该适用于您的端点:

@GetMapping(path = "/users/{userId}", produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE})
public ResponseEntity<UserDTO> getUserById(@PathVariable(value = "userId") Long userId) {
    return new ResponseEntity<>(userService.get(userId), HttpStatus.OK);
}