Spring Boot Sping Boot 控制器内容协商

cclgggtu  于 2023-05-06  发布在  Spring
关注(0)|答案(3)|浏览(190)

我在Spring-boot应用程序中编写了一个简单的REST控制器,但我不确定如何实现内容协商,使其基于请求头中的Content-Type参数返回JSON或XML。有人能给我解释一下,我做错了什么吗?
控制器方法:

@RequestMapping(value = "/message", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
  public Message getMessageXML(@RequestParam("text") String text) throws Exception {
    Message message = new Message();
    message.setDate(new Date());
    message.setName("Test");
    message.setAge(99);
    message.setMessage(text);

    return message;
  }

在调用这个方法时,我总是得到JSON(即使我将Content-Type指定为application/xmltext/xml)。
当我实现两个方法时,每个方法都有不同的Map和不同的内容类型,我能够从xml方法中获取XML,但如果我在一个方法中指定两个mediaType(如提供的示例),它就不起作用了。
我想要的是调用\message端点并接收

  • 当GET请求的Content-Type设置为application/xml时,返回XML
  • 当Content-Type为application/json时,为JSON

任何帮助都很感激。
编辑:我更新了我的控制器以接受所有媒体类型

@RequestMapping(value = "/message", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE }, consumes = MediaType.ALL_VALUE)
  public Message getMessageXML(@RequestParam("text") String text) throws Exception {
    Message message = new Message();
    message.setDate(new Date());
    message.setName("Vladimir");
    message.setAge(35);
    message.setMessage(text);

    return message;
  }
ltqd579y

ltqd579y1#

可以使用ContentNegotiationConfigurer
首先,你应该覆盖配置类中的configureContentNegotiation方法:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

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

favorParameter(true)-支持路径表达式优先于参数或接受头。
defaultContentType(MediaType.APPLICATION_JSON)-设置默认内容类型。这意味着如果你不传递路径表达式,Spring将生成JSON作为响应。
mediaType("xml", MediaType.APPLICATION_XML)-设置XML的路径表达式键。
现在,如果你像这样声明你的控制器:

@Controller
class AccountController {

    @RequestMapping(value="/accounts", method=RequestMethod.GET)
    @ResponseStatus(HttpStatus.OK)
    public @ResponseBody List<Account> list(Model model, Principal principal) {
        return accountManager.getAccounts(principal) );
    }
}

并将其命名为localhost:8080/app/accounts.json,然后Spring将生成JSON作为响应。因此,如果调用localhost:8080/app/accounts.xml,您将收到XML响应
您可以找到有关此here的更多信息。

brgchamk

brgchamk2#

您可以在博客文章@RequestMapping with Produces and Consumes中找到一些提示。
请注意有关Content-Type和Accept头的部分:
@RequestMapping与Produces和Consumes:我们可以使用头Content-Type和Accept来找出请求内容以及它想要响应的mime消息是什么。为了清楚起见,@RequestMapping提供了生产和消费变量,我们可以指定将调用的方法的请求内容类型和响应内容类型。例如:

@RequestMapping(value="/method6", produces={"application/json","application/xml"}, consumes="text/html")
@ResponseBody
public String method6(){
    return "method6";
}

上面的方法只能消费Content-Type为text/html的消息,并且能够生成application/json和application/xml类型的消息。
您还可以尝试this不同的方法(使用ResponseEntity对象),该方法允许您找出传入的消息类型并生成相应的消息(也利用@ResponseBody注解)

3gtaxfhh

3gtaxfhh3#

旁注:在Sping Boot 2.6及更高版本中,路径文件扩展策略(例如/resource.xml)用于内容协商,因此未来可能无法证明新应用程序依赖于它。格式参数策略(例如/resource?format=xml)似乎也默认禁用。要启用格式参数策略,请添加一个配置类:

@Configuration
@EnableWebMvc
public class WebConfig
  implements WebMvcConfigurer
{
  @Override
  public void configureContentNegotiation( ContentNegotiationConfigurer configurer )
  {
    configurer
      .favorParameter( true );
  }
}

还要注意的是,从Java 8开始,WebMvcConfigurer接口有默认方法,配置类可以直接实现它,而不需要子类化WebMvcConfigurerAdapter

相关问题