【问题标题】:XML response from API with PathVariable来自带有 PathVariable 的 API 的 XML 响应
【发布时间】:2020-01-11 22:28:42
【问题描述】:

我有 API:

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

它应该返回 JSON 响应。

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

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

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

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

编辑:

我希望它无需专门添加“接受”标头,也无需编写任何其他逻辑,它将解析 {userId}.xml,然后设置适当的响应类型。

【问题讨论】:

  • 你用的是哪个版本的spring boot?
  • 我用Spring-Boot 2.1.3.RELEASE
  • 获取 userId 参数作为字符串并使用例如解析它正则表达式检测 xml 后缀

标签: java xml spring-boot path-variables


【解决方案1】:

这可以通过使用 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);
}

【讨论】:

    【解决方案2】:

    作为 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 标头选择首选的响应格式 - 例如 Accept: application/xml。 Spring 将尊重这一点并以请求的格式返回响应。

    要使其工作,您需要添加额外的依赖项,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);
        }
    }
    

    【讨论】:

    • 将 userid 设为 String 而不是 long 的问题是拆分字符串后需要额外验证,以检查其是否为有效数字,所以我认为使用 headers 会更好或可选的响应参数。
    【解决方案3】:

    我能想到的最简单的解决方案是有一个可选的请求参数“responseType”,默认值为 json,如果有人想要 XML 响应,他们可以调用 url,如:GET /users/123?responseType =xml 由于参数的默认值是 'json' 并且它具有属性“required= false”,因此在需要 json 响应的用例中您无需担心,如果有人想要 XML 响应,他们可以添加可选的请求参数。另外,我想您需要为控制器指定带有 json 和 xml 返回类型的产品,以让 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)
    )
    

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

    【讨论】:

    • 是的,这是一种选择,但不是很干净。拥有produces = {MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE} 不会改变任何事情。但是,如果您首先放置 MediaType.APPLICATION_XML_VALUE,那么默认响应将是 XML。但它将在 XML 中同时包含 /{userId}.xml/{userId}。只能通过指定 Accept 标头来切换到 JSON。有没有办法以某种方式调整 Spring-Boot 使其开箱即用?
    猜你喜欢
    • 2021-01-08
    • 1970-01-01
    • 2023-03-12
    • 2014-05-10
    • 2011-04-30
    • 1970-01-01
    • 2021-04-06
    • 2013-03-04
    • 2012-11-28
    相关资源
    最近更新 更多