[英]JAX-RS HATEOAS Using Jersey, Unwanted Link properties in JSON
Since Jersey 2.9, it's been possible to create link relations for hypermedia-driven REST APIs through declarative linking.从 Jersey 2.9 开始,可以通过声明式链接为超媒体驱动的 REST API 创建链接关系。
This code, for example:这段代码,例如:
@InjectLink(
resource = ItemResource.class,
style = Style.ABSOLUTE,
bindings = @Binding(name = "id", value = "${instance.id}"),
rel = "self"
)
@XmlJavaTypeAdapter(Link.JaxbAdapter.class)
@XmlElement(name="link")
Link self;
...in theory is expected to produce JSON like this: ...理论上预计会产生这样的 JSON:
"link" : {
"rel" : "self",
"href" : "http://localhost/api/resource/1"
}
However, Jersey produces different JSON with a lot of properties that I don't need:但是,Jersey 生成不同的 JSON,其中包含许多我不需要的属性:
"link" : {
"rel" : "self",
"uri" : "http://localhost/api/resource/1",
"type": null,
"uriBuilder" : null
}
Notice also that instead of href
, it uses uri
.另请注意,它使用uri
而不是href
。 I looked at Jersey's implementation of the Link
object and found JerseyLink
.我查看了 Jersey 的Link
对象的实现并找到了JerseyLink
。
I want to use Jersey's declarative linking instead of rolling out my own implementation.我想使用 Jersey 的声明式链接而不是推出我自己的实现。 I ended up using Jackson annotations just to ignore other JerseyLink
properties.我最终使用 Jackson 注释只是为了忽略其他JerseyLink
属性。
@JsonIgnoreProperties({ "uriBuilder", "params", "type", "rels" })
Has anyone used declarative linking with Jersey and had the expected JSON output (eg, href
instead of uri
, without extra Jersey properties) without having to use JsonIgnoreProperties
or other hacks?有没有人使用过与 Jersey 的声明式链接并具有预期的 JSON 输出(例如, href
而不是uri
,没有额外的 Jersey 属性)而不必使用JsonIgnoreProperties
或其他黑客?
Thanks.谢谢。
EDIT编辑
I resolved this using an approach which I think is a hack but works well for me and doesn't require the use of a complicated adapter.我使用一种我认为是 hack 但对我来说效果很好的方法解决了这个问题,并且不需要使用复杂的适配器。
I realized that I can actually expose a different object instead of the Link injected by Jersey.我意识到我实际上可以公开一个不同的对象,而不是由 Jersey 注入的 Link。
I created a wrapper object named ResourceLink:我创建了一个名为 ResourceLink 的包装对象:
public class ResourceLink {
private String rel;
private URI href;
//getters and setters
}
Then in my representation object I have a getter method:然后在我的表示对象中,我有一个 getter 方法:
public ResourceLink getLink() {
ResourceLink link = new ResourceLink();
link.setRel(self.getRel());
link.setHref(self.getUri());
return link;
}
So I used Jersey to inject the link but returned a different object in a getter method in my representation object.所以我使用 Jersey 来注入链接,但在我的表示对象中的 getter 方法中返回了一个不同的对象。 This would be the property that would be serialized to JSON and not the injected link object because I didn't create a getter method for it.这将是序列化为 JSON 的属性,而不是注入的链接对象,因为我没有为它创建 getter 方法。
Environment: Jersey 2.13 ( all provider versions are also 2.13 ).环境: Jersey 2.13(所有提供程序版本也是 2.13 )。
Whether you use declarative or programmatic linking, the serialization shouldn't differ.无论您使用声明式链接还是程序化链接,序列化都不应该有所不同。 I chose programmatic, just because I can :-)我选择程序化,只是因为我可以:-)
Test classes:测试类:
@XmlRootElement
public class TestClass {
private javax.ws.rs.core.Link link;
public void setLink(Link link) { this.link = link; }
@XmlElement(name = "link")
@XmlJavaTypeAdapter(Link.JaxbAdapter.class)
public Link getLink() { return link; }
}
@Path("/links")
public class LinkResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getResponse() {
URI uri = URI.create("https://stackoverflow.com/questions/24968448");
Link link = Link.fromUri(uri).rel("stackoverflow").build();
TestClass test = new TestClass();
test.setLink(link);
return Response.ok(test).build();
}
}
@Test
public void testGetIt() {
WebTarget baseTarget = target.path("links");
String json = baseTarget.request().accept(
MediaType.APPLICATION_JSON).get(String.class);
System.out.println(json);
}
jersey-media-moxy球衣媒体莫西
Dependency依赖
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
</dependency>
Result (weird)结果(奇怪)
{
"link": "javax.ws.rs.core.Link$JaxbLink@cce17d1b"
}
jersey-media-json-jackson球衣媒体-json-杰克逊
Dependency依赖
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
</dependency>
Result (close, but what's with the params
?)结果(关闭,但params
什么?)
{
"link": {
"params": {
"rel": "stackoverflow"
},
"href": "https://stackoverflow.com/questions/24968448"
}
}
jackson-jaxrs-json-provider jackson-jaxrs-json-provider
Dependency依赖
<dependency>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.4.0</version>
</dependency>
Result (Two different results, with two different JSON providers)结果(两个不同的结果,具有两个不同的 JSON 提供程序)
resourceConfig.register(JacksonJsonProvider.class);
{
"link": {
"uri": "https://stackoverflow.com/questions/24968448",
"params": {
"rel": "stackoverflow"
},
"type": null,
"uriBuilder": {
"absolute": true
},
"rels": ["stackoverflow"],
"title": null,
"rel": "stackoverflow"
}
}
resourceConfig.register(JacksonJaxbJsonProvider.class);
{
"link": {
"params": {
"rel": "stackoverflow"
},
"href": "https://stackoverflow.com/questions/24968448"
}
}
We are annotating the field with @XmlJavaTypeAdapter(Link.JaxbAdapter.class)
.我们使用@XmlJavaTypeAdapter(Link.JaxbAdapter.class)
注释该字段。 Let look at a snippet of this adapter让我们看一下这个适配器的片段
public static class JaxbAdapter extends XmlAdapter<JaxbLink, Link> {...}
So from Link
, we are being marshalled to JaxbLink
所以从Link
,我们被编组到JaxbLink
public static class JaxbLink {
private URI uri;
private Map<QName, Object> params;
...
}
jersey-media-moxy球衣媒体莫西
Seems to be a bug... See below in solutions.似乎是一个错误......请参阅下面的解决方案。
The others其他
The other two are dependent on jackson-module-jaxb-annotations
to handle marshalling using JAXB annotations.另外两个依赖于jackson-module-jaxb-annotations
来处理使用 JAXB 注释的编组。 jersey-media-json-jackson
will automatically register the required JaxbAnnotationModule
. jersey-media-json-jackson
将自动注册所需的JaxbAnnotationModule
。 For jackson-jaxrs-json-provider
, using JacksonJsonProvider
will not support JAXB annotations (without confgiruation), and using JacksonJsonJaxbProvider
will give us the JAXB annotation support.对于jackson-jaxrs-json-provider
,使用JacksonJsonProvider
将不支持 JAXB 注解(没有配置),而使用JacksonJsonJaxbProvider
将为我们提供 JAXB 注解支持。
So if we have JAXB annotation support, we will get marshalled to JaxbLink
, which will give this result所以如果我们有JAXB 注释支持,我们将被编组到JaxbLink
,这将给出这个结果
{
"link": {
"params": {
"rel": "stackoverflow"
},
"href": "https://stackoverflow.com/questions/24968448"
}
}
The ways we can get the result with all the unwanted properties, is to 1) , use the jackson-jaxrs-json-provider
's JacksonJsonProvider
or 2) , create a ContextResolver
for ObjectMapper
where we don't register the JaxbAnnotationModule
.该方法我们可以与所有不需要的属性得到的结果,是1),使用jackson-jaxrs-json-provider
的JacksonJsonProvider
或2),创建一个ContextResolver
为ObjectMapper
我们不注册JaxbAnnotationModule
。 You seem to be doing one of those.你似乎正在做其中之一。
The above still doesn't get us where we want to get to (ie no params
).以上仍然没有让我们到达我们想要到达的地方(即没有params
)。
For jersey-media-json-jackson
and jackson-jaxrs-json-provider
...对于jersey-media-json-jackson
和jackson-jaxrs-json-provider
...
...which use Jackson, the only thing I can think of at this point is to create a custom serializer ...使用Jackson,此时我唯一能想到的就是创建一个自定义序列化程序
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import javax.ws.rs.core.Link;
public class LinkSerializer extends JsonSerializer<Link>{
@Override
public void serialize(Link link, JsonGenerator jg, SerializerProvider sp)
throws IOException, JsonProcessingException {
jg.writeStartObject();
jg.writeStringField("rel", link.getRel());
jg.writeStringField("href", link.getUri().toString());
jg.writeEndObject();
}
}
Then create a ContextResolver
for the ObjectMapper
, where we register the serializer然后为ObjectMapper
创建一个ContextResolver
,我们在那里注册序列化器
@Provider
public class ObjectMapperContextResolver
implements ContextResolver<ObjectMapper> {
private final ObjectMapper mapper;
public ObjectMapperContextResolver() {
mapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addSerializer(Link.class, new LinkSerializer());
mapper.registerModule(simpleModule);
}
@Override
public ObjectMapper getContext(Class<?> type) {
return mapper;
}
}
This is the result这是结果
{
"link": {
"rel": "stackoverflow",
"href": "https://stackoverflow.com/questions/24968448"
}
}
With jersey-media-moxy , it appears there's a Bug with missing setters in the JaxbLink
class, so the marshalling reverts to calling toString
, which is what's shown above.使用jersey-media-moxy ,似乎在JaxbLink
类中有一个缺少 setter 的错误,因此编组恢复到调用toString
,这就是上面显示的内容。 A work around, as proposed here by Garard Davidson , is just to create another adapter Garard Davidson 在此提出的解决方法就是创建另一个适配器
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import javax.ws.rs.core.Link;
import javax.xml.bind.annotation.XmlAnyAttribute;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.namespace.QName;
public class LinkAdapter
extends XmlAdapter<LinkJaxb, Link> {
public LinkAdapter() {
}
public Link unmarshal(LinkJaxb p1) {
Link.Builder builder = Link.fromUri(p1.getUri());
for (Map.Entry<QName, Object> entry : p1.getParams().entrySet()) {
builder.param(entry.getKey().getLocalPart(), entry.getValue().toString());
}
return builder.build();
}
public LinkJaxb marshal(Link p1) {
Map<QName, Object> params = new HashMap<>();
for (Map.Entry<String,String> entry : p1.getParams().entrySet()) {
params.put(new QName("", entry.getKey()), entry.getValue());
}
return new LinkJaxb(p1.getUri(), params);
}
}
class LinkJaxb {
private URI uri;
private Map<QName, Object> params;
public LinkJaxb() {
this (null, null);
}
public LinkJaxb(URI uri) {
this(uri, null);
}
public LinkJaxb(URI uri, Map<QName, Object> map) {
this.uri = uri;
this.params = map!=null ? map : new HashMap<QName, Object>();
}
@XmlAttribute(name = "href")
public URI getUri() {
return uri;
}
@XmlAnyAttribute
public Map<QName, Object> getParams() {
return params;
}
public void setUri(URI uri) {
this.uri = uri;
}
public void setParams(Map<QName, Object> params) {
this.params = params;
}
}
Using this adapter instead改用这个适配器
@XmlElement(name = "link")
@XmlJavaTypeAdapter(LinkAdapter.class)
private Link link;
will give us the desired output会给我们想要的输出
{
"link": {
"href": "https://stackoverflow.com/questions/24968448",
"rel": "stackoverflow"
}
}
Now that I think about it, the LinkAdapter
would work with the Jackson provider also.现在我考虑了一下, LinkAdapter
也可以与 Jackson 提供程序一起使用。 No need to create a Jackson Serializer/Deserializer.无需创建 Jackson Serializer/Deserializer。 The Jackson module should already support the JAXB annotations out the box, given the JacksonFeature
is enabled.考虑到JacksonFeature
已启用,Jackson 模块应该已经支持开箱即用的 JAXB 注释。 The examples above show using the JAXB/JSON providers separately, but given just the JacksonFeature
is enabled, the JAXB version of the provider should be used.上面的示例显示单独使用 JAXB/JSON 提供程序,但如果仅启用了JacksonFeature
,则应使用提供程序的 JAXB 版本。 This may actually be the more preferred solution.这实际上可能是更优选的解决方案。 No need to create an ContextResolvers
for the ObjectMapper
:-D无需创建一个ContextResolvers
为ObjectMapper
:-D
It's also possible to declare the annotation at the package level, as seen here它也可以在包级别声明注释,如看到这里
I'd like to share with my solution for serialising/deserialising Link objects using with Jackson and the mix-in annotations .我想与我分享使用 Jackson 和混合注释的序列化/反序列化 Link 对象的解决方案。
LinkMixin:链接混合:
@JsonAutoDetect(
fieldVisibility = JsonAutoDetect.Visibility.NONE,
getterVisibility = JsonAutoDetect.Visibility.NONE,
isGetterVisibility = JsonAutoDetect.Visibility.NONE)
@JsonDeserialize(using = LinkMixin.LinkDeserializer.class)
public abstract class LinkMixin extends Link {
private static final String HREF = "href";
@JsonProperty(HREF)
@Override
public abstract URI getUri();
@JsonAnyGetter
public abstract Map<String, String> getParams();
public static class LinkDeserializer extends JsonDeserializer<Link> {
@Override
public Link deserialize(
final JsonParser p,
final DeserializationContext ctxt) throws IOException {
final Map<String, String> params = p.readValueAs(
new TypeReference<Map<String, String>>() {});
if (params == null) {
return null;
}
final String uri = params.remove(HREF);
if (uri == null) {
return null;
}
final Builder builder = Link.fromUri(uri);
params.forEach(builder::param);
return builder.build();
}
}
}
Example:例子:
final ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(Link.class, LinkMixin.class);
final Link link = Link.fromUri("http://example.com")
.rel("self")
.title("xxx")
.param("custom", "my")
.build();
final String json = mapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(Collections.singleton(link));
System.out.println(json);
final List<Link> o = mapper.readValue(json, new TypeReference<List<Link>>() {});
System.out.println(o);
Output:输出:
[ {
"href" : "http://example.com",
"rel" : "self",
"title" : "xxx",
"custom" : "my"
} ]
[<http://example.com>; rel="self"; title="xxx"; custom="my"]
Using the suggested update solution I was still getting the rel part inside the params map.使用建议的更新解决方案,我仍然在 params 映射中获取 rel 部分。
I have made some changes in the Link adapter class我在链接适配器类中做了一些更改
public class LinkAdapter
extends XmlAdapter<LinkJaxb, Link> {
public LinkAdapter() {
}
public Link unmarshal(LinkJaxb p1) {
Link.Builder builder = Link.fromUri(p1.getUri());
return builder.build();
}
public LinkJaxb marshal(Link p1) {
return new LinkJaxb(p1.getUri(), p1.getRel());
}
}
class LinkJaxb {
private URI uri;
private String rel;
public LinkJaxb() {
this (null, null);
}
public LinkJaxb(URI uri) {
this(uri, null);
}
public LinkJaxb(URI uri,String rel) {
this.uri = uri;
this.rel = rel;
}
@XmlAttribute(name = "href")
public URI getUri() {
return uri;
}
@XmlAttribute(name = "rel")
public String getRel(){return rel;}
public void setUri(URI uri) {
this.uri = uri;
}
}
It now holds only the two params which are needed (rel,href) I did not really understand when do I need to unmarshal a Jaxb link to a Link.它现在只包含需要的两个参数 (rel,href) 我真的不明白什么时候需要将 Jaxb 链接解组到链接。 What mattered to me was the Link to Jaxb link marshaling.对我来说重要的是 Link to Jaxb 链接编组。
Thank You, @peeskillet and @Nir Sivan, for your answers.谢谢@peeskillet 和@Nir Sivan 的回答。 But I was able to make it work without using the LinkAdapter
or ContextResolver<ObjectMapper>
.但是我能够在不使用LinkAdapter
或LinkAdapter
ContextResolver<ObjectMapper>
情况下使其工作。
I just added a instance variable of the custom Link type (here ResourceLink
which is analogous to your LinkJaxb
) to my entity class as a @Transient
property and after that Jackson configuration automatically included that attribute in the Response JSON我刚刚将自定义 Link 类型的实例变量(这里ResourceLink
类似于您的LinkJaxb
)作为@Transient
属性添加到我的实体类中,之后 Jackson 配置自动将该属性包含在响应 JSON 中
import javax.xml.bind.annotation.XmlAttribute;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@JsonInclude(Include.NON_EMPTY)
public class ResourceLink {
private String uri;
private String rel;
public ResourceLink() {
this (null, null);
}
public ResourceLink(String uri) {
this(uri, null);
}
public ResourceLink(String uri,String rel) {
this.uri = uri;
this.rel = rel;
}
@XmlAttribute(name = "href")
public String getUri() {
return uri;
}
@XmlAttribute(name = "rel")
public String getRel(){return rel;}
public void setUri(String uri) {
this.uri = uri;
}
}
package com.bts.entities;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.bts.rs.root.util.ResourceLink;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
@Entity
@Table(name="cities")
@JsonInclude(Include.NON_EMPTY)
public class City {
@Id
@Column(name="city_id")
private Integer cityId;
@Column(name="name")
private String name;
@Column(name="status")
private int status;
@Column(name="del_status")
private int delStatus;
@Transient
List<ResourceLink> links = new ArrayList<ResourceLink>();
// private
public City () {
}
public City (Integer id, String name) {
this.cityId = id;
this.name = name;
this.status = 0;
this.delStatus = 0;
}
// getters and setters for Non-transient properties
// Below is the getter for lInks transient attribute
public List<ResourceLink> getLinks(){
return this.links;
}
// a method to add links - need not be a setter necessarily
public void addResourceLink (String uri,String rel) {
this.links.add(new ResourceLink(uri, rel));
}
}
@GET
@Path("/karanchadha")
@Produces({MediaType.APPLICATION_JSON})
@Transactional
public Response savePayment() {
City c1 = new City();
c1.setCityId(11);
c1.setName("Jamshedpur");
c1.addResourceLink("http://www.test.com/home", "self");
c1.addResourceLink("http://www.test.com/2", "parent");
return Response.status(201).entity(c1).build();
}
First dependencies :第一个依赖项:
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.34</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-declarative-linking</artifactId>
<version>2.34</version>
</dependency>
Second - config class:第二 - 配置类:
package app.rest.config;
import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.jackson.internal.jackson.jaxrs.json.JacksonJaxbJsonProvider;
import org.glassfish.jersey.linking.DeclarativeLinkingFeature;
import org.glassfish.jersey.server.ResourceConfig;
@ApplicationPath(value = "rest")
public class RestApplicationConfig extends ResourceConfig{
public RestApplicationConfig() {
register(JacksonJaxbJsonProvider.class);
register(DeclarativeLinkingFeature.class);
packages("app.rest.controllers");
}
}
Third - create adapter class第三 - 创建适配器类
package app.rest.config;
import javax.json.Json;
import javax.json.JsonObject;
import javax.json.bind.adapter.JsonbAdapter;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.UriBuilder;
public class CustomJsonAdapter implements JsonbAdapter<Link, JsonObject> {
@Override
public JsonObject adaptToJson(Link link) throws Exception {
StringBuilder builder = new StringBuilder();
builder.append("http://");
builder.append(link.getUri().getHost());
builder.append(":");
builder.append(link.getUri().getPort());
builder.append(link.getUri().getRawPath());
return Json.createObjectBuilder().add("href", builder.toString()).add("rel", link.getRel()).build();
}
@Override
public Link adaptFromJson(JsonObject json) throws Exception {
Link link = Link.fromUriBuilder(UriBuilder.fromUri(json.getString("href"))).rel(json.getString("rel")).build();
return link;
}
}
Forth - register JsonbConfig with custom adapter class from Link class to Json第四- 使用自定义适配器类注册 JsonbConfig,从 Link 类到 Json
package app.rest.config;
import javax.json.bind.Jsonb;
import javax.json.bind.JsonbBuilder;
import javax.json.bind.JsonbConfig;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
@Provider
public class AppJsonConfig implements ContextResolver<Jsonb> {
@Override
public Jsonb getContext(Class<?> type) {
JsonbConfig jsonbConfig = new JsonbConfig();
jsonbConfig.withAdapters(new CustomJsonAdapter());
return JsonbBuilder.create(jsonbConfig);
}
}
Fifth : create the model with Link and @InjectLink annotation第五:使用 Link 和 @InjectLink 注释创建模型
package app.rest.model;
import java.io.Serializable;
import java.util.Objects;
import javax.json.bind.annotation.JsonbTypeAdapter;
import javax.ws.rs.core.Link;
import javax.xml.bind.annotation.XmlRootElement;
import org.glassfish.jersey.linking.Binding;
import org.glassfish.jersey.linking.InjectLink;
import org.glassfish.jersey.linking.InjectLink.Style;
import app.rest.config.CustomJsonAdapter;
import app.rest.controllers.RestController;
@XmlRootElement
public class StudentResource implements Serializable{
private static final long serialVersionUID = 1L;
private Long id;
private String name;
private String surname;
@InjectLink(resource = RestController.class,
style = Style.ABSOLUTE,
rel = "self",
method = "getStudentById",
bindings = @Binding(name = "id", value = "${instance.id}"))
@JsonbTypeAdapter(value = CustomJsonAdapter.class)
private Link link;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Link getLink() {
return link;
}
public void setLink(Link link) {
this.link = link;
}
@Override
public int hashCode() {
return Objects.hash(name, surname);
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
StudentResource other = (StudentResource) obj;
return Objects.equals(name, other.name) && Objects.equals(surname, other.surname);
}
}
And at the end rest controller最后休息控制器
package app.rest.controllers;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
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.Context;
import javax.ws.rs.core.GenericEntity;
import javax.ws.rs.core.Link;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import app.rest.model.*;
@Path(value = "student")
public class RestController {
@Context
private UriInfo uriInfo;
private final ArrayList<StudentResource> students = new ArrayList<>();
public RestController() {
StudentResource s1 = new StudentResource();
s1.setId(1L);
s1.setName("test1");
s1.setSurname("surTest1");
students.add(s1);
StudentResource s2 = new StudentResource();
s2.setId(2L);
s2.setName("new_St");
s2.setSurname("surNew");
students.add(s2);
}
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getAllStudents() throws URISyntaxException{
Link link = Link.fromUriBuilder(uriInfo.getAbsolutePathBuilder()).rel("self").type("GET").build();
GenericEntity<List<StudentResource>> studentsEntities = new GenericEntity<List<StudentResource>>(students) {};
return Response.status(Response.Status.OK).entity(studentsEntities).links(link).build();
}
@GET
@Path(value = "/{id}")
@Produces(MediaType.APPLICATION_JSON)
public Response getStudentById(@PathParam(value = "id") Long id ) {
Iterator<StudentResource> iterator = students.iterator();
StudentResource studentById= null;
while (iterator.hasNext()) {
StudentResource next = iterator.next();
if(next.getId().equals(id)) {
studentById = next;
break;
}
}
if(null!=studentById) return Response.status(Response.Status.OK).entity(studentById).build();
else return Response.status(Response.Status.NO_CONTENT).build();
}
}
Deployed and tested on Payara 5.201在 Payara 5.201 上部署和测试
Produces : get http://localhost:8080/sampleappee/rest/student/1产生:获取 http://localhost:8080/sampleappee/rest/student/1
{"id":1,"link":{"href":"http://localhost:8080/sampleappee/rest/student/1","rel":"self"},"name":"test1","surname":"surTest1"}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.