亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Spring?boot怎么實現超靈活的注解式數據校驗

發布時間:2021-12-02 11:46:17 來源:億速云 閱讀:184 作者:iii 欄目:開發技術

本篇內容主要講解“Spring boot怎么實現超靈活的注解式數據校驗”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Spring boot怎么實現超靈活的注解式數據校驗”吧!

通過切面,實現超靈活的注解式數據校驗

在企業系統的開發中,用戶表單輸入的場景是會經常遇見的,如何讓數據校驗脫離于業務代碼邏輯,誰也不想在邏輯代碼里對字段逐一判斷。。。。

Spring MVC的校驗方式

在使用Spring MVC時的時候,直接使用hibernate-validator的注解,如下:

public class User {
    private Long id;
    @NotBlank(message = "name不能為空")
    @Size(min = 5, max = 10, message = "字符在5到10個")
    private String name;
    private String des;
    @NotNull
    @Max(value = 3, message = "type 參數錯誤")
    @Min(value = 0, message = "type 參數錯誤")
    private Integer type;
    @Min(value = 0, message = "參數錯誤, limit必須大于或等于0")  
    private int limit;
    @Pattern(regexp = "^(true|false)$", message = "參數錯誤, 參數isActive只能是true或者false")
    private String flag;
    // setters and getters

然后將User對象作為Controller的參數,交給Spring MVC去幫你校驗。

通過切面實現自己的注解式數據校驗

這是一個SOA的微服務應用,沒有controller和Spring MVC,當然也沒有所謂的容器(Tomcat、Jetty),對于來自于client的調用,也要進行參數校驗。繼續基于hibernate-validator,

參看validator的官方文檔

引入依賴:

<dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-validator-cdi</artifactId>
   <version>5.4.1.Final</version>
</dependency>
<dependency>
   <groupId>org.glassfish</groupId>
   <artifactId>javax.el</artifactId>
   <version>3.0.1-b08</version>
</dependency>

這里需要引入spring boot和aop的一些知識點,自行去網上google吧。我直接上代碼了,誰叫我是代碼的搬運工。

定義一個切面:

@Aspect  //一個切面
@Configuration  // spring boot 配置類
public class RequestParamValidAspect {
    private final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
    private final ExecutableValidator methodValidator = factory.getValidator().forExecutables();
    private final Validator beanValidator = factory.getValidator();
    private <T> Set<ConstraintViolation<T>> validMethodParams(T obj, Method method, Object [] params){
        return methodValidator.validateParameters(obj, method, params);
    }
    private <T> Set<ConstraintViolation<T>> validBeanParams(T bean) {
        return beanValidator.validate(bean);
    }
    @Pointcut("execution(* com.jiaobuchong.commodity.service.*.*(..))")
    public void soaServiceBefore(){}
    /* * 通過連接點切入 */
    @Before("soaServiceBefore()")
    public void twiceAsOld1(JoinPoint point) {
        //  獲得切入目標對象
        Object target = point.getThis();
        // 獲得切入方法參數
        Object [] args = point.getArgs();
        // 獲得切入的方法
        Method method = ((MethodSignature)point.getSignature()).getMethod();
        // 校驗以基本數據類型 為方法參數的
        Set<ConstraintViolation<Object>> validResult = validMethodParams(target, method, args);
        Iterator<ConstraintViolation<Object>> violationIterator = validResult.iterator();
        while (violationIterator.hasNext()) {
            // 此處可以拋個異常提示用戶參數輸入格式不正確
            System.out.println("method check---------" + violationIterator.next().getMessage());
        }
        // 校驗以java bean對象 為方法參數的 
        for (Object bean : args) {
            if (null != bean) {
                validResult = validBeanParams(bean);
                violationIterator = validResult.iterator();
                while (violationIterator.hasNext()) {
            // 此處可以拋個異常提示用戶參數輸入格式不正確
                    System.out.println("bean check-------" + violationIterator.next().getMessage());
                }
            }
        }
    }
}

具體的Service

// DemoService.java
public interface DemoService {
    void one(@NotNull(message = "不能為null") Integer a, @NotBlank String b);
    void two(@NotNull(message = "paramsVo不能為null") ParamsVo paramsVo,
             @NotNull(message = "go不能為null") String go);
}
// ParamsVo.java
public class ParamsVo {
    @NotBlank(message = "不能為空")
    private String name;
    @NotBlank
    @Length(min = 2, max = 20, message = "不可以為空,最多20個字")
    private String desc;
    @NotNull
    @Valid  // 需要加上@Valid注解,不然不會校驗到Img對象
    private List<Img> imgList;
    @NotNull(message = "length不能為null")
    @Range(min = 3, max = 100, message = "長度范圍3-100")
    private Integer length;
    // omitted other code
}
public class Img {
    @NotNull(message = "img id 不能為null")
    private Long id;
    @NotBlank(message = "img name 不能為空")
    private String name;
    // omitted other code
}

運行DemoService:

@Autowired 
    private DemoService demoService;
    @Test
    public void testGo() {
        demoService.one(null, "");
        ParamsVo paramsVo = new ParamsVo();
        List<Img> list = new ArrayList<>();
        Img img = new Img();
        list.add(img);
        paramsVo.setImgList(list);
        paramsVo.setDesc("你");
        paramsVo.setLength(1);
        demoService.two(paramsVo, null);
    }

運行結果:

method check———不能為空
method check———不能為null
method check———go不能為null
bean check——-img name 不能為空
bean check——-不能為空
bean check——-深度范圍3-100
bean check——-img id 不能為null
bean check——-不可以為空,最多20個字

這樣比Spring MVC的校驗功能還強大了,

// Spring MVC中對下面這樣的校驗是沒有作用的
void one(@NotNull(message = "不能為null") Integer a, @NotBlank String b);

經過一番改造后,啥都支持了。而且獨立于業務邏輯,維護和新增校驗都很方便,代碼量也變少了!

Spring boot aop注解數據權限校驗

注解類

@Retention(RetentionPolicy.RUNTIME)
public @interface DataAuthValid
{    
    //位置
    public int index() default 0;
    
    //字段   id
    //public String id() default "id";
    
    //字段   id
    public String orgId() default "org_id";
    
    //mapper
    @SuppressWarnings("rawtypes")
    public Class<? extends Mapper> mapper();
}

AOP切面

@Aspect
@Component
@Order(1)
public class DataAuthAop { 
    private static String types = "java.lang.String,java.lang.Long,long";    
    @Before("@annotation(dataAuth)")
    public void beforeMethod(JoinPoint point,DataAuthValid dataAuth) throws Exception {
        
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Map<String, Object> payloadMap = (Map<String, Object>) request.getAttribute("payloadMap");
        Long companyid = Long.parseLong(payloadMap.get("companyid")+"");
        if(companyid != 1) {
            Object[] args = point.getArgs();
            Object obj = args[dataAuth.index()];
            String ids = null;
            String typeName = obj.getClass().getTypeName();
            if(types.contains(typeName)) {
                ids = obj + "";
            }else {
                Field[] fields = obj.getClass().getDeclaredFields();
                for (Field f : fields) {
                    f.setAccessible(true);
                    if("id".equals(f.getName())) {
                        Long id = (Long) f.get(obj);
                        ids = id + "";
                    }
                }
            }
            String[] idArr = ids.split(",");
            for (String id : idArr) {
                Class cla = dataAuth.mapper();
                Mapper mapper = (Mapper) SpringBeanFactoryUtils.getApplicationContext().getBean(cla);
                Object object = mapper.selectByPrimaryKey(Long.valueOf(id));
                Field field = obj.getClass().getDeclaredField(dataAuth.orgId());
                field.setAccessible(true);
                Long orgId = (Long)field.get(obj);
                if(!companyid.equals(orgId)) {
                    throw new RuntimeException();
                }
            }
        }
    }
}

使用

Spring?boot怎么實現超靈活的注解式數據校驗

到此,相信大家對“Spring boot怎么實現超靈活的注解式數據校驗”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

石渠县| 静乐县| 临清市| 盘山县| 高密市| 灵山县| 青岛市| 阿图什市| 萨嘎县| 建德市| 汽车| 固镇县| 平武县| 沛县| 萍乡市| 鲁甸县| 安国市| 西青区| 绥芬河市| 兴城市| 岳西县| 西丰县| 霸州市| 石家庄市| 瓦房店市| 顺平县| 科技| 蒙山县| 仪征市| 曲阜市| 都昌县| 桓台县| 墨玉县| 泰兴市| 碌曲县| 兴文县| 清水河县| 高要市| 台东县| 丰城市| 灵台县|