Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring mvc Spring引导从控制器返回json和xml_Spring Mvc_Spring Boot - Fatal编程技术网

Spring mvc Spring引导从控制器返回json和xml

Spring mvc Spring引导从控制器返回json和xml,spring-mvc,spring-boot,Spring Mvc,Spring Boot,我有一个SpringBoot1.1.7应用程序,它在大部分UI中使用Thymeleaf,所以我的控制器的响应并不是一个真正的问题。但是,现在我需要在用户通过URL提交请求时提供XML响应 以下是一个典型的请求: http://localhost:9001/remote/search?sdnName=Victoria&address=123 Maple Ave 以下是我的gradle配置的大部分: project.ext { springBootVersion = '1.1.7.

我有一个SpringBoot1.1.7应用程序,它在大部分UI中使用Thymeleaf,所以我的控制器的响应并不是一个真正的问题。但是,现在我需要在用户通过URL提交请求时提供XML响应

以下是一个典型的请求:

http://localhost:9001/remote/search?sdnName=Victoria&address=123 Maple Ave
以下是我的gradle配置的大部分:

project.ext {
    springBootVersion = '1.1.7.RELEASE'
}

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
    compile("org.springframework.boot:spring-boot-starter-thymeleaf")
    compile("org.springframework.boot:spring-boot-starter-security")
    compile("org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion")
    compile("org.springframework.security:spring-security-web:4.0.0.M1")
    compile("org.springframework.security:spring-security-config:4.0.0.M1")
    compile('org.thymeleaf.extras:thymeleaf-extras-springsecurity3:2.1.1.RELEASE')
    compile("org.springframework.boot:spring-boot-starter-actuator")
    compile('com.fasterxml.jackson.dataformat:jackson-dataformat-xml:2.5.0')
}
这是我的控制器:

@Controller
public class RemoteSearchController {

    @Autowired
    private SdnSearchService sdnSearchService;

    @RequestMapping(value = "/remote/search", method = RequestMethod.GET, produces = MediaType.APPLICATION_XML_VALUE)
    public List<Sdn> search(@ModelAttribute SdnSearch sdnSearch) {
        List<Sdn> foundSdns = sdnSearchService.find( sdnSearch );
        return foundSdns;
}
@Controller
public class RemoteSearchController {

    @Autowired
    private SdnSearchService sdnSearchService;

    @RequestMapping(value = "/remote/search", method = RequestMethod.GET, produces = { "application/xml", "text/xml" }, consumes = MediaType.ALL_VALUE )
    @ResponseBody
    public SdnSearchResults search(@ModelAttribute SdnSearch sdnSearch) {
        List<Sdn> foundSdns = sdnSearchService.find( sdnSearch );
        SdnSearchResults results = new SdnSearchResults();
        results.setSdns( foundSdns );
        return results;
    }
}
我能够通过REST客户端(如CocoaREST)接收请求并处理它。但是当我返回SDN列表时,我得到以下异常,即使我的类路径上确实有Jackson&Jackson dataformat xml:

org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
    at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:229)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:301)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:248)
    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.getHandlerInternal(AbstractHandlerMethodMapping.java:57)
    at org.springframework.web.servlet.handler.AbstractHandlerMapping.getHandler(AbstractHandlerMapping.java:299)
我的REST客户机包含一个“text/xml”的Accept头(但老实说,我希望他们不必设置它。理想情况下,对该控制器的任何调用都将始终获得xml,而不管头是否存在)

有办法解决这个问题吗?我以为媒体转换器已经包括在内了,只要控制器告诉他们什么就返回什么

解决方案:
下面是我发布的答案。

创建一个新类可能更好:

public class SdnSearchResult {
  private List<Sdn> sdns;
  ...
}
完成此操作后,另一个控制器必须编码为:

@Controller
public class RemoteSearchController {
  @Autowired
  private SdnSearchService sdnSearchService;

  @RequestMapping("/remote/search")
  @ResponseBody
  public SdnSearchResult search(@RequestBody SdnSearch sdnSearch) {
    return sdnSearchService.find(sdnSearch);
  }
}
快速解释代码中的更改:

  • @RequestBody
    将自动将整个HTTP请求正文反序列化为
    SdnSearch
    实例。外部应用程序通常将请求数据作为HTTP主体提交,因此
    @RequestBody
    将确保对Java对象的反序列化自动进行
  • @ResponseBody
    将根据外部客户端的功能和类路径上可用的库自动序列化返回值。如果Jackson在类路径上可用,并且客户机已经表示可以接受JSON,那么返回值将自动作为JSON发送。如果JRE为1.7或更高版本(这意味着JAXB包含在JRE中),并且客户机已表示可以接受XML,则返回值将自动作为XML发送
  • List
    需要更改为
    SdnSearchResult
    ,以确保应用程序可以使用单个控制器方法交换JSON、XML、RSS和ATOM格式,因为XML(以及基于XML的格式)需要在输出上使用根标记,
    List
    无法转换为根标记
  • 完成这些更改后,启动REST客户端,如Chrome的Postman扩展,并向
    /remote/search
    提交请求,并提供以下信息:

  • 请求头
    接受
    设置为
    application/json
  • 请求头
    Content-Type
    设置为
    application/json
  • 请求正文设置为JSON字符串
    {“sdnName”:“Victoria”,“address”:“123 Maple Ave”}

  • 这将为您提供一个JSON响应。

    您已将控制器方法标记为生成
    应用程序/xml
    响应(
    products=MediaType.application\xml\u VALUE
    )。请求的接受头(
    accept:text/xml
    )不匹配,因此Spring确定您的
    search
    方法无法处理请求

    有几种不同的方法可以在服务器上解决此问题,具体取决于您的具体要求:

    • 您可以完全删除
      products
      属性
    • 您可以指定多种媒体类型:
      products={“application/xml”,“text/xml”}

    我遇到了完全相同的问题,我在Spring文档网站上找到了解决方案:

    在合成中,我将以下依赖项添加到项目的
    pom.xml

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

    解决方案:我使用了下面两种答案的组合(非常感谢!)。我在这里张贴,以防其他人需要帮助

    我的修改控制器:

    @Controller
    public class RemoteSearchController {
    
        @Autowired
        private SdnSearchService sdnSearchService;
    
        @RequestMapping(value = "/remote/search", method = RequestMethod.GET, produces = MediaType.APPLICATION_XML_VALUE)
        public List<Sdn> search(@ModelAttribute SdnSearch sdnSearch) {
            List<Sdn> foundSdns = sdnSearchService.find( sdnSearch );
            return foundSdns;
    }
    
    @Controller
    public class RemoteSearchController {
    
        @Autowired
        private SdnSearchService sdnSearchService;
    
        @RequestMapping(value = "/remote/search", method = RequestMethod.GET, produces = { "application/xml", "text/xml" }, consumes = MediaType.ALL_VALUE )
        @ResponseBody
        public SdnSearchResults search(@ModelAttribute SdnSearch sdnSearch) {
            List<Sdn> foundSdns = sdnSearchService.find( sdnSearch );
            SdnSearchResults results = new SdnSearchResults();
            results.setSdns( foundSdns );
            return results;
        }
    }
    
    @控制器
    公共类远程搜索控制器{
    @自动连线
    专用SDN搜索服务SDN搜索服务;
    @RequestMapping(value=“/remote/search”,method=RequestMethod.GET,products={“application/xml”,“text/xml”},consumes=MediaType.ALL_值)
    @应答器
    公共SDN搜索结果搜索(@ModelAttribute SDN搜索SDN搜索){
    List foundSdns=sdnSearchService.find(sdnSearch);
    SdnSearchResults=新的SdnSearchResults();
    结果:setSdns(foundSdns);
    返回结果;
    }
    }
    
    在我的客户机上,我设置了请求头:

    内容类型:应用程序/文本 接受:text/xml 我认为最终的问题是我的客户端头没有正确设置,所以我可能不需要做一些更改。但我喜欢包含结果列表的SearchResults类的想法:

    @XmlRootElement
    public class SdnSearchResults {
        private List<Sdn> sdns;
    ...
    }
    
    @XmlRootElement
    公共类SDN搜索结果{
    私人名单特殊数据网络;
    ...
    }
    
    除了Michael在他的文章中所说的,我还向pom.xml添加了以下依赖项

    <dependency>
        <groupId>org.codehaus.woodstox</groupId>
        <artifactId>woodstox-core-asl</artifactId>
        <version>4.4.1</version>
    </dependency>
    
    
    org.codehaus.woodstox
    
    或者在浏览器中

    在我的例子中,我想返回一个格式化的XML字符串,并将其全部合并到一行中

    products={“application/xml”,“text/xml”}
    添加到请求映射中就足以将字符串作为格式化的xml(带缩进)返回

    例如:

    @RequestMapping(method= RequestMethod.GET, value="/generate/{blabla}", produces = { "application/xml", "text/xml" })
        public String getBlaBla(@PathVariable("param") String param) throws IOException {
    }
    

    祝您好运。

    我不确定您的Spring Boot版本(1.1.7.RELEASE),但我使用的是1.5.2.RELEASE版本,此xml转换/序列化会自动进行,无需使用任何jackson依赖项,如少数答案中所述

    我想这是因为自SpringBootVersion1.5.1.RELEASE以来,
    org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter
    是自动配置的&转换器使用JRE的默认JAXB实现(因此不需要显式的xml转换依赖项)

    其次,客户机在请求中设置的
    Accept
    头决定了预期的输出格式,因此请求映射如下(即单个端点),
    @RequestMapping(method= RequestMethod.GET, value="/generate/{blabla}", produces = { "application/xml", "text/xml" })
        public String getBlaBla(@PathVariable("param") String param) throws IOException {
    }
    
    @RequestMapping(method = RequestMethod.GET, value = "/remote/search", produces = {
            MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE })
    
       <dependency>
           <groupId>com.fasterxml.jackson.dataformat</groupId>
           <artifactId>jackson-dataformat-xml</artifactId>
        </dependency>