![](/img/trans.png)
[英]Canot call set method on a object that's proxied with Cglib2AopProxy
[英]Spring CGLIB AopProxy interferes with Jersey resource method parameter validation
Stack是帶有Bootty / Jersey的Spring Boot。 這是有問題的資源方法:
@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文檔的建議並創建了以下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代理的實現。 該模式將來可能會更改並破壞此代碼,當注釋無法闡明其目的時,我可能不會在這里解釋此代碼。 最奇怪的是,它似乎是斷斷續續的。 有時參數名稱很好,有時則不好。 任何建議表示贊賞。
事實證明,這是由於從eclipse運行服務器而導致的。 我還沒有弄清楚為什么,但是從命令行運行服務器可以解決問題。 如果有人能弄清為什么Eclipse會這樣做以及如何關閉導致Eclipse的任何“功能”,那么我會贊成/接受你的回答。 現在的答案是,不要在Eclipse中運行該服務。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.