Stack是Spring Boot w / Jetty / Jersey。这是有问题的资源方法:
@GET
@Path("campaignTargets")
@Produces(MediaType.APPLICATION_JSON)
@Transactional(readOnly=true)
public List<CampaignTargetOutputDTO> getCampaignTargets(
@PathParam("businessUnitId") Integer id,
@QueryParam("name") String name,
@Pattern(regexp = DATE_VALIDATION_PATTERN) @QueryParam("startDate") String startDate,
@Pattern(regexp = DATE_VALIDATION_PATTERN) @QueryParam("endDate") String endDate,
@Pattern(regexp = INTEGER_CSV_VALIDATION_PATTERN) @QueryParam("targetTypeIds") String targetTypeIds,
@Pattern(regexp = ALPHANUM_CSV_VALIDATION_PATTERN) @QueryParam("statuses") String statuses) {
return ResourceUtil.entityOr404(campaignService.getAdvertiserCampaignTargets(id, name, startDate, endDate, targetTypeIds, statuses));
}
当Jersey拦截对此方法的调用以执行验证时,它不会(始终)获得此方法。我之所以知道这一点,是因为我接受了Jersey documentation的建议并创建了以下ValidationConfig
:
@Provider
public class ValidationConfigurationContextResolver implements
ContextResolver<ValidationConfig> {
@Context
private ResourceContext resourceContext;
@Override
public ValidationConfig getContext(Class<?> type) {
final ValidationConfig config = new ValidationConfig();
config.constraintValidatorFactory(
resourceContext.getResource(InjectingConstraintValidatorFactory.class));
config.parameterNameProvider(new CustomParameterNameProvider());
return config;
}
private static class CustomParameterNameProvider extends DefaultParameterNameProvider {
private static final Pattern PROXY_CLASS_PATTERN = Pattern.compile("(.*?)\\$\\$EnhancerBySpringCGLIB\\$\\$.*$");
public CustomParameterNameProvider() {
}
@Override
public List<String> getParameterNames(Method method) {
/*
* Since we don't have a full object here, there's no good way to tell if the method we are receiving
* is from a proxy or the resource object itself. Proxy objects have a class containing the string
* $$EnhancerBySpringCGLIB$$ followed by some random digits. These proxies don't have the same annotations
* on their method params as their targets, so they can actually interfere with this parameter naming.
*/
String className = method.getDeclaringClass().getName();
Matcher m = PROXY_CLASS_PATTERN.matcher(className);
if(m.matches()) {
try {
return getParameterNames(method.getDeclaringClass().getSuperclass().
getMethod(method.getName(), method.getParameterTypes()));
} catch (Exception e) {
return super.getParameterNames(method);
}
}
Annotation[][] annotationsByParam = method.getParameterAnnotations();
List<String> paramNames = new ArrayList<>(annotationsByParam.length);
for(Annotation[] annotations : annotationsByParam) {
String name = getParamName(annotations);
if(name == null) {
name = "arg" + (paramNames.size() + 1);
}
paramNames.add(name);
}
return paramNames;
}
private String getParamName(Annotation[] annotations) {
for(Annotation annotation : annotations) {
if(annotation.annotationType() == QueryParam.class) {
return ((QueryParam) annotation).value();
} else if(annotation.annotationType() == PathParam.class) {
return ((PathParam) annotation).value();
}
}
return null;
}
}
}
我对此解决方案的主要问题是它需要一段评论(希望)以防止将来出现混淆。否则它似乎工作。如果没有这个,我会得到像arg1
这样的无信息参数名称,等等,我想避免使用。这个解决方案的另一个大问题是它过分依赖Spring中Aop代理的实现。该模式可能会在未来的某个时刻更改并破坏此代码,当评论未能阐明其目的时,我可能无法在此解释此代码。最奇怪的是,这似乎是间歇性的。有时参数名称是好的,有时它们不是。任何建议都表示赞赏。
答案 0 :(得分:0)
事实证明,这是因为从eclipse运行服务器而发生的。我还没弄清楚原因,但是从命令行运行服务器可以解决问题。如果有人能弄明白为什么eclipse这样做以及如何关闭任何&#34;功能&#34;日食引起了这种情况,我会upvote /接受你的回答。现在答案是,不要在eclipse中运行服务。