簡體   English   中英

Spring CGLIB AopProxy干擾Jersey資源方法參數驗證

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM