gpt4 book ai didi

Java – 自定义注释不会被考虑

转载 作者:太空宇宙 更新时间:2023-11-04 11:13:17 25 4
gpt4 key购买 nike

我构建了一个 EmployeeEndpoint,它包含不同的方法,例如创建、更新、删除等等。为了简化这个问题,我只使用了 create 方法。

因为我想要一个可扩展的应用程序,所以我构建了一个包含基本方法的接口(interface)。在界面中,我现在可以使用 JAX-RS-Annotations 对方法进行注释。因为它们将被继承,所以我只需重写 EmployeeEndpoint 中的接口(interface)方法。

界面

public interface RESTCollection<T> {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public T create(T entity) throws Exception;
}

端点

@Stateless
@Path(“employee“)
public class EmployeeEndpoint implements RESTCollection<Employee> {
@Override
public Employee create(Employee employee) throws Exception {
return this.createEmployee(employee);
}
}

上面的例子运行良好。如果我想添加自定义注释,我可以这样做:

解决方案1

public interface RESTCollection<T> {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Permissions(Role.Admin)
public T create(T entity) throws Exception;
}

解决方案2

@Stateless
@Path(“employee“)
public class EmployeeEndpoint implements RESTCollection<Employee> {
@Override
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Permissions(Role.Admin)
public Employee create(Employee employee) throws Exception {
return this.createEmployee(employee);
}
}

但是解决方案1并不是一个好主意,因为并非每个实体都只能由管理员创建。通过解决方案2,我失去了可扩展性和注释代码较少的优势。所以最好的方法是:

解决方案3

@Stateless
@Path(“employee“)
public class EmployeeEndpoint implements RESTCollection<Employee> {
@Override
@Permissions(Role.Admin)
public Employee create(Employee employee) throws Exception {
return this.createEmployee(employee);
}
}

但是现在,当我在 JAX-RS 的 ContainerRequestFilter 接口(interface)方法(称为过滤器)中捕获 Permissions-Annotation 时,我得到了 null 值,但我不明白。

@Context
private ResourceInfo resourceInfo;

resourceInfo.getResourceMethod().getAnnotation(Permissions.class) // is null

注释

@NameBinding
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Permissions {
Role[] value() default {};
}

枚举

public enum Role {
Admin,
User
}

是否可以采用解决方案3或具有相同优势的其他方法?

更新

因为原因似乎不是我发布的代码,所以我将向您展示我的 AuthorizationFilter。因此我用了this发布。

授权过滤器

@Provider
@Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter {

@Inject
@AuthenticatedUser
private User authenticatedUser;

@Context
private ResourceInfo resourceInfo;

@Override
public void filter(ContainerRequestContext requestContext) throws IOException {

Class<?> resourceClass = resourceInfo.getResourceClass();
List<Role> classRoles = extractRoles(resourceClass);

Method resourceMethod = resourceInfo.getResourceMethod();
List<Role> methodRoles = extractRoles(resourceMethod);

try {

if (methodRoles.isEmpty()) checkPermissions(classRoles, requestContext.getHeaderString(HttpHeaders.AUTHORIZATION));
else checkPermissions(methodRoles, requestContext.getHeaderString(HttpHeaders.AUTHORIZATION));

} catch (NotAuthorizedException e) {
requestContext.abortWith(
Response.status(Response.Status.UNAUTHORIZED).build());
} catch (Exception e) {
requestContext.abortWith(
Response.status(Response.Status.FORBIDDEN).build());
}
}

private List<Role> extractRoles(AnnotatedElement annotatedElement) {
if (annotatedElement == null) return new ArrayList<Role>();
else {
Permissions perms = annotatedElement.getAnnotation(Permissions.class);
if (perms == null) return new ArrayList<Role>();
else {
Role[] allowedRoles = perms.value();
return Arrays.asList(allowedRoles);
}
}
}

private void checkPermissions(List<Role> allowedRoles, String authorizationHeader) throws NotAuthorizedException, Exception {
if (!allowedRoles.isEmpty()) {
if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer "))
throw new NotAuthorizedException("Authorization header must be provided");
else if (!allowedRoles.contains(this.authenticatedUser.getRole()))
throw new Exception("User has no permissions");
}
}
}

最佳答案

你的代码看起来不错。

我已经运行了一些测试,我能想到的唯一原因是您在 Employee 资源上使用了2 种不同的 Permission 类型,而不是过滤器上的类型。 (检查您的导入)

不确定您的Filter代码,但这是我的代码,它正在工作(请参阅导入):

package com.app.filters; // TODO change this with yours

import java.io.IOException;
import java.util.Arrays;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;

import com.app.services.Permissions; // TODO change this with yours

public class AuthorizationFilter implements ContainerRequestFilter {

@Context
ResourceInfo resourceInfo;

@Override
public void filter (ContainerRequestContext requestContext) throws IOException {
Permissions perms = resourceInfo.getResourceMethod ().getAnnotation (Permissions.class);

System.out.println (getClass ().getSimpleName () + " --> Permissions: " + Arrays.toString (perms.value ())); // prints [Admin]
}

}

如果您想测试 Employee 资源上注释的实际值,则有额外的好处:

....
import com.app.services.Permissions; // TODO change this with yours (the one on the filter being the same as this one)
....

@Permissions (Role.Admin)
@Override
public Employee create (Employee employee) throws Exception {
Class<?> [] cArg = new Class [1];
cArg [0] = Employee.class;

Method method = getClass ().getMethod ("create", cArg);
Permissions perms = method.getAnnotation (Permissions.class);

System.out.println (EmployeeService.class.getSimpleName () + " --> Permissions: " + Arrays.toString (perms.value ()));

return null;
}

关于Java – 自定义注释不会被考虑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45761353/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com