Көктем MVC - @Valid REST қызметіндегі бұршақтардың тізімінде

Көктемде MVC REST қызметі (json), менде осындай сияқты контроллер әдісі бар:

@RequestMapping(method = RequestMethod.POST, value = { "/doesntmatter" })
@ResponseBody
public List<...> myMethod(@Valid @RequestBody List request, BindingResult bindingResult) {

MyBean сыныбының бит валидациясы аннотациялары бар жерде.

Дәлелдемелер бұл жағдайда орын алған жоқ, бірақ ол басқа контроллерлер үшін жақсы жұмыс істейді.

Мен json-ті енгізуді өзгерте алатын тізімге кіргізуді қаламаймын.

Неліктен листілер тізіміне қатысты ешқандай растама жоқ? Қандай нұсқалар бар?


22
stackoverflow.com/a/36313615/3110023 пайдалануыңызға болады
қосылды автор mehdi, көзі

7 жауаптар

@Valid is a JSR-303 annotation and JSR-303 applies to validation on JavaBeans. A java.util.List is not a JavaBean (according to the official description of a JavaBean), hence it cannot be validated directly using a JSR-303 compliant validator. This is supported by two observations.

Section 3.1.3 of the JSR-303 Specification says that:

In addition to supporting instance validation, validation of graphs of object is also supported. The result of a graph validation is returned as a unified set of constraint violations. Consider the situation where bean X contains a field of type Y. By annotating field Y with the @Valid annotation, the Validator will validate Y (and its properties) when X is validated. The exact type Z of the value contained in the field declared of type Y (subclass, implementation) is determined at runtime. The constraint definitions of Z are used. This ensures proper polymorphic behavior for associations marked @Valid.

Collection-valued, array-valued and generally Iterable fields and properties may also be decorated with the @Valid annotation. This causes the contents of the iterator to be validated. Any object implementing java.lang.Iterable is supported.

Маңызды ақпараттың қалыңдығын атап өттім. Бұл бөлім жинау түрінің расталуы үшін, оны бұршақ ішінде инкапсулациялау керек ( Келтірілген жағдайды қарастырайық, онда X түріндегі Y өрісі бар өріс бар); сондай-ақ, жинақтар тікелей өрістер мен қасиеттерге ) назар аудара алмайды ( Топтамалық құндылық, жиымдық және әдетте айналдырылатын өрістер мен қасиеттер де безендірілген болуы мүмкін .

Өзекті JSR-303 іске асыру

Менде үлгі қосымшасы бар Hibernate Validator және Apache Beans Validator. Бұл үлгіде mvn clean test -Phibernate (Gibernate Validator) және mvn clean test -Papache (Beans Validator үшін) сияқты сынақтарды іске қоссаңыз, екеуі де тікелей коллекцияларды , ол техникалық сипаттамаға сәйкес келеді. Hibernate Validator - бұл JSR-303 үшін анықтамалық іске асыру болғандықтан, бұл үлгі тағы да дәлелдеу үшін жинақтарды бұршақ ішінде жинақталуы керек екендігінің тағы бір дәлелі болып табылады.


Бұл тазартылғаннан кейін, мен осы мәселеде көрсетілгендей контроллер әдісіне коллекцияны тапсыруға тырысқанда дизайн мәселесі де бар. Түпнұсқалар жинақтарда тікелей жұмыс істеуі мүмкін болса да, контроллер әдісі жинақтарға тікелей салыстырылмайтын пайдаланушы XML, SOAP, ATOM, EDI, Google протоколының буферлері және т.б. сияқты баламалы деректер ұсынуымен жұмыс істей алмайды. Бұл ұсыныстарды қолдау үшін, контроллер объектінің даналарын қабылдауы және қайтаруы керек. Бұл кез-келген жолмен инкапсуляциялауды қажет етеді. Сондықтан, List дегенді басқа нысанға орап қою ұсынылады, себебі басқа жауаптар ұсынылды.

28
қосылды

Мұны істеудің жалғыз жолы - тізімді орау, бұл JSON енгізуінің өзгертуі керек дегенді білдіреді.

@RequestMapping(method = RequestMethod.POST, value = { "/doesntmatter" })
@ResponseBody
public List<...> myMethod(@Valid @RequestBody List request, BindingResult bindingResult) {

болады:

@RequestMapping(method = RequestMethod.POST, value = { "/doesntmatter" })
@ResponseBody
public List<...> myMethod(@Valid @RequestBody MyBeanList request, BindingResult bindingResult) {

және бізге де қажет:

import javax.validation.Valid;
import java.util.List;

public class MyBeanList {

    @Valid
    List list;

    //getters and setters....
}

Бұл тізімдерге арналған теңдестірілген тексерушімен бірге болуы мүмкін, бірақ мен әлі де алыс емеспін.

@Valid аннотациясы стандартты JSR-303 Bean Validation API бөлігі болып табылады және көктемге тән конструкция емес.   Жазғы MVC тиісті Validator конфигурацияланған кезде байланыстырудан кейін @Valid нысанын тексереді.

Reference : http://docs.spring.io/spring/docs/current/spring-framework-reference/html/validation.html

9
қосылды

Тікелей тексеруді қолданып көріңіз. Сол сияқты бірнәрсе:

@Autowired
Validator validator;

@RequestMapping(method = RequestMethod.POST, value = { "/doesntmatter" })
@ResponseBody
public Object myMethod(@RequestBody List request, BindingResult bindingResult) {
    for (int i = 0; i < request.size(); i++) {
        Object o = request.get(i);
        BeanPropertyBindingResult errors = new BeanPropertyBindingResult(o, String.format("o[%d]", i));
        validator.validate(o, errors);
        if (errors.hasErrors())
            bindingResult.addAllErrors(errors);
    }
    if (bindingResult.hasErrors())
        ...
4
қосылды

Өзіңіздің валидаторыңызды org.springframework.validation.beanvalidation.LocalValidatorFactoryBean элементі ретінде енгізіңіз және әрбір элемент үшін сол валидаторды шақырыңыз.

public class CheckOutValidator implements Validator {


    private Validator validator;

   @Override
    public void validate(Object target, Errors errors) { 
    List request = (List) target;
    Iterator it = request.iterator()   
    while(it.hasNext()) {
    MyBean b = it.next();
    validator.validate(b, errors);

     }

     }

//setters and getters

}
2
қосылды

There is a elegant way to wrapper your request in a custom java.util.List which acts as both List and JavaBean. see here

1
қосылды

I think your best option is to wrap the list - How to validate request parameter if it is not a bean in spring MVC?

@Valid жиынтығының элементтеріне қолданылатынын айтудың ешқандай жолы жоқ.

0
қосылды
Джсон енгізуін өзгерте алмайтындай тізімді орауға қандай да бір тәсіл бар ма?
қосылды автор J0B, көзі

Егер сізде бар әрбір тізім үшін қабықша жазуды қаламасаңыз, сіз әдеттегі қабықты пайдалана аласыз:

public class ListWrapper {

    private List list;

    public ListWrapper() {
        list = new ArrayList<>();
    }

    public ListWrapper(List list) {
        this.list = list;
    }

    @Valid
    public List getList() {
        return list;
    }

    public void setList(List list) {
        this.list = list;
    }

    public boolean add(E e) {
        return list.add(e);
    }

    public void clear() {
        list.clear();
    }

}
0
қосылды