当前位置: 首页 > 知识库问答 >
问题:

JAX-RS(Jersey 2实现)具有URL扩展的内容协商。xml或。json

穆俊杰
2023-03-14

我看到了一个Java RESTFUL webservice,它允许在URL中请求内容类型,并在末尾添加一个扩展,例如

  • <代码>。xml

这就是我在自己的Web服务中努力实现的内容协商风格。

我知道@Produces注释,以及一个方法可以使用(value = {})语法解析多个类型的事实,方法是添加接受标头,比如使用Postman,Chrome扩展名。

但我不知道如何有效地从一种方法中提取信息,并委托给另一种方法。

我假设REGEX可以与@Path@PathParam一起使用,但我这样做的尝试尚未取得成果。

有人能举个例子吗?

这是我迄今为止的尝试:

package com.extratechnology.caaews;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.extratechnology.caaews.model.Log;


@Path("et")
@Produces(MediaType.APPLICATION_JSON)
public class CAAEWS {


    @GET
    @Path("\\.{format}")
    @Produces(value = {MediaType.APPLICATION_JSON, MediaType.TEXT_XML})
    public Log getLog(
            @PathParam("format") String format
    ){
        Log result = null;
        switch (format) {
        case "json":
            result = this.getJSON();
        case "xml":
            result = this.getXML();
        }
        return result;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Log getJSON() {
        return new Log("JSON!");
    }

    @GET
    @Produces(MediaType.TEXT_XML)
    public Log getXML() {
        return new Log("XML!");
    }

}
package com.extratechnology.caaews.model;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Log {
    private String log;

    public Log(String log) {
        this.log = log;
    }

    public String getLog() {
        return log;
    }

    public void setLog(String log) {
        this.log = log;
    }

}

该项目可以从Spring工具套件/Eclipse中设置,方法是使用以下内容创建一个Maven项目(类似,但比这里的4:50更为更新):

  • 组织。玻璃鱼。运动衫原型
  • 运动衫。快速启动。webapp
  • 2.26

然后取消对pom部分的注释。提供xml以支持JSON,这有效地为WAR添加了更多JAR。

我发现我也有一些讨厌的BCEL错误,不得不将一些条目附加到catalina.properties文件中,在键下:

tomcat.util.scan.StandardJarScanFilter.jarsToSkip=\
....
javax.json-api-1.1.jar, javax.json.bind-api-1.0.jar, javax.json-1.1.jar, \
yasson-1.0.jar

http://localhost:18080/caaews/webapi/et

产量:

{"log":"JSON!"}

http://localhost:18080/caaews/webapi/et.xml或

http://localhost:18080/caaews/webapi/et.json

产量:

HTTP Status 404 - Not Found

我还想知道是否有某种HTTP侦听器类型的方法来实现这一点。我的Java有点过时了,但它是servlet过滤器,还是类似于AOP的建议。

多亏了@user1803551,我在switch语句中加入了中断符。

多亏了@callmepills,我对代码进行了一些调整。

类级别@Path注释现在有这个。@Produces(value={MediaType.APPLICATION_JSON, MediaType.TEXT_XML})

getLog@Path注释是“{format}”。

为了调用和委托getLog,必须对URL使用以下语法:

http://localhost:18080/caaews/webapi/et

http://localhost:18080/caaews/webapi/et/.xml

http://localhost:18080/caaews/webapi/et/.json

路径中需要一个“/”不是我想要的,所以我认为我可能必须解决servlet过滤器,而不是@PathParam方法。。

共有3个答案

公冶嘉茂
2023-03-14

您是否尝试过在类级别摆脱@Path注释?那么您的方法级别注释将是:

@Path("et.{format}")

我认为您当前的实现正在创建一个子资源,该子资源与以下路径匹配:

/et/{format}
史俊德
2023-03-14

JAX-RS代码有几个问题:

路径注释的值仅在参数模板内和字符后解析正则表达式。您试图在参数模板之外使用正则表达式,“\.{format}”,因此它不会将其解析为正则表达式。

方法的路径包括类路径的段,后跟它自己的路径段。当您尝试调用/et时,您的代码建议路径/et/。{格式}/et。{格式},它没有在任何地方定义,因此是404。

这是一个根据您的代码工作的示例:

@Path("et")
public class Resource {

    private static final String JSON = "json";
    private static final String XML = "xml";

    @GET
    @Path(".{format:(" + JSON + "|" + XML + ")}")
    @Produces(value = { MediaType.APPLICATION_JSON, MediaType.TEXT_XML }) // not XML?
    public String getLog(@PathParam("format") String format) {
        switch (format) {
            case JSON:
                this.getJSON();
                break;
            case XML:
                this.getXML();
        }
        return format;
    }

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public void getJSON() {
        System.out.println("in JSON");
    }

    @GET
    @Path("otherPath")
    @Produces(MediaType.APPLICATION_XML)
    public void getXML() {
        System.out.println("in XML");
    }
}

您的有效请求现在是:

  • http://localhost:18080/caaews/webapi/et(JSON通过getJSON
  • http://localhost:18080/caaews/webapi/et/otherPath(XML通过getXML
  • http://localhost:18080/caaews/webapi/et/.xml(XML通过getLog
  • http://localhost:18080/caaews/webapi/et/.json(JSON通过getLog

根据需要更改路径。我使用“otherPath”作为XML方法,因为它不能与空路径JSON方法冲突。我不建议这样做。

注意:

  • 在switch语句中使用break
  • 为了减少出现错误的机会,请像我对自定义格式类型所做的那样,对可重用字符串等使用常量。枚举更好

编辑:

请求现在有一个路径/et/

@GET
@Path("{segment:[a-zA-Z0-9_]*\\.(" + JSON + "|" + XML + ")}")
@Produces(value = { MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
public String getLog(@PathParam("segment") String segment) {
    String format = segment.substring(segment.indexOf('.') + 1);
    switch (format) {
        case JSON:
            this.getJSON();
            break;
        case XML:
            this.getXML();
    }
    return format;
}

正则表达式表示任何字母数字或下划线一次或多次。你可以用你想要的任何限制来替换那个部分。有关允许的字符,请参阅URL规范。

子车征
2023-03-14

虽然你没有标记jersey,但你的问题表明你正在使用jersey,所以我将发布一个特定于jersey的解决方案。Jersey提供的属性可用于设置媒体类型映射

public static final String MEDIA\u TYPE\u映射

定义URI扩展到媒体类型的映射。该属性由UriconneFilter使用。有关媒体类型映射的更多信息,请参阅javadoc。

属性值必须是StringString[]Map的实例

txt : text/plain, xml : application/xml

未设置默认值。

配置属性的名称为“jersey.config.server.mediaTypeMappings”。

final Map<String, MediaType> mediaTypeMappings = new HashMap<>();
mediaTypeMappings.put("xml", MediaType.APPLICATION_XML_TYPE);
mediaTypeMappings.put("json", MediaType.APPLICATION_JSON_TYPE);

final ResourceConfig rc = new ResourceConfig()
        .packages("com.example.jersey")
        .property(ServerProperties.MEDIA_TYPE_MAPPINGS, mediaTypeMappings);
<servlet>
    <servlet-name>JerseyApplication</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
        <param-name>jersey.config.server.provider.packages</param-name>
        <param-value>com.example</param-value>
    </init-param>
    <init-param>
        <param-name>jersey.config.server.mediaTypeMappings</param-name>
        <param-value>xml:application/xml, json:application/json</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

 类似资料:
  • 问题内容: 我有一个使用Jersey构建的REST服务。 我希望能够根据发送到服务器的MIME设置我的自定义异常编写器的MIME。当接收到json和接收到xml 时返回。 现在我进行了硬编码,但这使XML客户端陷入了黑暗。 我可以利用什么上下文来获取当前请求? 谢谢! 根据答案更新 对于对完整解决方案感兴趣的其他人: 连同 其中ErrorResponseConverter是自定义JAXB POJO

  • Apache支持HTTP/1.1规范中定义的内容协商,它可以根据浏览器提供的参数选择一个资源最合适的媒体类型、语言、字符集和编码的表现方式。它还实现了一些对浏览器发送不完整内容协商信息进行智能处理的能力。 内容协商由mod_negotiation模块支持,并被默认编译进服务器。 关于内容协商(Content Negotiation) 一个资源可能会有多种不同的表现形式,比如,可能会有不同语言或者媒

  • You can configure how Spring MVC determines the requested media types from the request. The available options are to check the URL path for a file extension, check the "Accept" header, a specific quer

  • 我将rest服务配置为通过Variant实现内容协商。在jersey上一切正常,但在apache cxf上有些问题。 找不到类ContentType:Application/XML的消息正文编写器 当我将响应构造为xml类型时,似乎找不到正确的正文编写器。

  • 主要内容:关于内容协商Apache HTTPD支持规范中描述的内容协商。它可以根据浏览器提供的媒体类型,语言,字符集和编码首选项,选择资源的最佳表示形式。它还实现了一些功能,可以更智能地处理来自发送不完整协商信息的浏览器的请求。 内容协商由模块提供,该模块默认编译。 关于内容协商 资源可以以多种不同的表示形式提供。例如,它可能以不同语言或不同媒体类型或组合形式提供。选择最合适选择的一种方法是为用户提供索引页面,然后让他

  • 内容协商是基于客户端或服务器偏好选择多种可能的表示之一以返回客户端的过程。 确定接受的渲染器 REST framework 根据可用的渲染器,每个渲染器的优先级以及客户端的 Accept: header,使用简单的内容协商风格来确定应将哪些媒体类型返回给客户端。所使用的风格部分由客户端驱动,部分由服务器驱动。 更具体的媒体类型优先于较不特定的媒体类型。 如果多种媒体类型具有相同的特性,则优先根据为