项目中需要用到url后面拼接参数,post中批量传参的场景
所以就有了如下的实现方案:
@RequestParam和@RequestBody两个注解同时使用,看到网上有人说尽量不要这么使用,我还没去探究为什么。
@Data
public class Request {
/**
* 纬度
*/
@NotNull(message = "latitude不能为空")
private Double latitude;
/**
* 经度
*/
@NotNull(message = "longitude不能为空")
private Double longitude;
/**
* 区分每个坐标的id
*/
@NotNull(message = "coordinateId不能为空")
private String coordinateId;
/**
* 坐标体系,支持wgs84ll、gcj02ll,默认wgs84ll
*/
@EnumValid(target = CoordinateChannel.class, message = "仅支持wgs84ll、gcj02ll坐标体系")
private String coordinateType = "wgs84ll";
}
枚举类:
public enum CoordinateChannel {
WGS84LL(1, "wgs84ll"),
GCJ02LL(2, "gcj02ll");
private String value;
private Integer index;
CoordinateChannel(Integer index, String value) {
this.index = index;
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public Integer getIndex() {
return index;
}
public void setIndex(Integer index) {
this.index = index;
}
@Override
public String toString() {
return value;
}
}
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy = {EnumValidator.class})
public @interface EnumValid {
String message() default "";
// 作用参考@Validated和@Valid的区别
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
/**
* 目标枚举类
*/
Class<?> target() default Class.class;
/**
* 是否忽略空值
*/
boolean ignoreEmpty() default true;
}
public class EnumValidator implements ConstraintValidator<EnumValid, String> {
// 枚举校验注解
private EnumValid annotation;
@Override
public void initialize(EnumValid constraintAnnotation) {
annotation = constraintAnnotation;
}
@Override
public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext) {
boolean result = false;
Class<?> cls = annotation.target();
boolean ignoreEmpty = annotation.ignoreEmpty();
// target为枚举,并且value有值,或者不忽视空值,才进行校验
if (cls.isEnum() && (value != null || !ignoreEmpty)) {
Object[] objects = cls.getEnumConstants();
for (Object obj : objects) {
// 使用此注解的枚举类需要重写toString方法,改为需要验证的值
if (obj.toString().equals(value)) {
result = true;
break;
}
}
} else {
result = true;
}
return result;
}
}
使用@RequestParam和@RequestBody注解
@RequestMapping("/test")
public Map fenceBatchExit(@RequestParam(value = "tid") String tid,
@RequestParam(value = "code") String code,
@Valid @RequestBody List<Request> requests) {
int size = requests.size();
// 加一个size大小的限定
Map map = new HashMap();
List<Map> searchData = null;
for (Request request: requests) {
// 逻辑处理
map.put(request.getId(), searchData);
}
return map;
}
注意全局捕获ConstraintViolationException异常:捕获上面注解方法中传参错误的情况
注意:下面的代码只是一个模板示例
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
@ExceptionHandler(value = Exception.class)
public ResultModel exceptionHandler(HttpServletRequest request, Exception e) {
ResultModel resultModel = new ResultModel();
log.error("GlobalExceptionHandler exceptionHandler e->{}", e.getMessage());
try {
if (e instanceof ConstraintViolationException){
resultModel.setMsg(e.getMessage());
resultModel.setRet(******);
} else {
resultModel.setMsg(*****);
resultModel.setRet(*****);
}
} catch (Exception ex) {
logger.error("GlobalExceptionHandler exceptionHandler ex{}", ex);
} finally {
MDC.clear();
}
return resultModel;
}
}
下面请求方法新手可看,大佬可以移步了: