亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Spring boot通過(guò)切面,實(shí)現(xiàn)超靈活的注解式數(shù)據(jù)校驗(yàn)過(guò)程

 更新時(shí)間:2021年12月02日 10:46:55   作者:Balalalalalalalala  
這篇文章主要介紹了Spring boot通過(guò)切面,實(shí)現(xiàn)超靈活的注解式數(shù)據(jù)校驗(yàn)過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

通過(guò)切面,實(shí)現(xiàn)超靈活的注解式數(shù)據(jù)校驗(yàn)

在企業(yè)系統(tǒng)的開發(fā)中,用戶表單輸入的場(chǎng)景是會(huì)經(jīng)常遇見的,如何讓數(shù)據(jù)校驗(yàn)脫離于業(yè)務(wù)代碼邏輯,誰(shuí)也不想在邏輯代碼里對(duì)字段逐一判斷。。。。

Spring MVC的校驗(yàn)方式

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

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

然后將User對(duì)象作為Controller的參數(shù),交給Spring MVC去幫你校驗(yàn)。

通過(guò)切面實(shí)現(xiàn)自己的注解式數(shù)據(jù)校驗(yàn)

這是一個(gè)SOA的微服務(wù)應(yīng)用,沒(méi)有controller和Spring MVC,當(dāng)然也沒(méi)有所謂的容器(Tomcat、Jetty),對(duì)于來(lái)自于client的調(diào)用,也要進(jìn)行參數(shù)校驗(yàn)。繼續(xù)基于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的一些知識(shí)點(diǎn),自行去網(wǎng)上google吧。我直接上代碼了,誰(shuí)叫我是代碼的搬運(yùn)工。

定義一個(gè)切面:

@Aspect  //一個(gè)切面
@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(){}
    /* * 通過(guò)連接點(diǎn)切入 */
    @Before("soaServiceBefore()")
    public void twiceAsOld1(JoinPoint point) {
        //  獲得切入目標(biāo)對(duì)象
        Object target = point.getThis();
        // 獲得切入方法參數(shù)
        Object [] args = point.getArgs();
        // 獲得切入的方法
        Method method = ((MethodSignature)point.getSignature()).getMethod();
        // 校驗(yàn)以基本數(shù)據(jù)類型 為方法參數(shù)的
        Set<ConstraintViolation<Object>> validResult = validMethodParams(target, method, args);
        Iterator<ConstraintViolation<Object>> violationIterator = validResult.iterator();
        while (violationIterator.hasNext()) {
            // 此處可以拋個(gè)異常提示用戶參數(shù)輸入格式不正確
            System.out.println("method check---------" + violationIterator.next().getMessage());
        }
        // 校驗(yàn)以java bean對(duì)象 為方法參數(shù)的 
        for (Object bean : args) {
            if (null != bean) {
                validResult = validBeanParams(bean);
                violationIterator = validResult.iterator();
                while (violationIterator.hasNext()) {
            // 此處可以拋個(gè)異常提示用戶參數(shù)輸入格式不正確
                    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個(gè)字")
    private String desc;
    @NotNull
    @Valid  // 需要加上@Valid注解,不然不會(huì)校驗(yàn)到Img對(duì)象
    private List<Img> imgList;
    @NotNull(message = "length不能為null")
    @Range(min = 3, max = 100, message = "長(zhǎng)度范圍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
}

運(yùn)行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);
    }

運(yùn)行結(jié)果:

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個(gè)字

這樣比Spring MVC的校驗(yàn)功能還強(qiáng)大了,

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

經(jīng)過(guò)一番改造后,啥都支持了。而且獨(dú)立于業(yè)務(wù)邏輯,維護(hù)和新增校驗(yàn)都很方便,代碼量也變少了!

Spring boot aop注解數(shù)據(jù)權(quán)限校驗(yàn)

注解類

@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();
                }
            }
        }
    }
}

使用

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

相關(guān)文章

  • java序列化對(duì)象根據(jù)不同配置動(dòng)態(tài)改變屬性名的方法

    java序列化對(duì)象根據(jù)不同配置動(dòng)態(tài)改變屬性名的方法

    本文主要介紹了java序列化對(duì)象根據(jù)不同配置動(dòng)態(tài)改變屬性名的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • springmvc整合freemarker配置的詳細(xì)步驟

    springmvc整合freemarker配置的詳細(xì)步驟

    本篇文章主要介紹了springmvc整合freemarker的詳細(xì)步驟,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • java 中歸并排序算法詳解

    java 中歸并排序算法詳解

    這篇文章主要介紹了java 中歸并排序算法詳解的相關(guān)資料,歸并排序算法又稱為合并排序算法,是一種時(shí)間復(fù)雜度為O(N logN)的排序算法,因而其在平常生活工作中應(yīng)用非常廣泛,需要的朋友可以參考下
    2017-09-09
  • Intellij idea下使用不同tomcat編譯maven項(xiàng)目的服務(wù)器路徑方法詳解

    Intellij idea下使用不同tomcat編譯maven項(xiàng)目的服務(wù)器路徑方法詳解

    今天小編就為大家分享一篇關(guān)于Intellij idea下使用不同tomcat編譯maven項(xiàng)目的服務(wù)器路徑方法詳解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-02-02
  • HashMap vs TreeMap vs Hashtable vs LinkedHashMap

    HashMap vs TreeMap vs Hashtable vs LinkedHashMap

    這篇文章主要介紹了HashMap vs TreeMap vs Hashtable vs LinkedHashMap的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-07-07
  • SpringBoot實(shí)現(xiàn)發(fā)送郵件功能

    SpringBoot實(shí)現(xiàn)發(fā)送郵件功能

    這篇文章主要介紹了SpringBoot 發(fā)送郵件功能實(shí)現(xiàn),本文以163郵箱為例通過(guò)這個(gè)小案例給大家介紹,需要的朋友可以參考下
    2019-12-12
  • Java基礎(chǔ)學(xué)習(xí)之字符緩沖流的應(yīng)用

    Java基礎(chǔ)學(xué)習(xí)之字符緩沖流的應(yīng)用

    這篇文章主要為大家詳細(xì)介紹了Java基礎(chǔ)中的字符緩沖流的相關(guān)應(yīng)用,例如復(fù)制Java文件等,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一
    2022-09-09
  • 淺析Spring boot 中 logback 配置<springProperty> 讀取application.properties 中的屬性

    淺析Spring boot 中 logback 配置<springPropert

    這篇文章主要介紹了淺析Spring boot 中 logback 配置<springProperty> 讀取application.properties 中的屬性,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-02-02
  • 詳解J2EE開發(fā)的網(wǎng)站部署到阿里云服務(wù)器的方法

    詳解J2EE開發(fā)的網(wǎng)站部署到阿里云服務(wù)器的方法

    這篇文章主要介紹了詳解J2EE開發(fā)的網(wǎng)站部署到阿里云服務(wù)器的方法,需要的朋友可以參考下
    2018-01-01
  • JSP常用七大動(dòng)作指令實(shí)例解析

    JSP常用七大動(dòng)作指令實(shí)例解析

    這篇文章主要介紹了JSP常用七大動(dòng)作指令實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-10-10

最新評(píng)論