簡體   English   中英

將@PathParam 傳遞給 Jersey 中的子資源定位器類

[英]Passing @PathParam to Sub Resource locator class in Jersey

我想以這種方式調用我的 api 端點:

http://.../companies/1/employees

並用代碼 1 檢索公司的員工。我有這個代碼:

@Path("companies")
public class CompanyResource {

    @Context
    ResourceContext resourceContext;

    @GET
    @Path("{idCompany}/employees")
    public EmployeeResource getEmployees() {
        return resourceContext.getResource(EmployeeResource.class);
    }

}

@Path("/employees")
public class EmployeeResource {

    @PathParam("idCompany")
    String idCompany;

    @GET
    public List<Employee> getEmployees() {
        // here "idCompany" is null
        //some code
    }
}

但路徑參數為空。 我究竟做錯了什么? 有沒有更正確的方法來做到這一點?

以下是JAX-RS 2.0可能解決方案的摘要:

  • 使用構造函數請求作用域子資源:

     @Path("companies") public class CompanyResource { @Path("{idCompany}/employees") public EmployeeResource getEmployees(@PathParam("idCompany") String companyId) { return new EmployeeResource(companyId); } } public class EmployeeResource { private String companyId public EmployeeResource(String companyId) { this.companyId = companyId; } @GET public List<Employee> getEmployees() { //some code } } 

    缺點:

    • 沒有依賴注入
  • 使用ResourceContext #initResource(Class)請求作用域子資源:

     @Path("companies") public class CompanyResource { @Context private ResourceContext resourceContext; @GET @Path("{idCompany}/employees") public EmployeeResource getEmployees(@PathParam("idCompany") String companyId) { EmployeeResource employeeResource = new EmployeeResource(companyId); return resourceContext.initResource(employeeResource); } } public class EmployeeResource { @Context private Request request; private String companyId public EmployeeResource(String companyId) { this.companyId = companyId; } @GET public List<Employee> getEmployees() { //some code } } 

    缺點:

  • 使用ResourceContext#getResource(Class)請求作用域子資源:

     @Path("companies") public class CompanyResource { @Context private ResourceContext resourceContext; @GET @Path("{idCompany}/employees") public EmployeeResource getEmployees(@PathParam("idCompany") String companyId) { EmployeeResource employeeResource = resourceContext.getResource(EmployeeResource.class); employeeResource.setCompanyId(companyId); return employeeResource; } } public class EmployeeResource { @Context private Request request; private String companyId public setCompanyId(String companyId) { this.companyId = companyId; } @GET public List<Employee> getEmployees() { //some code } } 

    缺點:

  • 使用@PathParam作為字段請求作用域子資源:

     @Path("companies") public class CompanyResource { @Context private ResourceContext resourceContext; @GET @Path("{idCompany}/employees") public EmployeeResource getEmployees() { return resourceContext.getResource(EmployeeResource.class); } } public class EmployeeResource { @Context private Request request; @PathParam("idCompany") private String companyId; @GET public List<Employee> getEmployees() { // some code } } 

    缺點:

  • 請求返回類型為Class<T>作用域子資源:

     @Path("companies") public class CompanyResource { @GET @Path("{idCompany}/employees") public Class<EmployeeResource> getEmployees() { return EmployeeResource.class; } } public class EmployeeResource { @Context private Request request; @PathParam("idCompany") private String companyId; @GET public List<Employee> getEmployees() { // some code } } 

    缺點:

  • 使用@PathParam作為方法參數請求作用域子資源:

     @Path("companies") public class CompanyResource { @Context private ResourceContext resourceContext; @GET @Path("{idCompany}/employees") public Class<EmployeeResource> getEmployees() { return resourceContext.getResource(EmployeeResource.class); } } public class EmployeeResource { @Context private Request request; @GET public List<Employee> getEmployees(@PathParam("idCompany") String companyId) { // some code } } 

    缺點:

  • 使用@PathParam作為方法參數的Singleton子資源:

     @Path("companies") public class CompanyResource { @Context private ResourceContext resourceContext; @GET @Path("{idCompany}/employees") public Class<EmployeeResource> getEmployees() { return resourceContext.getResource(EmployeeResource.class); } } @Singleton public class EmployeeResource { @Context private Request request; @GET public List<Employee> getEmployees(@PathParam("idCompany") String companyId) { // some code } } 

    缺點:

也可以看看:

我無法重現null id,但有幾點需要指出

  • @GET應從被刪除EmployeeResource getEmployees()方法。 子資源定位器不應具有HTTP方法注釋。 請參閱子資源
  • 此外, EmployeeResource上的@Path被忽略(不需要)。 不是問題,只是認為你應該知道。

下面是使用Jersey Test Framework的完整工作示例。 以下是我使用的測試依賴項

<dependency>
    <groupId>org.glassfish.jersey.test-framework.providers</groupId>
    <artifactId>jersey-test-framework-provider-grizzly2</artifactId>
    <version>${jersey2.version}</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.glassfish.jersey.media</groupId>
    <artifactId>jersey-media-json-jackson</artifactId>
    <version>${jersey2.version}</version>
    <scope>test</scope>
</dependency>

您可以像任何其他JUnit測試一樣運行它

import java.util.ArrayList;
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.container.ResourceContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.junit.Test;
import static junit.framework.Assert.*;

public class LocatorTest extends JerseyTest {

    public static class Employee {
        public String firstName;
        public String lastName;
        public Employee(){}
        public Employee(String firstName, String lastName) {
            this.firstName = firstName;
            this.lastName = lastName;
        }
    }

    public static class Company {
        public String companyId;
        public List<Employee> employees;
        public Company(){}
        public Company(String companyId, List<Employee> employees) {
            this.companyId = companyId;
            this.employees = employees;
        }
    }

    @Path("companies")
    public static class CompanyResource {

        @Context
        private ResourceContext resourceContext;

        @Path("{companyId}/employees")
        public EmployeeResource getEmployees() {
            return resourceContext.getResource(EmployeeResource.class);
        }
    }

    public static class EmployeeResource {

        @PathParam("companyId")
        public String companyId;

        @GET
        @Produces(MediaType.APPLICATION_JSON)
        public Company getCompanyEmployees() {
            List<Employee> emps = new ArrayList<>();
            emps.add(new Employee("pee", "skillet"));
            emps.add(new Employee("Stack", "Overflow"));
            Company co = new Company(companyId, emps);
            return co;
        }
    }

    @Override
    public ResourceConfig configure() {
        return new ResourceConfig(CompanyResource.class);
    }

    @Test
    public void doit() {
        Response response = target("companies/1234/employees").request().get();
        assertEquals(200, response.getStatus());
        Company co = response.readEntity(Company.class);
        assertNotNull(co.companyId);
        assertEquals("1234", co.companyId);
        assertEquals(2, co.employees.size());
        response.close();
    }
}

我像這樣使用路徑參數

@GET
public List<Employee> getEmployees(@PathParam("idCompany") String id ) {
    // here "idCompany" is null
    //some code
}

這就是我通常這樣做的方式:

@Path("companies")
public class CompanyResource {

    @GET
    @Path("{idCompany}/employees")
    public EmployeeResource getEmployees(@PathParam("idCompany") String idCompany) {
       // ...
    }

}

要么

@Path("companies/{idCompany}/employees")
public class EmployeeResource {

    @PathParam("idCompany")
    String idCompany;

    @GET
    public List<Employee> getEmployees() {
       //
    }
}

@PathParam在第二個示例中為null,因為為了將其注入字段,服務類上的@Path注釋必須有一個聲明{idCompany} @PathParam

如果任何解決方案不起作用,請嘗試此作為最后的手段。

@GET
@Path("{companyId: \\d+}/employees")
public EmpoyeesResource subResource() {

    return CDI.current().select(EmployeesResource.class).get();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM