我正在使用球衣2.17和HK2来创建一个简单的休息应用程序。
我有ContainerRequestFilter
拒绝任何没有“currentuser”cookie的请求。
我有这样的事情:
@Path("/users")
public class UserResource {
private UserService userService;
@GET
@Path("/orders")
@Produces("application/json")
public List<Order> findOrdersOfCurrentUser() {
// some ugly code to access headers, extract cookies, and finally
// extract username (a String) from a particular cookie
return this.userService.findOrdersByUsername(username) ;
}
}
我想编写比这更优雅的代码。 像这样:
@Path("/users")
public class UserResource {
private UserService userService;
@CurrentUsername
private String currentUser;
@GET
@Path("/orders")
@Produces("application/json")
public List<Order> findOrdersOfCurrentUser() {
return this.userService.findOrdersByUsername(username) ;
}
}
我真的很喜欢hk2,并且很难找到实现它的方法。
我只是要求实现正确的接口(或扩展类)。
答案 0 :(得分:4)
您正在寻找的内容并非琐碎。解决此问题的一种方法是将SecurityContext
内的ContainerRequestFilter
设置为seen here。这并不涉及与HK2的任何直接互动。然后,您可以在资源类中注入SecurityContext
。并通过
securityContext.getUserPrincipal().getName();
如果您真的想要使用自定义注释注入用户名,则需要创建InjectionResolver
(See Defining Custom Injection Annotation。您可以注入ContainerRequestContext
(同一个传递到ContainerRequestFilter
)中的过滤方法或SecurityContext
中的InjectionResolver
。例如
过滤
@Provider
@PreMatching
public class UserFilter implements ContainerRequestFilter {
public static final String USER_PROP = "user";
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
requestContext.setProperty(USER_PROP, new User("peeskillet"));
}
}
注释
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CurrentUser {
}
InjectionResolver
public class CurrentUserInjectionResolver implements InjectionResolver<CurrentUser> {
javax.inject.Provider<ContainerRequestContext> requestContext;
@Inject
public CurrentUserInjectionResolver(
javax.inject.Provider<ContainerRequestContext> requestContext) {
this.requestContext = requestContext;
}
@Override
public Object resolve(Injectee injectee, ServiceHandle<?> sh) {
if (User.class == injectee.getRequiredType()) {
return requestContext.get().getProperty(UserFilter.USER_PROP);
}
return null;
}
@Override
public boolean isConstructorParameterIndicator() { return false; }
@Override
public boolean isMethodParameterIndicator() { return false; }
}
绑定InjectionResolver
@Provider
public class UserFeature implements Feature {
@Override
public boolean configure(FeatureContext context) {
context.register(new AbstractBinder(){
@Override
public void configure() {
bind(CurrentUserInjectionResolver.class)
.to(new TypeLiteral<InjectionResolver<CurrentUser>>(){})
.in(Singleton.class);
}
});
return true;
}
}
资源
@Path("user")
public class UserResource {
@CurrentUser
private User user;
@GET
public Response getCurrentUser() {
return Response.ok(user.getUsername()).build();
}
}
现在我对第二种方法不太确定,至少关于过滤器的部分是@PreMatching
过滤器。如果我不进行预匹配,则User
将为空。似乎ContainerRequestContext
还没有我们设置的属性,这意味着似乎正在发生的事情是在过滤器之前调用InjectResolver
。我需要研究一下。将其作为预匹配,不需要IMO。
就个人而言,我会采用第一种方法,只使用SecurityContext
。一个完整的例子就在我上面提供的链接中。通过这种方法,您可以根据需要利用泽西岛的RolesAllowedDynamicFeature
。