最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

spring boot+自定義 AOP 實(shí)現(xiàn)全局校驗(yàn)的實(shí)例代碼

 更新時(shí)間:2019年04月09日 16:07:06   作者:吃桃子的小松鼠  
最近公司重構(gòu)項(xiàng)目,重構(gòu)為最熱的微服務(wù)框架 spring boot, 重構(gòu)的時(shí)候遇到幾個(gè)可以統(tǒng)一處理的問(wèn)題。這篇文章主要介紹了spring boot+自定義 AOP 實(shí)現(xiàn)全局校驗(yàn) ,需要的朋友可以參考下

最近公司重構(gòu)項(xiàng)目,重構(gòu)為最熱的微服務(wù)框架 spring boot, 重構(gòu)的時(shí)候遇到幾個(gè)可以統(tǒng)一處理的問(wèn)題,也是項(xiàng)目中經(jīng)常遇到,列如:統(tǒng)一校驗(yàn)參數(shù),統(tǒng)一捕獲異常。。。

僅憑代碼 去控制參數(shù)的校驗(yàn),有時(shí)候是冗余的,但通過(guò)框架支持的 去控制參數(shù)的校驗(yàn),是對(duì)于開發(fā)者很友好,先看下面的例子

 @NotEmpty(message="手機(jī)號(hào)不能為空")
   @Size(min=11,max=11,message="手機(jī)號(hào)碼長(zhǎng)度不正確")
   @Pattern(regexp=StringUtils.REGEXP_MOBILE,message="手機(jī)號(hào)格式不正確")
  private String mobile;

這是spring boot支持的 校驗(yàn)注解,然后我們?cè)?contoller層 加上@Valid 注解 就可以達(dá)到校驗(yàn)的目的。這是一種框架自帶的

本章 就展示一種 自定義的 AOP 校驗(yàn),首先 寫一個(gè)注解,注解里面可以寫上 我們需要校驗(yàn)的規(guī)則, 比如長(zhǎng)度,正則。。。

@Documented
@Target({ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidateParam {
  int min() default 0;
  int max() default Integer.MAX_VALUE;
  String message() default "params is not null";
  String regexp();
  Class<?>[] groups() default { };
   Class<? extends Payload>[] payload() default { };
   boolean isNotNull() default true;
}

然后定義一個(gè)AOP類

package com.onecard.primecard.common.aop;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.regex.Pattern;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
import com.jfcf.core.dto.ResultData;
import com.onecard.core.support.util.StringUtils;
import com.onecard.primecard.common.annotation.ValidateParam;
import com.onecard.primecard.common.utils.ResultDataUtil;
/**
 * 全局 切面類(校驗(yàn)參數(shù))
 * 
 * @author Administrator
 *
 */
@Aspect
@Component
public class GobalHandlerAspect {
  private static Logger logger = LoggerFactory.getLogger(GobalHandlerAspect.class);
  @Pointcut("execution(* 包名.controller..*.*(..)) && execution(* 包名.controller..*.*(..))")
  public void checkAspect(){};
  @Before("checkAspect()")
  public void befor(JoinPoint joinPoint) throws Exception{
    //前置統(tǒng)一輸出參數(shù)
    Object[] args = joinPoint.getArgs();
    if(args != null && args.length>0){
      Object obj = args[0];
      ParameterizedType pt = (ParameterizedType)obj.getClass().getGenericSuperclass();
      Class<?> classzz = (Class<?>) pt.getActualTypeArguments()[0];
      logger.info("【小X卡】-【請(qǐng)求實(shí)體入?yún)ⅰ浚?+classzz.newInstance().toString());
    }
  }
  @Around("checkAspect()")
  public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
    //校驗(yàn)參數(shù)
    Object[] args = joinPoint.getArgs();
    Object obj = null;
    if(args != null && args.length > 0){
      obj = args[0];
      Class classzz = obj.getClass();
      //沒有順序和秩序的數(shù)組
      Field[] fieldArray = classzz.getDeclaredFields();
      ArrayList<Field> fieldList = new ArrayList<Field>(Arrays.asList(fieldArray));
      String res = checkParam(fieldList,obj);
      if(StringUtils.isNotNull(res)){
        return ResultDataUtil.result(ResultData.STATUS_PARAM_ERROR, res);
      }
    }
    return joinPoint.proceed();
  }
  private String checkParam(ArrayList<Field> fieldList, Object obj) throws Exception {
    for(Field field : fieldList){
      ValidateParam validateParam = field.getAnnotation(ValidateParam.class);
      logger.info("【小X卡】獲取注解值:"+validateParam.isNotNull()+"min="+validateParam.min()+"max="+validateParam.max());
      Method method = obj.getClass().getMethod("get"+getMethodName(field.getName()));
      logger.info("【小X卡】入?yún)?shí)體方法名稱:"+method.getName());
      if(method != null){
        Object val = method.invoke(obj);
        logger.info("【小x卡】回調(diào)方法:"+val);
        if(validateParam != null && validateParam.isNotNull() == true){
          if(null == val || "".equals(val) ){
            return field.getName()+"必填參數(shù)為空";
          }
        }
        if(validateParam.min()==11 && validateParam.max() == 11){
          if(val.toString().length() != 11){
            return field.getName()+"請(qǐng)輸入?yún)?shù)正確的長(zhǎng)度";
          }
        }
        if(validateParam.regexp().equals(StringUtils.REGEXP_MOBILE)){
          if(!Pattern.matches(StringUtils.REGEXP_MOBILE, val.toString())){
            return field.getName()+"參數(shù)格式錯(cuò)誤";
          }
        }
      }
    }
    return null;
  }
   /**
   * 方法首字母大寫
   * @param fieldName
   * @return
   */
  private String getMethodName(String fieldName) {
    StringBuffer buffer = new StringBuffer();
    String firstLetter = fieldName.substring(0, 1).toUpperCase();
    return buffer.append(firstLetter).append(fieldName.substring(1, fieldName.length())).toString();
  }    
 }

定義一個(gè)切點(diǎn) @Pointcut, 用execution 表達(dá)式,去獲取要校驗(yàn)的 某個(gè)類 和某個(gè)方法, 也就是連接點(diǎn),然后 用定義一個(gè)通知,上面代碼中有2個(gè)通知,一個(gè)前置通知@Before,一個(gè)環(huán)繞通知@Around,我們使用功能最強(qiáng)大的環(huán)繞通知。

通過(guò)上面的代碼可以看出  首先獲取參數(shù),然后通過(guò)反射機(jī)制 獲取 入?yún)?duì)象中的全部字段, 再去獲取 我們?cè)谧侄沃屑?我們自定義注解的字段,通過(guò)反射方法的回調(diào),獲取字段值,對(duì)值做判斷, 返回校驗(yàn)結(jié)果。

總結(jié)

以上所述是小編給大家介紹的spring boot+自定義 AOP 實(shí)現(xiàn)全局校驗(yàn)的實(shí)例代碼,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的!

相關(guān)文章

  • Spring中ThreadLocal的解析

    Spring中ThreadLocal的解析

    這篇文章主要介紹了Spring中ThreadLocal的解析,Spring通過(guò)各種DAO模板類降低了開發(fā)者使用各種數(shù)據(jù)持久技術(shù)的難度。這些模板類都是線程安全的,也就是說(shuō),多個(gè)DAO可以復(fù)用同一個(gè)模板實(shí)例而不會(huì)發(fā)生沖突,下面一起進(jìn)入文章學(xué)子詳細(xì)內(nèi)容吧
    2022-01-01
  • java實(shí)現(xiàn)udp通訊的代碼

    java實(shí)現(xiàn)udp通訊的代碼

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)udp通訊的代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • Spring零基礎(chǔ)到進(jìn)階之鴻蒙開篇

    Spring零基礎(chǔ)到進(jìn)階之鴻蒙開篇

    Spring框架是一個(gè)開放源代碼的J2EE應(yīng)用程序框架,由Rod Johnson發(fā)起,是針對(duì)bean的生命周期進(jìn)行管理的輕量級(jí)容器(lightweight container)。 Spring解決了開發(fā)者在J2EE開發(fā)中遇到的許多常見的問(wèn)題,提供了功能強(qiáng)大IOC、AOP及Web MVC等功能
    2022-07-07
  • @RequestParam 接收參數(shù)的值為null的處理方式

    @RequestParam 接收參數(shù)的值為null的處理方式

    這篇文章主要介紹了@RequestParam 接收參數(shù)的值為null的處理方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java中seata框架的XA模式詳解

    Java中seata框架的XA模式詳解

    這篇文章主要介紹了Java中seata框架的XA模式詳解,Seata?是一款開源的分布式事務(wù)解決方案,致力于提供高性能和簡(jiǎn)單易用的分布式事務(wù)服務(wù),Seata?將為用戶提供了?AT、TCC、SAGA?和?XA?事務(wù)模式,為用戶打造一站式的分布式解決方案,需要的朋友可以參考下
    2023-08-08
  • 使用Feign調(diào)用注解組件(實(shí)現(xiàn)字段賦值功能)

    使用Feign調(diào)用注解組件(實(shí)現(xiàn)字段賦值功能)

    這篇文章主要介紹了使用Feign調(diào)用注解組件(實(shí)現(xiàn)字段賦值功能),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • Java 畫時(shí)鐘遇到的問(wèn)題及解決方案

    Java 畫時(shí)鐘遇到的問(wèn)題及解決方案

    我是一個(gè)剛?cè)腴T的小菜鳥,希望我寫的東西可以幫助和我一樣剛?cè)腴T的兄弟們少走一些彎路,也希望大佬們可以多指點(diǎn)指點(diǎn)我。感謝!解決在畫時(shí)鐘遇到的問(wèn)題讓我花費(fèi)不少時(shí)間...說(shuō)兩個(gè)困擾我比較久的
    2021-11-11
  • IntelliJ IDEA 2019.1.1 for MAC 下載和注冊(cè)碼激活教程圖解

    IntelliJ IDEA 2019.1.1 for MAC 下載和注

    這篇文章主要介紹了IntelliJ IDEA 2019.1.1 for MAC 下載和注冊(cè)碼激活,教程,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-04-04
  • 新手學(xué)習(xí)Java對(duì)Redis簡(jiǎn)單操作

    新手學(xué)習(xí)Java對(duì)Redis簡(jiǎn)單操作

    這篇文章主要介紹了新手學(xué)習(xí)Java對(duì)Redis簡(jiǎn)單操作,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Spring Boot使用Servlet及Filter過(guò)程詳解

    Spring Boot使用Servlet及Filter過(guò)程詳解

    這篇文章主要介紹了Spring Boot使用Servlet及Filter過(guò)程詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07

最新評(píng)論

明水县| 鄂伦春自治旗| 乌鲁木齐县| 宕昌县| 怀来县| 五家渠市| 中山市| 淮安市| 米易县| 镇原县| 临安市| 东乡族自治县| 湖南省| 孟连| 新绛县| 泾阳县| 永仁县| 赞皇县| 五家渠市| 汉沽区| 长武县| 自贡市| 连州市| 哈尔滨市| 荆州市| 常山县| 安多县| 东明县| 桐柏县| 五原县| 桂林市| 司法| 万山特区| 常德市| 怀柔区| 凤凰县| 格尔木市| 扎赉特旗| 满洲里市| 冷水江市| 苗栗县|