Я разрабатываю корпоративное приложение Java, в настоящее время делая Java материал безопасности EE для ограничения доступа для конкретных функций определенным пользователям. Я настроил сервер приложений и все, и теперь я использую RolesAllowed-аннотацию для обеспечения методов:
@Documented
@Retention (RUNTIME)
@Target({TYPE, METHOD})
public @interface RolesAllowed {
String[] value();
}
Когда я использую аннотацию как это, она хорошо работает:
@RolesAllowed("STUDENT")
public void update(User p) { ... }
Но это не то, что я хочу, поскольку я должен использовать Строку здесь, рефакторинг становится трудным, и опечатки могут произойти. Таким образом вместо того, чтобы использовать Строку, я хотел бы использовать Перечисление значений в качестве параметра для этой аннотации. Перечисление похоже на это:
public enum RoleType {
STUDENT("STUDENT"),
TEACHER("TEACHER"),
DEANERY("DEANERY");
private final String label;
private RoleType(String label) {
this.label = label;
}
public String toString() {
return this.label;
}
}
Таким образом, я пытался использовать Перечисление в качестве параметра как это:
@RolesAllowed(RoleType.DEANERY.name())
public void update(User p) { ... }
Но затем я получаю следующую ошибку компилятора, хотя Enum.name просто возвращает Строку (который является всегда постоянным, не так ли?).
Значение для RolesAllowed.value атрибута аннотации должно быть константным выражением'
Следующая вещь, которую я попробовал, состояла в том, чтобы добавить дополнительную заключительную Строку к моему Перечислению:
public enum RoleType {
...
public static final String STUDENT_ROLE = STUDENT.toString();
...
}
Но это также не работает в качестве параметра, приводя к той же ошибке компилятора:
// The value for annotation attribute RolesAllowed.value must be a constant expression
@RolesAllowed(RoleType.STUDENT_ROLE)
Как я могу достигнуть поведения, которое я хочу? Я даже реализовал свой собственный перехватчик для использования моих собственных аннотаций, который красив, но слишком много выравнивает кодов для небольшой проблемы как это.
Отказ от ответственности
Этим вопросом был первоначально вопрос о Scala. Я узнал, что Scala не является источником проблемы, таким образом, я сначала пытаюсь сделать это в Java.
Я не думаю, что ваш подход к использованию перечислений сработает. Я обнаружил, что ошибка компилятора исчезла, если я изменил поле STUDENT_ROLE
в вашем последнем примере на постоянную строку, а не на выражение:
public enum RoleType {
...
public static final String STUDENT_ROLE = "STUDENT";
...
}
Однако это означает, что значения перечисления не будут можно использовать где угодно, потому что вместо этого вы будете использовать строковые константы в аннотациях.
Мне кажется, вам было бы лучше, если бы ваш класс RoleType
содержал не что иное, как набор статических констант final String.
Чтобы понять, почему ваш код не компилируется, я изучил Спецификацию языка Java (JLS). JLS для аннотаций утверждает, что для аннотации с параметром типа T и значением V ,
если T является примитивный тип или
String
, V является константным выражением.
Постоянное выражение включает, среди прочего,
полные имена в форме TypeName . Идентификатор , который ссылается на постоянные переменные
и постоянную переменную , определяется как
переменная примитивного типа или типа
Строка
, которая является окончательной и инициализируется выражением константы времени компиляции