2015-04-01 2 views
1

У меня есть простая служба типа REST, реализованная в JAX-RS для поддержки Foo. Он создает foos с POST foos, перечисляет foos с GET foos и детализирует данный foo с GET foo/42 (где 42 - это идентификатор foo).Возможность повторного использования в службах REST с JAX-RS

public class FooService { 

    @POST 
    @Path("/foos") 
    public Foo create(Foo foo){ 
    entityManager.getTransaction().begin(); 
    entityManager.persist(foo); 
    entityManager.getTransaction().commit(); 
    return foo; 
    } 

    @GET 
    @Path("/foos") 
    public List<Foo> get(){ 
     List<Foo> foos = //more-or-less generic JPA querying-code 
     return foos; 
    } 

    @GET 
    @Path("/foos/{id}") 
    public Foo get(@PathParam("id") int id){ 
     Foo foo = //more-or-less generic JPA querying-code 
     return foo; 
    } 
} 

Теперь, если у меня есть аналогичный сервис для поддержания Bar «с, как я полагаю, элегантно избежать повторения кода?

public class BarService { 

    @POST 
    @Path("/bars") 
    public Bar create(Bar bar){ 
    entityManager.getTransaction().begin(); 
    entityManager.persist(bar); 
    entityManager.getTransaction().commit(); 
    return bar; 
    } 

    @GET 
    @Path("/bars") 
    public List<Bar> get(){ 
     List<Bar> bars = //more-or-less generic JPA querying-code 
     return bars; 
    } 

    @GET 
    @Path("/bars/{id}") 
    public Bar get(@PathParam("id") int id){ 
     Bar bar = //more-or-less generic JPA querying-code 
     return bar; 
    } 
} 

Единственным отличием является путь значения, указанные в аннотации @Path. Поскольку это значение должно быть статическим (видно во время компиляции) это не возможно создать AbstracService класс как:

public abstract class AbstracService<X> { 

    //abstrac static is not possible 
    public abstract static final String PATH; 

    @POST 
    @Path(PATH) 
    public X create(X entity){ ... } 

    @GET 
    @Path(PATH) 
    public List<X> get(){ ... } 

    @GET 
    @Path(PATH + "/{id}") 
    public X get(@PathParam("id") int id){ ... } 
} 


public class FooService extends AbstractService<Foo>{ 
     //just override the PATH to be "foos" 
}  

public class BarService extends AbstractService<Bar>{ 
     //just override the PATH to be "bars" 
}  

мне нужно переопределить каждый метод сервиса Как только настроить @Path и их называют super сек реализации?

Вышеуказанные классы FooService и BarService слишком похожи, чтобы мой звонок повторного использования не звучал.

ответ

3

Довольно распространен по всем моим классам ресурсов будет этой картине

@Path("foo") 
public class FoosResource { 
    @GET // get all `Foo` resources 
    ... 
    @GET 
    @Path("{id}") // get `Foo` with this id 
    ... 
    @POST // create new `Foo` in `foo` collection 
    ... 
    @PUT 
    @Path("{id}") // Update `Foo` with this id 
} 

Вы получаете идею. Дело в том, что название коллекции на классе ресурсов, а не уровня метода ресурсов, как вы его

@Path("foo/{id}") 

Вы будете нуждаться в @Path в любом случае, чтобы сделать класс класс ресурс, то почему бы не использовать самое подходящее имя для него.

Еще одна вещь, которую я мог бы добавить, - это то, что я часто делаю. Я добавляю поле Class в абстрактном классе, с конструктором arg, который я могу передать Class. Затем в конкретной реализации класса, I super(Foo.class). Таким образом, JPA имеет доступ к классу, что упрощает работу с типом запросов.

+0

Вот чего мне не хватало. – bruno

-1

Ну я уверен, что вы могли бы сделать что-то вроде этого

@POST 
@Path("/{foosOrBars}")//will match to any string 
public BaseFooBar create(@PathParam("foosOrBars") String type){ 

if(type.equals("foos")){ 
//do something with the foo 
}else{ 
//do something different 
} 

} 

Так у вас есть базовый класс BaseFooBar, который вы можете расширить как Foo или Bar.

Но вы должны быть осторожны, если у вас есть другой метод на одной и той же службе, а также с тем же уровнем иерархии, например./Foobar. Он должен иметь фиксированный идентификатор и не использовать фигурные скобки, иначе ваш путь не будет правильно соответствовать.

+0

Слишком плохо, что базовый класс ('' BaseFooBar'' должен заранее знать все его расширение. – bruno

Смежные вопросы