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