提交 8d4d01f6 作者: 方治民

feat: 优化 Validate Optional 配置和使用方法

上级 d447d298
......@@ -3,11 +3,11 @@ package com.yiring.app.web.example;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckSafe;
import cn.dev33.satoken.annotation.SaIgnore;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.yiring.app.domain.user.UserExtension;
import com.yiring.app.domain.user.UserExtensionRepository;
import com.yiring.app.vo.user.UserExtensionVo;
import com.yiring.auth.annotation.AuthIgnore;
import com.yiring.auth.domain.user.User;
import com.yiring.auth.util.Auths;
import com.yiring.common.core.I18n;
......@@ -17,9 +17,11 @@ import com.yiring.common.exception.BusinessException;
import com.yiring.common.param.PageParam;
import com.yiring.common.util.Commons;
import com.yiring.common.util.FileUtils;
import com.yiring.common.validation.group.Group;
import com.yiring.common.vo.PageVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
......@@ -82,12 +84,12 @@ public class ExampleController {
@ApiOperation(value = "JSON 传参")
@PostMapping("json")
public Result<PageVo<String>> json(@RequestBody @Validated PageParam param) {
public Result<PageVo<String>> json(@RequestBody @Validated(Group.Optional.class) PageParam param) {
return page(param);
}
@AuthIgnore
@SneakyThrows
@SaIgnore
@SneakyThrows(IOException.class)
@ApiOperation(value = "文件下载", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@GetMapping("download")
public void download(HttpServletResponse response) {
......
......@@ -11,9 +11,11 @@ import java.lang.annotation.*;
* @author Jim
* @version 0.1
* 2022/4/7 15:21
* @deprecated 已过期,请使用 @SaIgnore
*/
@SuppressWarnings({ "unused" })
@Deprecated
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
......
......@@ -3,10 +3,12 @@ package com.yiring.auth.param.permission;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.yiring.auth.domain.permission.Permission;
import com.yiring.common.validation.group.Group;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serial;
import java.io.Serializable;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import lombok.*;
......@@ -14,6 +16,7 @@ import lombok.experimental.FieldDefaults;
/**
* 权限信息入参类
*
* @author Jim
* @version 0.1
* 2022/3/25 17:09
......@@ -31,6 +34,10 @@ public class PermissionParam implements Serializable {
@Serial
private static final long serialVersionUID = -6781934969837655538L;
@ApiModelProperty(value = "id", example = "1", required = true)
@NotBlank(groups = { Group.Edit.class })
String id;
@ApiModelProperty(value = "权限类型", example = "MENU", required = true)
@NotNull(message = "权限类型不能为空")
Permission.Type type;
......
/* (C) 2022 YiRing, Inc. */
package com.yiring.auth.param.role;
import com.yiring.common.validation.group.Group;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serial;
import java.io.Serializable;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotEmpty;
import lombok.*;
import lombok.experimental.FieldDefaults;
/**
* 角色信息入参类
*
* @author Jim
* @version 0.1
* 2022/3/25 17:09
......@@ -27,6 +30,10 @@ public class RoleParam implements Serializable {
@Serial
private static final long serialVersionUID = 6572751635422870217L;
@ApiModelProperty(value = "id", example = "1", required = true)
@NotBlank(groups = { Group.Edit.class })
String id;
@ApiModelProperty(value = "标识", example = "admin", required = true)
@NotEmpty(message = "角色标识不能为空")
String uid;
......
......@@ -14,6 +14,7 @@ import lombok.experimental.FieldDefaults;
/**
* 菜单输出类
*
* @author Jim
* @version 0.1
* 2022/3/25 17:09
......@@ -37,6 +38,9 @@ public class MenuVo implements Serializable {
@JsonIgnore
String pid;
@ApiModelProperty(value = "唯一标识", example = "Dashboard")
String uid;
@ApiModelProperty(value = "名称", example = "Dashboard")
String name;
......
......@@ -20,7 +20,6 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.time.LocalDateTime;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Example;
......@@ -40,7 +39,7 @@ import org.springframework.web.bind.annotation.RestController;
@Slf4j
@Validated
@SuppressWarnings({ "deprecation", "all" })
@SuppressWarnings({ "all" })
@ApiSupport(order = -99)
@Api(tags = "身份认证", description = "Auth")
@RestController
......@@ -53,7 +52,7 @@ public class AuthController {
@ApiOperation(value = "注册")
@PostMapping("register")
public Result<String> register(@Valid RegisterParam param) {
public Result<String> register(@Validated RegisterParam param) {
// 检查用户名是否存在
long count = userRepository.count(Example.of(User.builder().username(param.getUsername()).build()));
if (count > 0) {
......@@ -91,7 +90,7 @@ public class AuthController {
@ApiOperation(value = "登录")
@PostMapping("login")
public Result<LoginVo> login(@Valid LoginParam param, HttpServletRequest request) {
public Result<LoginVo> login(@Validated LoginParam param, HttpServletRequest request) {
// 查询用户信息是否匹配
User user = userRepository.findByAccount(param.getAccount());
if (user == null) {
......@@ -151,7 +150,7 @@ public class AuthController {
@SaCheckLogin
@ApiOperation(value = "安全校验")
@GetMapping("safe")
public Result<String> safe(@Valid SafeParam param) {
public Result<String> safe(@Validated SafeParam param) {
User user = auths.getLoginUser();
if (SaSecureUtil.sha256(param.getPassword()).equals(user.getPassword())) {
StpUtil.openSafe(120);
......
......@@ -14,15 +14,15 @@ import com.yiring.common.core.Result;
import com.yiring.common.core.Status;
import com.yiring.common.exception.BusinessException;
import com.yiring.common.param.IdParam;
import com.yiring.common.param.OptionalPidParam;
import com.yiring.common.param.PageParam;
import com.yiring.common.param.PidParam;
import com.yiring.common.validation.group.Group;
import com.yiring.common.vo.PageVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
......@@ -56,7 +56,7 @@ public class PermissionController {
@ApiOperation(value = "新增")
@PostMapping("add")
public Result<String> add(@Valid PermissionParam param) {
public Result<String> add(@Validated({ Group.Add.class }) PermissionParam param) {
if (has(param.getUid())) {
throw BusinessException.i18n("Code.1001");
}
......@@ -68,8 +68,8 @@ public class PermissionController {
@ApiOperation(value = "修改")
@PostMapping("modify")
public Result<String> modify(@Valid PermissionParam param, @Valid IdParam idParam) {
Optional<Permission> optional = permissionRepository.findById(idParam.getId());
public Result<String> modify(@Validated({ Group.Edit.class }) PermissionParam param) {
Optional<Permission> optional = permissionRepository.findById(param.getId());
if (optional.isEmpty()) {
throw Status.NOT_FOUND.exception();
}
......@@ -88,7 +88,7 @@ public class PermissionController {
@ApiOperation(value = "删除")
@PostMapping("deleted")
public Result<String> deleted(@Valid IdParam param) {
public Result<String> deleted(@Validated IdParam param) {
Optional<Permission> optional = permissionRepository.findById(param.getId());
if (optional.isEmpty()) {
throw Status.NOT_FOUND.exception();
......@@ -101,7 +101,7 @@ public class PermissionController {
@ApiOperation(value = "查询")
@GetMapping("find")
public Result<PermissionVo> find(@Valid IdParam param) {
public Result<PermissionVo> find(@Validated IdParam param) {
Optional<Permission> optional = permissionRepository.findById(param.getId());
if (optional.isEmpty()) {
throw Status.NOT_FOUND.exception();
......@@ -116,7 +116,7 @@ public class PermissionController {
@ApiOperation(value = "分页查询")
@GetMapping("page")
public Result<PageVo<PermissionVo>> page(@Valid PageParam param) {
public Result<PageVo<PermissionVo>> page(@Validated PageParam param) {
Page<Permission> page = permissionRepository.findAll(PageParam.toPageable(param));
List<PermissionVo> data = Permissions.toPermissionVos(page.toList());
PageVo<PermissionVo> vo = PageVo.build(data, page.getTotalElements());
......@@ -125,7 +125,7 @@ public class PermissionController {
@ApiOperation(value = "树结构查询")
@GetMapping(value = "tree")
public Result<ArrayList<PermissionVo>> tree(OptionalPidParam param) {
public Result<ArrayList<PermissionVo>> tree(@Validated(Group.Optional.class) PidParam param) {
List<Permission> permissions = permissionRepository.findAll();
List<PermissionVo> vos = Permissions.toTree(
permissions,
......
......@@ -15,12 +15,12 @@ import com.yiring.common.exception.BusinessException;
import com.yiring.common.param.IdParam;
import com.yiring.common.param.IdsParam;
import com.yiring.common.param.PageParam;
import com.yiring.common.validation.group.Group;
import com.yiring.common.vo.PageVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.io.Serializable;
import java.util.*;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
......@@ -55,7 +55,7 @@ public class RoleController {
@ApiOperation(value = "新增")
@PostMapping("add")
public Result<String> add(@Valid RoleParam param) {
public Result<String> add(@Validated({ Group.Add.class }) RoleParam param) {
if (has(param.getUid())) {
throw BusinessException.i18n("Code.1002");
}
......@@ -68,8 +68,8 @@ public class RoleController {
@ApiOperation(value = "修改")
@PostMapping("modify")
public Result<String> modify(@Valid RoleParam param, @Valid IdParam idParam) {
Optional<Role> optional = roleRepository.findById(idParam.getId());
public Result<String> modify(@Validated({ Group.Edit.class }) RoleParam param) {
Optional<Role> optional = roleRepository.findById(param.getId());
if (optional.isEmpty()) {
throw Status.NOT_FOUND.exception();
}
......@@ -89,7 +89,7 @@ public class RoleController {
@ApiOperation(value = "分配权限")
@PostMapping("assign")
public Result<String> assign(@Valid IdParam idParam, @Valid IdsParam idsParam) {
public Result<String> assign(@Validated IdParam idParam, @Validated IdsParam idsParam) {
Optional<Role> optional = roleRepository.findById(idParam.getId());
if (optional.isEmpty()) {
throw Status.NOT_FOUND.exception();
......@@ -107,7 +107,7 @@ public class RoleController {
@ApiOperation(value = "删除")
@PostMapping("deleted")
public Result<String> deleted(@Valid IdsParam param) {
public Result<String> deleted(@Validated IdsParam param) {
List<Role> roles = roleRepository.findAllById(param.toIds());
roleRepository.deleteAll(roles);
return Result.ok();
......@@ -115,7 +115,7 @@ public class RoleController {
@ApiOperation(value = "查询")
@GetMapping("find")
public Result<RoleVo> find(@Valid IdParam param) {
public Result<RoleVo> find(@Validated IdParam param) {
Optional<Role> optional = roleRepository.findById(param.getId());
if (optional.isEmpty()) {
throw Status.NOT_FOUND.exception();
......@@ -130,7 +130,7 @@ public class RoleController {
@ApiOperation(value = "分页查询")
@GetMapping("page")
public Result<PageVo<RoleVo>> page(@Valid PageParam param) {
public Result<PageVo<RoleVo>> page(@Validated PageParam param) {
Page<Role> page = roleRepository.findAll(PageParam.toPageable(param));
List<RoleVo> data = new ArrayList<>(Permissions.toRoleVos(page.toSet()));
PageVo<RoleVo> vo = PageVo.build(data, page.getTotalElements());
......
......@@ -19,7 +19,6 @@ import io.swagger.annotations.ApiOperation;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;
import javax.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
......@@ -52,7 +51,7 @@ public class UserController {
@ApiOperation(value = "分配角色")
@PostMapping("assign")
public Result<String> assign(@Valid IdParam idParam, @Valid IdsParam idsParam) {
public Result<String> assign(@Validated IdParam idParam, @Validated IdsParam idsParam) {
Optional<User> optional = userRepository.findById(idParam.getId());
if (optional.isEmpty()) {
throw Status.NOT_FOUND.exception();
......@@ -70,7 +69,7 @@ public class UserController {
@ApiOperation(value = "分页查询")
@GetMapping("page")
public Result<PageVo<UserVo>> page(@Valid PageParam param) {
public Result<PageVo<UserVo>> page(@Validated PageParam param) {
Page<User> page = userRepository.findAll(PageParam.toPageable(param));
List<UserVo> data = page.get().map(user -> Commons.transform(user, UserVo.class)).collect(Collectors.toList());
......
......@@ -8,6 +8,7 @@ import com.yiring.common.constant.DateFormatter;
import com.yiring.common.core.Result;
import com.yiring.common.util.Commons;
import java.time.LocalDateTime;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
......@@ -34,6 +35,11 @@ public class RequestAspect {
@Value("${debug}")
Boolean debug;
/**
* 白名单
*/
List<String> WHITE_LIST = List.of("/swagger-resources", "/error");
@Pointcut(
"@annotation(org.springframework.web.bind.annotation.RequestMapping) || @annotation(org.springframework.web.bind.annotation.PostMapping) || @annotation(org.springframework.web.bind.annotation.GetMapping) || @annotation(org.springframework.web.bind.annotation.PutMapping) || @annotation(org.springframework.web.bind.annotation.DeleteMapping) || @annotation(org.springframework.web.bind.annotation.PatchMapping) || @annotation(org.springframework.web.bind.annotation.ExceptionHandler)"
)
......@@ -42,6 +48,10 @@ public class RequestAspect {
@Around("apiPointCut()")
public Object around(ProceedingJoinPoint point) throws Throwable {
HttpServletRequest request = getRequest();
// 放行白名单
if (WHITE_LIST.contains(request.getServletPath())) {
return point.proceed();
}
// 计算接口执行耗时
long start = System.currentTimeMillis();
......
......@@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serial;
import java.io.Serializable;
import javax.validation.constraints.NotBlank;
import lombok.*;
import lombok.experimental.FieldDefaults;
......@@ -27,5 +28,6 @@ public class KeywordParam implements Serializable {
private static final long serialVersionUID = -8690942241103456894L;
@ApiModelProperty(value = "关键字", example = "hi")
@NotBlank
String keyword;
}
/* (C) 2021 YiRing, Inc. */
package com.yiring.common.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serial;
import java.io.Serializable;
import lombok.*;
import lombok.experimental.FieldDefaults;
/**
* 公共的 Boolean 查询参数
*
* @author ifzm
* @version 0.1
* 2019/5/28 22:11
*/
@ApiModel(value = "BooleanParam", description = "公共的 Boolean 查询参数")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class OptionalBooleanParam implements Serializable {
@Serial
private static final long serialVersionUID = -3100195332181882287L;
@ApiModelProperty(value = "value", example = "true")
Boolean value;
}
/* (C) 2021 YiRing, Inc. */
package com.yiring.common.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;
import javax.validation.constraints.Min;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.FieldDefaults;
import lombok.experimental.SuperBuilder;
import org.hibernate.validator.constraints.Range;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
/**
* 可选的公共的分页排序查询参数
*
* @author ifzm
* @version 0.1 2019/3/10 16:29
*/
@ApiModel(value = "OptionalPageParam", description = "可选的公共的分页排序查询参数")
@Data
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class OptionalPageParam implements Serializable {
@Serial
private static final long serialVersionUID = 6103761701912769946L;
@ApiModelProperty(value = "分页条数", example = "10", required = true)
@Range(min = 1, max = 100)
Integer pageSize;
@ApiModelProperty(value = "当前页数", example = "1", required = true)
@Min(1)
Integer pageNo;
@ApiModelProperty(value = "排序字段", example = "id")
String sortField;
@ApiModelProperty(value = "排序方向(ASC|DESC)", example = "DESC")
Sort.Direction sortOrder;
/**
* 根据参数构建分页对象
*
* @param param {@link OptionalPageParam}
* @return Pageable
*/
@SuppressWarnings({ "unused" })
public static Pageable toPageable(OptionalPageParam param) {
if (param == null) {
return Pageable.unpaged();
}
Sort sort = Sort.unsorted();
if (Objects.nonNull(param.getSortField())) {
sort = Sort.by(new Sort.Order(param.getSortOrder(), param.getSortField()));
}
return PageRequest.of(param.getPageNo() - 1, param.getPageSize(), sort);
}
}
/* (C) 2021 YiRing, Inc. */
package com.yiring.common.param;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.io.Serial;
import java.io.Serializable;
import lombok.*;
import lombok.experimental.FieldDefaults;
/**
* 公共的可选父级 ID 查询参数
*
* @author ifzm
* @version 0.1
* 2019/5/28 22:11
*/
@ApiModel(value = "OptionalPidParam", description = "公共的可选父级 ID 查询参数")
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@FieldDefaults(level = AccessLevel.PRIVATE)
public class OptionalPidParam implements Serializable {
@Serial
private static final long serialVersionUID = -8690942241103456893L;
@ApiModelProperty(value = "pid", example = "0")
String pid;
}
......@@ -21,6 +21,7 @@ import org.springframework.data.domain.Sort;
/**
* 公共的分页排序查询参数
* eg: 支持使用 @Validated(Group.Optional.class) 来忽略校验
*
* @author ifzm
* @version 0.1 2019/3/10 16:29
......@@ -36,12 +37,12 @@ public class PageParam implements Serializable {
@Serial
private static final long serialVersionUID = 6103761701912769946L;
@ApiModelProperty(value = "分页条数", example = "10", required = true)
@ApiModelProperty(value = "分页条数", example = "10")
@NotNull
@Range(min = 1, max = 100)
Integer pageSize;
@ApiModelProperty(value = "当前页数", example = "1", required = true)
@ApiModelProperty(value = "当前页数", example = "1")
@NotNull
@Min(1)
Integer pageNo;
......@@ -60,7 +61,7 @@ public class PageParam implements Serializable {
*/
@SuppressWarnings({ "unused" })
public static Pageable toPageable(PageParam param) {
if (param == null) {
if (param == null || Objects.isNull(param.getPageNo()) || Objects.isNull(param.getPageSize())) {
return Pageable.unpaged();
}
......
/* (C) 2022 YiRing, Inc. */
package com.yiring.common.util;
package com.yiring.common.validation;
import com.yiring.common.util.Commons;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
......@@ -33,7 +34,7 @@ public class ValidateUtil {
@Cleanup
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Set<ConstraintViolation<T>> constraintViolations = factory.getValidator().validate(t, groups);
if (constraintViolations.size() > 0) {
if (!Commons.isNullOrEmpty(constraintViolations)) {
throw new ConstraintViolationException(constraintViolations);
}
}
......
/* (C) 2022 YiRing, Inc. */
package com.yiring.common.validation.group;
import javax.validation.groups.Default;
/**
* validate group
* 预设一些全局公用的参数参数分组
*
* @author Jim
* @version 0.1
* 2022/11/10 11:46
*/
@SuppressWarnings("unused")
public interface Group {
/**
* 数据添加分组
*/
interface Add extends Default {}
/**
* 数据修改分组
*/
interface Edit extends Default {}
/**
* 通用的必填分组
*/
interface Required extends Default {}
/**
* 可选的分组
*/
interface Optional {}
}
......@@ -19,7 +19,6 @@ import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import java.sql.Timestamp;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
......@@ -115,7 +114,7 @@ public class MinioController {
*/
@ApiOperation(value = "文件下载", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
@GetMapping("download")
public void download(HttpServletResponse response, @Valid DownloadParam param) {
public void download(HttpServletResponse response, @Validated DownloadParam param) {
try {
StatObjectResponse statObject = minio.objectStat(param.getBucket(), param.getObject());
GetObjectResponse object = minio.getObject(param.getBucket(), param.getObject());
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论