搜尋

首頁  >  問答  >  主體

java 方法参数怎么优雅校验?

怪我咯怪我咯2769 天前977

全部回覆(5)我來回復

  • 阿神

    阿神2017-04-18 10:44:41

    謝謝各位的回答,我覺得此篇部落格的方案比較符合我的預期。

    使用SPRING AOP驗證方法參數是否合法

    回覆
    0
  • 怪我咯

    怪我咯2017-04-18 10:44:41

    不邀自來。這個問題,我之前也考慮過,包括異常處理,都是很繁瑣的,不是核心的業務邏輯,但是充斥在程式碼的各個角落,很繁瑣。
    我的解決方案,是透過aop+註解的方式,無侵入式的解決。
    1.第一步聲明自訂註解類別

    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    public @interface RequestRequire {
        
        /**
         * 请求当前接口所需要的参数,多个以小写的逗号隔开
         * @return
         */
        public String require() default "";
        
        /**
        *传递参数的对象类型
        */
        public Class<?> parameter() default Object.class;
    }

    2.對需要做非空判斷的方法做註解配置(我一般用在controller)

    @RequestMapping(value = "/register", method = RequestMethod.POST)
    @RequestRequire(require="mobile,sessionToken",parameter=AccountRequestParameter.class)
    public void register(HttpServletRequest request,
                HttpServletResponse response,HttpRequestParameter parameter)throws Exception{
            //核心代码
    }

    AccountRequestParameter類是一個參數類,裡麵包含了帳號模組的所有參數。

    3.編寫切面類

    @Aspect
    @Component
    public class RequestRequireAspect {
    
        Logger log=LoggerFactory.getLogger(RequestRequireAspect.class);
        
    
        public RequestRequireAspect() {
            log.info("初始化接口参数非空判断切面类...");
        }
        
        @Pointcut("@annotation(com.xxxx.RequestRequire)")
        public void controllerInteceptor() {
        }
    
        @Around("controllerInteceptor()")
        public Object around(ProceedingJoinPoint pjp) throws Throwable {
            
            //获取注解的方法参数列表
            Object[] args = pjp.getArgs();
            
            //获取被注解的方法
            MethodInvocationProceedingJoinPoint mjp = (MethodInvocationProceedingJoinPoint) pjp;
            MethodSignature signature = (MethodSignature) mjp.getSignature();
            Method method = signature.getMethod();
            
            //获取方法上的注解
            RequestRequire require = method.getAnnotation(RequestRequire.class);
            
            //以防万一,将中文的逗号替换成英文的逗号
            String fieldNames=require.require().replace(",", ",");
            
            //从参数列表中获取参数对象
            Object parameter=null;
            for(Object pa:args){
                //class相等表示是同一个对象
                if (pa.getClass()==require.parameter() ) {
                    parameter=pa;
                }
            }
            
            //通过反射去和指定的属性值判断是否非空
            Class cl=parameter.getClass();
            for(String fieldName:fieldNames.split(",")){
                
                //根据属性名获取属性对象
                Field f=cl.getField(fieldName);
                
                //设置可读写权限
                f.setAccessible(true);
                
                //获取参数值,因为我的参数都是String型所以直接强转
                String value=(String)f.get(parameter);
                
                //非空判断
                if(!StringUtils.isNotBlank(value)){
                    throw RuntimeException("参数:"+fieldName+"不允许为空");
                }
            }
            
            //如果没有报错,放行
            return pjp.proceed();
        }
    }
    1. 最後在springmvc裡面配置

        <aop:aspectj-autoproxy proxy-target-class="true"/>  

    5.最後,你那個方法需要做非空判斷,你就愉快的加上註解吧,不想就把註解移除,非侵入式,可插拔,封裝好了,以後項目都可以直接拿來用。

    回覆
    0
  • 怪我咯

    怪我咯2017-04-18 10:44:41

    Lombok @NonNull
    用法可以看這篇文章

    回覆
    0
  • ringa_lee

    ringa_lee2017-04-18 10:44:41

    優雅的驗證框架那麼多,為何不google一下。

    回覆
    0
  • 黄舟

    黄舟2017-04-18 10:44:41

    自己寫註解,為什麼不試試validation呢?寫個公共的校驗類別就好了。

    回覆
    0
  • 取消回覆