距离上次写博客已经有一段时间了,想到有很多技术点比较散又容易忘记,所以决定写点博客把这些都记下来
主要功能: 实现单属性,自定义对象和Map的null值校验处理
注意事项: 如果是SpringBoot 1.5的版本需要在pom文件加一下配置
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.3</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
1.主要类: 主要有两个类 一个是AOP类 另外一个是自定义注解
AOP类防止表单验证类
package com.example.auctionapp.aop;
import com.example.auctionapp.annotation.ObjectNotNull;
import com.example.auctionapp.core.Result;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import javax.validation.constraints.NotNull;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.HashMap;
import java.util.Map;
/**
* Controller防空校验
*
* @author 安能
* @version 1.0.7
* @date 2019年7月29日10:59:33
*/
@Aspect
@Component
@Slf4j
public class VerifyAspect {
/**
* 使用@Pointcut定义一个切入点,可以是一个规则表达式,比如下例中某个package下的所有函数,也可以是一个注解等。
* public表示访问权限是公有方法,第一个*表示返回类型,第二 *表示类名,第三个*表示方法(..)表示任何参数,包含子包
*/
@Pointcut("execution(public * com.example.auctionapp.controller.*.*(..))")
public void webLog() {
}
/**
* 环绕通知,环绕增强,相当于MethodInterceptor
*
* @param point
* @return
*/
@Around("webLog()")
public Result doAround(ProceedingJoinPoint point) throws Throwable {
Result result;
Class<?> targetClass = point.getTarget().getClass();
String methodName = point.getSignature().getName();
Object[] args = point.getArgs();
Map<String, String> dataMap = new HashMap<>(16);
for (Method method : targetClass.getMethods()) {
if (methodName.equals(method.getName())) {
Parameter[] parameters = method.getParameters();
for (int i = 0; i < parameters.length; i++) {
Class<?> aClass = parameters[i].getType();
ClassLoader classLoader = aClass.getClassLoader();
if (classLoader != null) {
boolean isObjectNotNull = parameters[i].isAnnotationPresent(ObjectNotNull.class);
if (isObjectNotNull) {
ObjectNotNull annotation = parameters[i].getAnnotation(ObjectNotNull.class);
String[] value = annotation.value();
Field[] fields = aClass.getDeclaredFields();
for (String v : value) {
for (Field field : fields) {
field.setAccessible(true);
if (v.equals(field.getName())) {
if (field.get(args[i]) == null) {
dataMap.put(field.getName(),"不能为空!");
}
}
}
}
}
// 非自定义类
} else {
boolean isObjectNotNull = parameters[i].isAnnotationPresent(ObjectNotNull.class);
if (isObjectNotNull) {
ObjectNotNull annotation = parameters[i].getAnnotation(ObjectNotNull.class);
String[] values = annotation.value();
if (args[i] instanceof Map) {
for (String value : values) {
Map map = (Map) args[i];
if (null == map.get(value)) {
dataMap.put(value,"不能为空!");
}
}
}
}
boolean isNotNull = parameters[i].isAnnotationPresent(NotNull.class);
if (isNotNull) {
if (args[i] == null) {
dataMap.put(parameters[i].getName(),"不能为空!");
}
}
}
}
}
}
if (dataMap.size() > 0) {
return Result.success(
dataMap);
}
result = (Result) point.proceed();
return result;
}
}
自定义注解类
package com.example.auctionapp.annotation;
import java.lang.annotation.*;
/**
* 防对象空注解,value为字符串数组,每个字符串对应类中的每个字段
*
* @author 安能
* @date 2019年7月30日13:24:25
*/
@Target({ElementType.METHOD, ElementType.FIELD, ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ObjectNotNull {
/**
* 字符串数组,每个字符串对应类中的每个字段
*
* @return 防空数组
*/
String[] value() default "";
}
2.返回结果类: result可以自由设置统一返回封装类
返回结果不演示过多没有什么意义,仅供参考!
package com.ms.auction.utils.respons;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
/**
* 统一API响应结果封装
* 不要单独使用Result会编译出错,使用ResultBuilder方法调用 Result为返回
*
* @author 安能
* @date 2019年6月24日10:56:38
*/
@Builder(access = AccessLevel.MODULE)
@EqualsAndHashCode()
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Getter
@ApiModel(value = "Result对象", description = "统一响应")
public final class Result<T> {
/**
* 状态码
*/
@ApiModelProperty(value = "状态码")
private int code;
/**
* 响应消息
*/
@ApiModelProperty(value = "响应消息")
private String message;
/**
* 响应数据
*/
@ApiModelProperty(value = "响应数据")
private T data;
}
3.controller演示类
可以防止单属性,自定义对象和Map类的为空校验
package com.example.auctionapp.controller;
import com.example.auctionapp.annotation.ObjectNotNull;
import com.example.auctionapp.annotation.WebLog;
import com.example.auctionapp.core.Result;
import com.example.auctionapp.core.ResultGenerator;
import com.example.auctionapp.entity.Account;
import com.example.auctionapp.service.IAccountService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.Map;
/**
* <p>
* 账户 前端控制器
* </p>
*
* @author 安能
* @since 2019-05-06
*/
@RestController
@RequestMapping("/account")
@Slf4j
public class AccountController {
@Resource
IAccountService accountService;
@GetMapping("u")
public Result updatePayPassword(@NotNull String name, @ObjectNotNull({"type","password"}) Account account,
@ObjectNotNull({"age","a"}) @RequestParam(required = false) Map map) {
return Result.errorInfo("123");
}
4.使用postMan效果演示
1. 正常不缺参数情况下
2. 缺少单属性参数
3.缺少自定义对象属性
4. 缺少Map属性
看到这里的同学也应该体验到了乐趣,代码写的有粗糙没有结构的,有兴趣的话可以优化一下
不懂的同学欢迎留言评论