Вы не можете иметь mutliple @Path
аннотации по одному методу. Это приводит к синтаксической ошибке «дублирования аннотации».
Однако существует несколько способов эффективного сопоставления двух путей к методу.
Аннотации @Path
в JAX-RS принимают параметры, значения которых могут быть ограничены с помощью регулярных выражений.
Эта аннотация :
@Path("a/{parameter: path1|path2}")
позволит получить доступ к методу запросов как для /a/path1
, так и для /a/path2
. Если вам нужно работать с подпакетами, выполните слэши: {a:path1\\/subPath1|path2\\/subPath2}
В качестве альтернативы вы можете настроить перенаправление. Вот как это сделать в Джерси (эталонная реализация JAX-RS), путем определения другого субресурса. Это просто пример, если вы предпочитаете другой способ обработки перенаправления, не стесняйтесь использовать его.
@Path("basepath")
public class YourBaseResource {
//this gets injected after the class is instantiated by Jersey
@Context
UriInfo uriInfo;
@Path("a/b")
@GET
public Responce method1(){
return Response.ok("blah blah").build();
}
@Path("a/b/c")
@GET
public Response method2(){
UriBuilder addressBuilder = uriInfo.getBaseUriBuilder();
addressBuilder.path("a/b");
return Response.seeOther(addressBuilder.build()).build();
}
}
Если вы часто требуется такая функциональность, я предлагаю перехватить входящие запросы с использованием фильтра сервлета и переписать пути «на лету». Это должно помочь вам сохранить все перенаправления в одном месте. В идеале вы можете использовать готовую библиотеку. UrlRewriteFilter
может сделать трюк, если у вас все в порядке с лицензией BSD (подробности см. на сайте своего кодового сайта Google).
Другой вариант - обработать это с помощью прокси-сервер, настроенный перед вашим Java-приложением. Вы можете настроить сервер Apache, чтобы предлагать базовые правила кэширования и перезаписи без усложнения кода Java.
Каждый класс (A и B) должен иметь файл заголовка и файл реализации.
Каждый файл заголовка (например, Ah
) не должен включать другой файл заголовка. (например, Bh
), но может включать прямую ссылку на другой класс (например, такой оператор, как class B;
), а затем может использовать указатели и / или ссылки на другой класс в его объявление (например, класс A
может содержать B *
как элемент данных и / или как параметр метода).
Каждый файл CPP (например, A.cpp
) может включать более одного файла заголовка (например, Ah
и Bh
). Рекомендуется, чтобы каждый файл CPP сначала включал свой собственный файл заголовка (например, A.cpp
должен включать Ah
, а затем Bh
, тогда как B.cpp
должен включать Bh
, а затем Ah
).
Каждый файл заголовка должен содержать только объявление, а не определение класса: например, он будет перечислять сигнатуры методов класса, но не тела / реализации методов (тела / реализации методов будут в файле .cpp
, а не в файле заголовка). Поскольку файлы заголовков не содержат деталей реализации, они не зависят (не нужно видеть) деталей других классов; в лучшем случае им нужно знать, что, например, B
- это имя класса: которое он может получить от прямого декларатина, вместо включения файла заголовка в другой файл заголовка.
Каждый файл заголовка должен содержать только объявление, а не определение класса: например, он будет перечислять сигнатуры методов класса, но не тела / реализации методов (тела / реализации методов будут в .cpp
файл, а не в файле заголовка). Поскольку файлы заголовков не содержат деталей реализации, они не зависят (не нуждаются в просмотре) деталей других классов; самое большее, им нужно знать, что, например, B
- это имя класса: которое он может получить от прямого декларатина, вместо включения файла заголовка в другой файл заголовка.
Каждый файл заголовка должен содержать только объявление, а не определение класса: например, в нем будут перечислены сигнатуры методов класса, но не тела / реализации методов (тела / реализации методов будут в .cpp
файл, а не в заголовочном файле). Поскольку файлы заголовков не содержат деталей реализации, они не зависят (не нужно видеть) деталей других классов; в лучшем случае им нужно знать, что, например, B
- это имя класса: которое он может получить от прямого декларатина, вместо включения файла заголовка в другой файл заголовка.
.cpp
, а не в файле заголовка). Поскольку файлы заголовков не содержат деталей реализации, они не зависят (не нуждаются в просмотре) деталей других классов; самое большее, им нужно знать, что, например, B
- это имя класса: которое он может получить от прямого декларатина, вместо включения файла заголовка в другой файл заголовка. но не тела / реализации методов (тела / реализации методов будут в файле .cpp
, а не в файле заголовка). Поскольку файлы заголовков не содержат деталей реализации, они не зависят (не нужно видеть) деталей других классов; в лучшем случае им нужно знать, что, например, B
- это имя класса: которое он может получить от прямого декларатина, вместо включения файла заголовка в другой файл заголовка. Поместите только объявления функций-членов в файлы заголовков (.h) и поместите определения функций-членов в файлы реализации (.cpp). Тогда ваши заголовочные файлы не должны включать друг друга, и вы можете включить оба заголовка в любой файл реализации.
Для случаев, когда вам необходимо ссылаться на другой класс в сигнатурах членов, вы можете использовать прямое объявление:
class A;
Это позволяет вам использовать указатель и ссылочные типы (A*
и A&
), хотя и не сам A
. Это также не позволяет вам называть участников.
Пример:
// a.h
struct B; // forward declaration
struct A {
void foo(B* b); // pointers and references to forward-declared classes are ok
};
// b.h
struct A; // forward declaration
struct B {
void bar(A& a); // pointers and references to forward-declared classes are ok
};
// a.cpp
#include "a.h"
#include "b.h"
void A::foo(B* b) {
b->bar(*this); // full declaration of B visible, ok to call members now
}
// b.cpp
#include "a.h"
#include "b.h"
void B::bar(A& a) {
a.foo(this); // full declaration of A visible, ok to call members now
}
Попробуйте поместить #ifndef
, #define
и #endif
в файлы .h.
Чтобы обойти проблему, вы также можете использовать форвардные объявления .