一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - @Valid 無(wú)法校驗(yàn)List<E>的問(wèn)題

@Valid 無(wú)法校驗(yàn)List<E>的問(wèn)題

2022-02-23 13:20MiracleWei777 Java教程

這篇文章主要介紹了@Valid 無(wú)法校驗(yàn)List<E>的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

 

@Valid 無(wú)法校驗(yàn)List<E>

 

原因

@Valid只能校驗(yàn)JavaBean,而List<E>不是JavaBean所以校驗(yàn)會(huì)失敗,嘗試了三種解決辦法,比較推薦方法3,其他兩種大家也可以學(xué)習(xí)一下。

 

方法

方法1:對(duì)List進(jìn)行Wrapper

既然List不是JavaBean,那我們就把它封裝成JavaBean,我們定義一個(gè)ListWrapper類如下:

package com.wyq.firstdemo.util; 
import lombok.Getter;
import lombok.Setter; 
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List; 
@Setter
@Getter
public class ListWrapper<E> {
    @Valid
    private List<E> list; 
    public ListWrapper() {
        list = new ArrayList<>();
    } 
    public  ListWrapper(List<E> list) {
        this.list = list;
    } 
}

同時(shí)修改一下controller對(duì)應(yīng)的方法:

    // 使用包裝類對(duì)list進(jìn)行驗(yàn)證
    @PostMapping("/insert/all")
    public ServerResponse<String> insertList(@Valid @RequestBody ListWrapper<UserEntity> listWrapper, BindingResult bindingResult) {
        if(bindingResult.hasErrors()) {
            log.error(bindingResult.getFieldError().toString());
            return ServerResponse.createByErrorMessage(bindingResult.getFieldError().getDefaultMessage());
        }
 
        userService.insertList(listWrapper.getList());
        return ServerResponse.createBySuccess();
    }

這樣就可以對(duì)list進(jìn)行校驗(yàn)了

注意:

由于對(duì)list進(jìn)行了包裝,如果我們傳參的時(shí)候

[{},{}..]要改為{“list”: [{},{}..]}

方法2:使用@Validated+@Valid

在controller類上面增加@Validated注解,并且刪除方法參數(shù)中的BindingResult bindingResult(因?yàn)檫@個(gè)參數(shù)已經(jīng)沒(méi)有用了,異常統(tǒng)一有controller返回了)

@Valid 無(wú)法校驗(yàn)List<E>的問(wèn)題

@Valid 無(wú)法校驗(yàn)List<E>的問(wèn)題

然后我們運(yùn)行一下測(cè)試一下

@Valid 無(wú)法校驗(yàn)List<E>的問(wèn)題

可以看到可以對(duì)參數(shù)進(jìn)行校驗(yàn)了,但還還有一個(gè)問(wèn)題,那就是這個(gè)不是我們想要的返回格式,它c(diǎn)ontroller自己返回的格式,所以我們需要做一個(gè)統(tǒng)一異常處理,代碼如下:

package com.wyq.firstdemo.handler;
import com.wyq.firstdemo.common.ServerResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice; 
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.Set;
 
@Slf4j
@RestControllerAdvice
public class ControllerExceptionHandler {
 
    @ExceptionHandler
    @ResponseBody
    public ServerResponse<String> handle(ConstraintViolationException exception) {
        log.error(String.valueOf(exception));
        Set<ConstraintViolation<?>> violations = exception.getConstraintViolations();
        StringBuilder builder = new StringBuilder();
        for (ConstraintViolation violation : violations) {
            builder.append(violation.getMessage());
            break;
        }
        return ServerResponse.createByErrorMessage(builder.toString());
    } 
}

經(jīng)過(guò)統(tǒng)一異常處理,我們這邊的返回結(jié)果就是我們想要的格式了

@Valid 無(wú)法校驗(yàn)List<E>的問(wèn)題

方法3:自定義一個(gè)List

先上代碼后說(shuō)明,先定義一個(gè)ValidList

package com.wyq.firstdemo.util;  
import javax.validation.Valid;
import java.util.*; 
public class ValidList<E> implements List<E> { 
    @Valid
    private List<E> list;
 
    public ValidList() {
        this.list = new ArrayList<>();
    }
 
    public ValidList(List<E> list) {
        this.list = list;
    }
 
    public List<E> getList() {
        return list;
    }
 
    public void setList(List<E> list) {
        this.list = list;
    }
 
    @Override
    public int size() {
        return list.size();
    }
 
    @Override
    public boolean isEmpty() {
        return list.isEmpty();
    } 
    ... 
}

對(duì)比方法3和方法1,有沒(méi)有覺(jué)得代碼有點(diǎn)相似,新建一個(gè)類,并且讓他實(shí)現(xiàn)List接口,使這個(gè)類即具有了JavaBean的特性,又具有了List的特性,比方法1簡(jiǎn)單優(yōu)雅很多。

只需要把List換成ValidList就可以了,還不需要多統(tǒng)一異常處理。

@Valid 無(wú)法校驗(yàn)List<E>的問(wèn)題

參考:https://stackoverflow.com/questions/28150405/validation-of-a-list-of-objects-in-spring/36313615#36313615

 

@validated 驗(yàn)證List

經(jīng)常遇到一些參數(shù)需要驗(yàn)證,用@validated 的分組驗(yàn)證方式很棒,可以解決大量的冗余代碼,提升美觀性。

但是我們平時(shí)會(huì)遇到入?yún)閘ist的校驗(yàn),@validated 的分組驗(yàn)證就無(wú)法使用了,非常麻煩,各大搜索引擎一查,總結(jié)一下比較推薦的方法:

 

反面例子

@***Mapping("/**")
public *** apiName(@RequestBody @Validated(Add.class) List<AClass> aObject)

正常情況下這個(gè)例子是無(wú)法使用的,不是接口無(wú)法使用,是@Validated無(wú)效。這是因?yàn)槟愕娜雲(yún)?shí)體是List,其內(nèi)并沒(méi)有調(diào)用AClass的@Valid,導(dǎo)致你的校驗(yàn)規(guī)則只校驗(yàn)的List本身,并不校驗(yàn)其內(nèi)部實(shí)體。

 

解決方法

在項(xiàng)目里添加一個(gè)ValidList類即可,此類通用,可以在全部由此需求的項(xiàng)目(jdk1.8)中添加,無(wú)需改動(dòng),有ValidList類之后只要將接口方法參數(shù)中的List改成ValidList即可:

@***Mapping("/**")
public *** apiName(@RequestBody @Validated(Add.class) ValidList<Bean> aObject)

上代碼:

注意這個(gè)構(gòu)造方法,網(wǎng)上的例子就少一點(diǎn)東西,會(huì)讓你很難用,我優(yōu)化了一下。

package com.analog.greatbolderserver.config.valid; 
import lombok.Data;
import lombok.NoArgsConstructor; 
import javax.validation.Valid;
import java.util.*;
 
/**
 * @ClassName ValidList
 * @Description ValidList
 * @Author TY
 * @Date 2020/8/26 16:05
 * @Version 1.0
 **/
@Data
@NoArgsConstructor
public class ValidList<E> implements List<E> { 
    @Valid
    private List<E> list = new LinkedList<>(); 
    public ValidList(List<E> paramList) {
        this.list = paramList;
    }
 
    @Override
    public int size() {
        return list.size();
    }
 
    @Override
    public boolean isEmpty() {
        return list.isEmpty();
    }
 
    @Override
    public boolean contains(Object o) {
        return list.contains(0);
    }
 
    @Override
    public Iterator<E> iterator() {
        return list.iterator();
    }
 
    @Override
    public Object[] toArray() {
        return list.toArray();
    }
 
    @Override
    public <T> T[] toArray(T[] a) {
        return list.toArray(a);
    }
 
    @Override
    public boolean add(E e) {
        return list.add(e);
    }
 
    @Override
    public boolean remove(Object o) {
        return list.remove(o);
    }
 
    @Override
    public boolean containsAll(Collection<?> c) {
        return list.containsAll(c);
    }
 
    @Override
    public boolean addAll(Collection<? extends E> c) {
        return list.addAll(c);
    }
 
    @Override
    public boolean addAll(int index, Collection<? extends E> c) {
        return list.addAll(index, c);
    }
 
    @Override
    public boolean removeAll(Collection<?> c) {
        return list.removeAll(c);
    }
 
    @Override
    public boolean retainAll(Collection<?> c) {
        return list.retainAll(c);
    }
 
    @Override
    public void clear() {
        list.clear();
    }
 
    @Override
    public E get(int index) {
        return list.get(index);
    }
 
    @Override
    public E set(int index, E element) {
        return list.set(index, element);
    }
 
    @Override
    public void add(int index, E element) {
        list.add(index, element);
    }
 
    @Override
    public E remove(int index) {
        return list.remove(index);
    }
 
    @Override
    public int indexOf(Object o) {
        return list.indexOf(o);
    }
 
    @Override
    public int lastIndexOf(Object o) {
        return list.lastIndexOf(o);
    }
 
    @Override
    public ListIterator<E> listIterator() {
        return list.listIterator();
    }
 
    @Override
    public ListIterator<E> listIterator(int index) {
        return list.listIterator(index);
    }
 
    @Override
    public List<E> subList(int fromIndex, int toIndex) {
        return list.subList(fromIndex, toIndex);
    }
}

這樣前端的代碼是不需要任何改動(dòng)的!

這個(gè)時(shí)候有小伙伴說(shuō),需要捕獲異常,是的,@Validated是通過(guò)拋出異常來(lái)進(jìn)行返回的。

上代碼,全局異常處理:

/**
 * @ClassName GlobalException
 * @Description 異常處理攔截器
 * @Author TY
 * @Date 13:59$ 2019-01-30$
 * @Version 1.0
 **/
@RestControllerAdvice
public class GlobalException {
    private Logger logger = LoggerFactory.getLogger(this.getClass());
 
    /**
     * 參數(shù)為空異常處理
     *
     * @param ex ex
     * @return ReturnResult
     */
    @ExceptionHandler({
            ParamNullException.class, MethodArgumentNotValidException.class,
            ConstraintViolationException.class, HttpMessageNotReadableException.class,
            MissingServletRequestParameterException.class
    })
    public ReturnResult<?> requestMissingServletRequest(Exception ex) {
        ReturnResult<?> returnResult = new ReturnResult<>();
        returnResult.setRetCode(2);
        if (ex instanceof MissingServletRequestParameterException) {
            returnResult.setRetMsg("參數(shù)非法:" + ((MissingServletRequestParameterException) ex).getParameterName());
        } else if (ex instanceof HttpMessageNotReadableException) {
            //排除入?yún)?wèn)題
            returnResult.setRetMsg("參數(shù)非法:" + ex.getMessage());
        } else if (ex instanceof MethodArgumentNotValidException) {
            //排除入?yún)?wèn)題
            FieldError error = (FieldError) ((MethodArgumentNotValidException) ex).getBindingResult().getAllErrors().get(0);
            returnResult.setRetMsg("參數(shù)非法:" + error.getField() + " " + error.getDefaultMessage());
        } else if (ex instanceof ConstraintViolationException) {
            //排除入?yún)?wèn)題
            ConstraintViolation<?> violation = ((ConstraintViolationException) ex).getConstraintViolations().iterator().next();
            returnResult.setRetMsg("參數(shù)非法:" + violation.getPropertyPath().toString().split("[.]")[1]
                    + violation.getMessage());
        }
        return returnResult;
    }
 
    /**
     * 其他異常
     *
     * @param request request
     * @param ex      ex
     * @return ReturnResult
     */
    @ExceptionHandler(Exception.class)
    public ReturnResult<?> resolveException(HttpServletRequest request, Exception ex) {
        ReturnResult<?> returnResult = new ReturnResult<>();
 
        logger.error("==============異常開始=============");
        logger.error("url: " + request.getRequestURL() + " msg: " + ex.getMessage());
        ex.printStackTrace();
        logger.info("==============異常結(jié)束=============");
 
        returnResult.setRetCode(1);
        returnResult.setRetMsg("GlobalException!!!");
        returnResult.setRetData(ex.toString());
        return returnResult;
    }
}

ReturnResult是自己定一的方法返回封裝類,根據(jù)自己的項(xiàng)目自己封裝就行。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。

原文鏈接:https://blog.csdn.net/weiyanqiang2012/article/details/94388824

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产精品亚洲午夜一区二区三区 | 91精品国产高清久久久久 | 国产精品免费一级在线观看 | 亚洲狠狠婷婷综合久久久久网站 | 日本在线视频播放 | 蜜月aⅴ免费一区二区三区 蜜桃影像传媒推广 | 岛国片免费观看 | 激情偷拍网 | 秋葵视频成人 | 精品综合久久久久久8888 | 免费av在线看 | 国产va免费精品高清在线 | 国产亚洲精品网站 | 日本免费三片在线观看 | 日韩一区二区不卡 | 3d动漫美女被吸乳羞羞有 | 国产成人综合网亚洲欧美在线 | 美女女女女女女bbbbbb毛片 | 5278欧美一区二区三区 | 亚洲精品国产精品精 | 四虎1515hhc0m | 亚洲经典激情春色另类 | 国产精品一区二区国产 | 精品卡1卡2卡三卡免费视频 | 17个农民工婉莹第一部 | gangbang日本 | 思久久 | 2020国产精品视频 | 日韩手机在线观看 | 视频在线观看入口一二三2021 | 天天亚洲综合 | 大陆国产vs国产对白 | avtt一区| 成人做视频免费 | 成人综合网站 | 美女被免费视频 | 亚洲视频在线看 | 暖暖视频免费观看视频中国.韩剧 | 亚拍一区| 国产青草视频在线观看免费影院 | 国产欧美日韩综合 |