2017-08-18 33 views
1

我已經構建了一個EmployeeEndpoint,它持有不同的方法,如創建,更新,刪除等等。爲了簡化這個問題,我只使用了create方法。Java - 自定義註釋將不被考慮

因爲我想要一個可伸縮的應用程序,我已經構建了一個包含基本方法的接口。在接口中,我現在可以使用JAX-RS-Annotations註釋這些方法。因爲它們將被繼承,所以我只需要重寫EmployeeEndpoint中的接口方法。

接口

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

但解決 ISN」這是一個好主意,因爲不是每個實體都可以創建o只有一位管理員。並與解決方案我放棄了可擴展性的優勢和更少的註釋代碼。所以最好的辦法是:

解決方案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界面方法稱爲過濾器中,我得到的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 
} 

是否有可能以任何方式去解決或不同的方法,我得到同樣的效果?

UPDATE

由於原因似乎並沒有被我貼我會告訴你我AuthorizationFilter代碼。因此我使用this後。

AuthorizationFilter

@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"); 
     } 
    } 
} 
+2

你是什麼意思「權限根本不考慮」? –

+0

當我在JAX-RS的ContainerRequestFilter接口方法中捕獲Permissions-Annotation時,我會看到'null'的值。 – Nadine

+0

剛剛測試過,它工作正常。你得到一個NullPointerException或是調用null的結果? –

回答

0

您的代碼看起來不錯。

我已經運行了一些測試,我能想到的唯一原因是,你正在使用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] 
    } 

} 

獎金,如果你想在測試註解的實際值你的員工資源:

.... 
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; 
} 
+0

我以爲同樣的事情,但這並不能解釋爲什麼解決方案1和2工作。這是假設OP實際測試1和2. –

+0

謝謝你的回答!這不是一個導入問題,我的AuthorizationFilter與您的非常相似。但我更新了我的問題併發布了AuthorizationFilter,以防萬一。 – Nadine