mikilin 結合spring項目

mikilin 結合spring項目

mikilin框架相當於一個工具類覈查的框架,如果要放在項目中,作爲Controller層作爲基本的核查層,那麼可以這麼做(由於mikilin暫時還沒有跟spring項目做適配,自己使用的時候,可以參考如下這樣寫)

一、新增自動覈查註解

可以修飾類,函數,以及Controller中的參數

import java.lang.annotation.*;

/**
 * 修飾函數和參數,用於屬性的核查
 *
 * <p>
 *     <ul>
 *         <li>1.修飾類:則會覈查類下面所有函數的所有參數</li>
 *         <li>2.修飾函數:則會覈查函數對應的所有參數</li>
 *         <li>3.修飾參數:則只會覈查指定的參數</li>
 *     </ul>
 * @author robot
 */
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER})
public @interface AutoCheck {

    /**
     * 分組
     */
    String group() default "_default_";
}

二、aop解析覈查

下面代碼直接拷貝即可,但是有些地方有道了自己的框架Neo,可以自己替換掉,其中NeoMap就是個普通的Map<String, Object>對象,其中的TimeRangeStrUrl是一個時間轉換爲中文的計算工具,如果不想使用Neo框架的話我會列在其他文件中

@Slf4j
@Aspect
@Component
public class ControllerAop {

    /**
     * 攔截方法中添加註解{@link EnableAopLog}的方法
     */
    @Around("@annotation(com.isyscore.walle.admin.aop.EnableAopLog)")
    public Object aroundEnableLog(ProceedingJoinPoint pjp) throws Throwable {
        Method currentMethod = getMethod(pjp);
        EnableAopLog enableAopLog = currentMethod.getDeclaredAnnotation(EnableAopLog.class);
        long start = System.currentTimeMillis();
        NeoMap outInfo = NeoMap.of();
        // 函數名字
        String funStr = pjp.getSignature().toLongString();
        outInfo.put("fun", funStr);

        // 參數的值
        outInfo.put("parameters", getParameters(pjp));
        Object result = null;
        try {
            result = pjp.proceed();
            outInfo.put("result", result);
        } catch (Exception e) {
            outInfo.put("timeout", TimeRangeStrUtil.parseTime(System.currentTimeMillis() - start));
            log.error(JSON.toJSONString(outInfo), e);
            return result;
        }

        outInfo.put("timeout", TimeRangeStrUtil.parseTime(System.currentTimeMillis() - start));
        if (enableAopLog.enable()) {
            log.info(JSON.toJSONString(outInfo));
        }
        return result;
    }

    /**
     * 攔截controller中所有的方法
     */
    @Around("execution(* com.isyscore.walle.admin.web.controller.*.*(..))")
    public Object aroundParameter(ProceedingJoinPoint pjp) {
        long start = System.currentTimeMillis();
        String funStr = pjp.getSignature().toLongString();
        Object result;
        Method currentMethod = getMethod(pjp);
        try {
            validate(pjp);
            result = pjp.proceed();
        } catch (Throwable e) {
            NeoMap outInfo = NeoMap.of();
            outInfo.put("fun", funStr);
            outInfo.put("parameters", getParameters(pjp));
            outInfo.put("timeout", TimeRangeStrUtil.parseTime(System.currentTimeMillis() - start));
            outInfo.put("errMsg", e.getMessage());
            log.error("後端異常:" + outInfo.toString(), e);
            Class<?> returnClass = currentMethod.getReturnType();
            if (e instanceof BusinessException) {
                if (Response.class.isAssignableFrom(returnClass)) {
                    BusinessException businessException = (BusinessException) e;
                    return Response.fail(businessException.getErrCode(), businessException.getMessage());
                } else {
                    return null;
                }
            } else {
                if (Response.class.isAssignableFrom(returnClass)) {
                    return Response.fail(HttpStatus.INTERNAL_SERVER_ERROR.toString(), e.getMessage());
                } else {
                    return null;
                }
            }
        }
        return result;
    }

    private List<Object> getParameters(ProceedingJoinPoint pjp) {
        List<Object> parameters = new ArrayList<>();
        Object[] args = pjp.getArgs();
        for (Object arg : args) {
            if (arg instanceof ServletRequest || arg instanceof ServletResponse || arg instanceof MultipartFile) {
                continue;
            }
            parameters.add(arg);
        }
        return parameters;
    }

    @SuppressWarnings("all")
    private void validate(ProceedingJoinPoint pjp) {
        Signature sig = pjp.getSignature();
        MethodSignature methodSignature;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("該註解只能用於方法");
        }
        methodSignature = (MethodSignature) sig;
        Method currentMethod;
        try {
            currentMethod = pjp.getTarget().getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
        } catch (NoSuchMethodException e) {
            throw new BusinessException(e);
        }

        if (currentMethod.getDeclaringClass().isAnnotationPresent(AutoCheck.class)) {
            doValidate(pjp);
        } else if (currentMethod.isAnnotationPresent(AutoCheck.class)) {
            doValidate(pjp);
        } else {
            Parameter[] parameters = currentMethod.getParameters();
            Object[] args = pjp.getArgs();
            for (int index = 0; index < args.length; index++) {
                if (args[index] instanceof ServletRequest || args[index] instanceof ServletResponse || args[index] instanceof MultipartFile) {
                    continue;
                }

                if (parameters[index].isAnnotationPresent(AutoCheck.class)) {
                    try {
                        MkValidators.validate(args[index]);
                    } catch (MkCheckException e) {
                        throw new BusinessException(HttpStatus.INTERNAL_SERVER_ERROR.toString(), "參數覈查異常:" + MkValidators.getErrMsg());
                    }
                }
            }
        }
    }

    @SuppressWarnings("all")
    private void doValidate(ProceedingJoinPoint pjp) {
        Object[] parameters = pjp.getArgs();
        for (Object parameter : parameters) {
            try {
                MkValidators.validate(parameter);
            } catch (MkCheckException e) {
                String checkErr = "參數覈查異常:" + MkValidators.getErrMsg();
                throw new BusinessException(HttpStatus.INTERNAL_SERVER_ERROR.toString(), checkErr);
            }
        }
    }

    private Method getMethod(ProceedingJoinPoint pjp) {
        Signature sig = pjp.getSignature();
        MethodSignature methodSignature;
        if (!(sig instanceof MethodSignature)) {
            throw new IllegalArgumentException("該註解只能用於方法");
        }
        methodSignature = (MethodSignature) sig;
        Method currentMethod;
        try {
            currentMethod = pjp.getTarget().getClass().getMethod(methodSignature.getName(), methodSignature.getParameterTypes());
        } catch (NoSuchMethodException e) {
            throw new BusinessException(e);
        }
        return currentMethod;
    }
}

三、Controller使用

1.修飾類

@AutoCheck
@RequestMapping("walle/maven/config")
@RestController
public class MavenConfigController extends BaseResponseController {

    @Autowired
    private MavenConfigService mavenConfigservice;

    /**
     * 新增maven依賴項
     */
    @PostMapping("insertMavenItem")
    public Response<Integer> insertMavenItem(@RequestBody MavenItemInsertReq mavenItemInsertReq) {
        return success(mavenConfigservice.insertMavenItem(mavenItemInsertReq));
    }
}

則該類中的任何方法對應的參數都會被覈查,比如上面的參數類型MavenItemInsertReq該類型的核查就是直接採用Mikilin的註解即可

2.修飾方法

則只有該方法會覈查,其他的不會

@RequestMapping("walle/maven/config")
@RestController
public class MavenConfigController extends BaseResponseController {

    @Autowired
    private MavenConfigService mavenConfigservice;

    /**
     * 新增maven依賴項
     */
    @AutoCheck
    @PostMapping("insertMavenItem")
    public Response<Integer> insertMavenItem(@RequestBody MavenItemInsertReq mavenItemInsertReq) {
        return success(mavenConfigservice.insertMavenItem(mavenItemInsertReq));
    }
}

3.修飾參數

@RequestMapping("walle/maven/config")
@RestController
public class MavenConfigController extends BaseResponseController {

    @Autowired
    private MavenConfigService mavenConfigservice;

    /**
     * 新增maven依賴項
     */
    @PostMapping("insertMavenItem")
    public Response<Integer> insertMavenItem(@AutoCheck @RequestBody MavenItemInsertReq mavenItemInsertReq) {
        return success(mavenConfigservice.insertMavenItem(mavenItemInsertReq));
    }
}

具體的核查方式見Mikilin文檔
簡書:https://www.jianshu.com/p/e7f212afa578
語雀:https://www.yuque.com/simonalong/mikilin/mduu3z
其中TimeRangeStrUtl工具類,見這裏:https://www.jianshu.com/p/67b189caab9f

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章