public @interface ParamCheck {
boolean notNull() default true;
String defaultValue() default “”;
}
简单描述:
ElementType.PARAMETER 使用于参数
boolean notNull() default true; 要求参数不为空,默认开启,可以自己传
String defaultValue() default “”; 默认值,默认设置 “”,可以自己传
接下来新建 参数校验的AOP实现类,ParamValidAop.java:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@Component
@Aspect
public class ParamValidAop {
@Pointcut(“execution(public * com.bsapple.vshop.controller….(…))”)
public void checkParam() {
}
@Before(“checkParam()”)
public void doBefore(JoinPoint joinPoint) {
}
@Around(“checkParam()”)
public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
MethodSignature signature = ((MethodSignature) pjp.getSignature());
//得到拦截的方法
Method method = signature.getMethod();
//获取方法参数注解,返回二维数组是因为某些参数可能存在多个注解
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations == null || parameterAnnotations.length == 0) {
return pjp.proceed();
}
//获取方法参数名
String[] paramNames = signature.getParameterNames();
//获取参数值
Object[] paranValues = pjp.getArgs();
//获取方法参数类型
Class>[] parameterTypes = method.getParameterTypes();
for (int i = 0; i < parameterAnnotations.length; i++) {
for (int j = 0; j < parameterAnnotations[i].length; j++) {
//如果该参数前面的注解不为空并且是ParamCheck的实例,并且notNull()=true,并且默认值为空,则进行非空校验
if (parameterAnnotations[i][j] != null && parameterAnnotations[i][j] instanceof ParamCheck && ((ParamCheck) parameterAnnotations[i][j]).notNull() && StringUtils.isEmpty(((ParamCheck)parameterAnnotations[i][j]).defaultValue())) {
paramIsNull(paramNames[i], paranValues[i], parameterTypes[i] == null ? null : parameterTypes[i].getName());
break;
}
//如果该参数前面的注解不为空并且是ParamCheck的实例,并且默认值不为空,并且参数值为空,则进行赋默认值
if(parameterAnnotations[i][j] != null && parameterAnnotations[i][j] instanceof ParamCheck && !StringUtils.isEmpty(((ParamCheck)parameterAnnotations[i][j]).defaultValue()) && (paranValues[i] == null || StringUtils.isEmpty(paranValues[i].toString()))){
paranValues[i] = putParam(((ParamCheck)parameterAnnotations[i][j]).defaultValue(), parameterTypes[i]);
}
}
}
return pjp.proceed(paranValues);
}
@AfterReturning(“checkParam()”)
public void doAfterReturning(JoinPoint joinPoint) {
}
private void paramIsNull(String paramName, Object value, String parameterType) {
if (value == null || “”.equals(value.toString().trim())) {
throw new ParamIsNullException(paramName, parameterType,“参数为空”);
}
}
private Object putParam(Object value, Class> parameterType) {
return CastValueTypeUtil.parsevalue(parameterType, value.toString());
}
}
需要注意,这个路径是你准备添加校验的controller的路径,改成你自己的:
然后是校验参数里面使用到的参数转换工具类,CastValueTypeUtil.java:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class CastValueTypeUtil {
public static Object parsevalue(Class> parameterTypes, String value) {
if(value==null || value.trim().length()==0){
return null;
}
value = value.trim();
if (Byte.class.equals(parameterTypes) || Byte.TYPE.equals(parameterTypes)) {
return parseByte(value);
} else if (Boolean.class.equals(parameterTypes) || Boolean.TYPE.equals(parameterTypes)) {
return parseBoolean(value);
} else if (String.class.equals(parameterTypes)) {
return value;
} else if (Short.class.equals(parameterTypes) || Short.TYPE.equals(parameterTypes)) {
return parseShort(value);
} else if (Integer.class.equals(parameterTypes) || Integer.TYPE.equals(parameterTypes)) {
return parseInt(value);
} else if (Long.class.equals(parameterTypes) || Long.TYPE.equals(parameterTypes)) {
return parseLong(value);
} else if (Float.class.equals(parameterTypes) || Float.TYPE.equals(parameterTypes)) {
return parseFloat(value);
} else if (Double.class.equals(parameterTypes) || Double.TYPE.equals(parameterTypes)) {
return parseDouble(value);
} else if (Date.class.equals(parameterTypes)) {
return parseDate(value);
} else {
throw new RuntimeException(“request illeagal type, type must be Integer not int Long not long etc, type=” + parameterTypes);
}
}
public static Byte parseByte(String value) {
try {
value = value.replaceAll(" ", “”);
return Byte.valueOf(value);
} catch(NumberFormatException e) {
throw new RuntimeException(“parseByte but input illegal input=” + value, e);
}
}
public static Boolean parseBoolean(String value) {
value = value.replaceAll(" ", “”);
if (Boolean.TRUE.toString().equalsIgnoreCase(value)) {
return Boolean.TRUE;
} else if (Boolean.FALSE.toString().equalsIgnoreCase(value)) {
return Boolean.FALSE;
} else {
throw new RuntimeException(“parseBoolean but input illegal input=” + value);
}
}
public static Integer parseInt(String value) {
try {
value = value.replaceAll(" ", “”);
return Integer.valueOf(value);
} catch(NumberFormatException e) {
throw new RuntimeException(“parseInt but input illegal input=” + value, e);
}
}
public static Short parseShort(String value) {
try {
value = value.replaceAll(" ", “”);
return Short.valueOf(value);
} catch(NumberFormatException e) {
throw new RuntimeException(“parseShort but input illegal input=” + value, e);
}
}
public static Long parseLong(String value) {
try {
value = value.replaceAll(" ", “”);
return Long.valueOf(value);
} catch(NumberFormatException e) {
throw new RuntimeException(“parseLong but input illegal input=” + value, e);
}
}
public static Float parseFloat(String value) {
try {
value = value.replaceAll(" ", “”);
return Float.valueOf(value);
} catch(NumberFormatException e) {
throw new RuntimeException(“parseFloat but input illegal input=” + value, e);
}
}
public static Double parseDouble(String value) {
try {
value = value.replaceAll(" ", “”);
return Double.valueOf(value);
} catch(NumberFormatException e) {
throw new RuntimeException(“parseDouble but input illegal input=” + value, e);
}
}
public static Date parseDate(String value) {
try {
String datePattern = “yyyy-MM-dd HH:mm:ss”;
SimpleDateFormat dateFormat = new SimpleDateFormat(datePattern);
return dateFormat.parse(value);
} catch(ParseException e) {
throw new RuntimeException(“parseDate but input illegal input=” + value, e);
}
}
}
然后是新建一个自定义异常,专门用于校验参数为空的时候抛出,ParamIsNullException.java:
public class ParamIsNullException extends RuntimeException {
private final String parameterName;
private final String parameterType;
private final String message;
public ParamIsNullException(String parameterName, String parameterType, String message) {
super();
this.parameterName = parameterName;
this.parameterType = parameterType;
this.message = message;
}
@Override
public String getMessage() {
return “请求参数类型:” + this.parameterType + “,参数名: '” + this.parameterName + message;
}
public final String getParameterName() {
return this.parameterName;
}
public final String getParameterType() {
return this.parameterType;
}
}
到这里,其实可以看到自定义注解以及AOP已经实现完毕。
接下来是做一下,统一的返回参以及全局异常捕获,
新建接口baseErrorInfoInterface.java:
public interface baseErrorInfoInterface {
String getResultCode();
String getResultMsg();
}
返回码的枚举类,CommonEnum.java:
public enum CommonEnum implements baseErrorInfoInterface {
// 数据操作错误定义
SUCCESS(“200”, “成功!”),
BODY_NOT_MATCH(“400”, “请求的数据格式不符!”),
SIGNATURE_NOT_MATCH(“401”, “请求的数字签名不匹配!”),
NOT_FOUND(“404”, “未找到该资源!”),
INTERNAL_SERVER_ERROR(“500”, “服务器内部错误!”),
SERVER_BUSY(“503”, “服务器正忙,请稍后再试!”),
REQUEST_METHOD_SUPPORT_ERROR(“40001”,“当前请求方法不支持”);
private String resultCode;
private String resultMsg;
CommonEnum(String resultCode, String resultMsg) {
this.resultCode = resultCode;
this.resultMsg = resultMsg;
}
@Override
public String getResultCode() {
return resultCode;
}
@Override
public String getResultMsg() {
return resultMsg;
}
}
然后是一个简单的返回体专用类,ResultBody.java:
import com.alibaba.fastjson.JSONObject;
public class ResultBody {
private String code;
private String message;
private Object result;
public ResultBody() {
}
public ResultBody(baseErrorInfoInterface errorInfo) {
this.code = errorInfo.getResultCode();
this.message = errorInfo.getResultMsg();
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Object getResult() {
return result;
}
public void setResult(Object result) {
this.result = result;
}
public static ResultBody success() {
return success(null);
}
public static ResultBody success(Object data) {
ResultBody rb = new ResultBody();
rb.setCode(CommonEnum.SUCCESS.getResultCode());
rb.setMessage(CommonEnum.SUCCESS.getResultMsg());
rb.setResult(data);
return rb;
}
public static ResultBody error(baseErrorInfoInterface errorInfo) {
ResultBody rb = new ResultBody();
rb.setCode(errorInfo.getResultCode());
rb.setMessage(errorInfo.getResultMsg());
rb.setResult(null);
return rb;
}
public static ResultBody error(String code, String message) {
ResultBody rb = new ResultBody();
rb.setCode(code);
rb.setMessage(message);
rb.setResult(null);
return rb;
}
public static ResultBody error( String message) {
ResultBody rb = new ResultBody();
rb.setCode("-1");
rb.setMessage(message);
rb.setResult(null);
return rb;
}
@Override
public String toString() {
return JSONObject.toJSonString(this);
}
}
最后是自定义的业务异常类,和全局异常捕获类,
BizException.java
public class BizException extends RuntimeException {
private static final long serialVersionUID = 1L;
protected String errorCode;
protected String errorMsg;
public BizException() {
super();
}
public BizException(baseErrorInfoInterface errorInfoInterface) {
super(errorInfoInterface.getResultCode());
this.errorCode = errorInfoInterface.getResultCode();
this.errorMsg = errorInfoInterface.getResultMsg();
}
public BizException(baseErrorInfoInterface errorInfoInterface, Throwable cause) {
super(errorInfoInterface.getResultCode(), cause);
this.errorCode = errorInfoInterface.getResultCode();
this.errorMsg = errorInfoInterface.getResultMsg();
}
public BizException(String errorMsg) {
super(errorMsg);
this.errorMsg = errorMsg;
}
public BizException(String errorCode, String errorMsg) {
super(errorCode);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public BizException(String errorCode, String errorMsg, Throwable cause) {
super(errorCode, cause);
this.errorCode = errorCode;
this.errorMsg = errorMsg;
}
public String getErrorCode() {
return errorCode;
}
public void setErrorCode(String errorCode) {
this.errorCode = errorCode;
}



