当前位置: 首页 > 面试题库 >

使用Enum类型作为@ RolesAllowed-Annotation的值参数

薛飞星
2023-03-14
问题内容

我正在开发Java企业应用程序,当前正在执行Java
EE安全性工作,以限制对特定用户的特定功能的访问。我配置了应用程序服务器以及所有内容,现在使用RolesAllowed注释保护方法的安全:

@Documented
@Retention (RUNTIME)
@Target({TYPE, METHOD})
public @interface RolesAllowed {
    String[] value();
}

当我使用这样的注释时,它可以正常工作:

@RolesAllowed("STUDENT")
public void update(User p) { ... }

但这不是我想要的,因为我必须在这里使用String,因此重构变得很困难,并且可能会出现拼写错误。因此,我想使用一个Enum值作为此注释的参数,而不是使用String。枚举看起来像这样:

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;
    }
}

所以我试图使用Enum作为这样的参数:

@RolesAllowed(RoleType.DEANERY.name())
public void update(User p) { ... }

但是然后我得到以下编译器错误,尽管Enum.name只是返回一个String(始终是常量,对吗?)。

注释属性RolesAllowed.value的值必须是一个常量表达式`

我尝试的下一件事是向我的Enum添加一个额外的最终String:

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类只包含一堆静态最终String常量,那您会更好。

为了了解为什么您的代码未编译,我看了一下Java语言规范(JLS)。批注的JLS
指出,对于参数类型为 T 且值为 V 的批注,

如果 T 是原始类型或String,则 V 是常数表达式。

甲常量表达式包括,除其他外,

TypeName 形式的合格名称。 引用常量变量的 标识符

并将常量定义

基本类型或类型的变量,该变量String是最终变量,并使用编译时常量表达式进行初始化



 类似资料:
  • 问题内容: 我正在尝试在一个抽象类中创建一个抽象方法,该抽象类将自己的Enum作为参数。但是我也希望枚举是通用的。 所以我这样宣布: 在实现中,我列举了一个枚举: 并且方法声明变为: 但是,如果我这样做: 我无法访问并显示错误消息: 我做了这样的解决方法: 但是我想知道是否有可能无法通过我的解决方法? 问题答案: 在您的方法实现中,不是枚举,而是类型参数(通常称为)。因此,它掩盖了与已经说过的ax

  • 我想使用泛型类作为另一个泛型类的类型参数。 起初,我对类的定义是这样的: 然后我的需求发生了变化,我不得不为我的R类型使用包装器/持有者类 到目前为止,我的尝试:(给出编译时错误:

  • 问题内容: 我试图将现有代码迁移到使用Enum上,由于缺乏Enum的经验,遇到了一些问题。首先是我的结构。在Entity中,我有一个枚举类(不确定它是否是一个类)。 在我的托管bean上,我有 然后在我的JSF, 我说不是上课 我在EJB中拥有一个原因,以便可以为我的实体创建一个枚举类型,因此我的查询看起来像这样 问题答案: 您不能在EL中访问像这样的枚举。但是,JSF内置了用于EL的枚举转换器。

  • 问题内容: 我有一个主枚举类,它本质上是一种对象类型的类定义。例如,它看起来像下面的示例: 我正在尝试建立一个Javascript模型的发布请求,该请求在主体中发送一个映射,例如 到使用 而我得到以下错误信息: 不能建立从字符串“红”型ColorDefinition的地图键:不是一个有效的表示:不能建立从字符串“红”型ColorDefinition的地图键:对于Enum类值不是一个 什么我在这里做

  • 问题内容: ./chains.go:26:10:不能在作业中使用UpperCaseHandler(typefunc(asl.MessageDelivery))作为asl.MessageHandler类型./chains.go:37:86:无法使用RepeatHandler(类型func(asl.MessageDelivery))与Repeater.ConsumeFunc的参数中的asl.Messa

  • 如果我以通常的方式声明一个类,我可以使用类名作为类型: 但是,如果我通过将类表达式分配给变量来声明一个类,我就不能将该名称用作类型: 建议使用不起作用,因为我想要的实例类型,而不是类本身的类型。 typescript操场示例 如何获取以第二种方式定义的类的实例类型? 我对以这种方式定义类感兴趣的原因是,我希望有一个接口来描述某些类将具有的静态方法,如此处的手册中所述(该部分中的第三个示例)。 下面