mikilin 结合spring项目
以下内容可忽略,该功能已经放入到mikilin框架中
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