feat: 增加Validation配置,重构部分地址Controller,增加针对地址的自定义校验器

This commit is contained in:
Gadfly 2021-08-06 18:21:27 +08:00
parent 87cde33933
commit 0933f45dca
9 changed files with 189 additions and 15 deletions

View File

@ -3,30 +3,48 @@ package com.youlai.mall.ums.pojo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.youlai.common.base.BaseEntity;
import com.youlai.common.constraints.CheckCityValid;
import com.youlai.common.constraints.CityType;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Positive;
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = true)
public class UmsAddress extends BaseEntity {
@TableId(type = IdType.AUTO)
private Long id;
@NotNull(message = "{id.positive}")
@Positive(message = "{id.positive}")
private Long memberId;
@Length(min = 2, max = 8, message = "{text.length.min}{text.length.max}")
private String name;
@Pattern(regexp = "^1(3\\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\\d|9[0-35-9])\\d{8}$", message = "{phone.valid}")
private String mobile;
@CheckCityValid(CityType.PROVINCE)
private String province;
@CheckCityValid(CityType.CITY)
private String city;
@CheckCityValid(CityType.AREA)
private String area;
@Length(min = 5, max = 100, message = "{text.length.min}{text.length.max}")
private String address;
@Pattern(regexp = "^[0-9]{6}$", message = "{zipcode.valid}")
private String zipCode;
private Integer defaulted;

View File

@ -12,6 +12,7 @@ import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
@ -30,7 +31,7 @@ public class AddressController {
@ApiOperation(value = "获取登录会员的地址列表")
@GetMapping
public Result list() {
public Result<List<UmsAddress>> list() {
Long memberId = JwtUtils.getUserId();
List<UmsAddress> addressList = iUmsAddressService.list(new LambdaQueryWrapper<UmsAddress>()
.eq(UmsAddress::getMemberId, memberId)
@ -42,13 +43,14 @@ public class AddressController {
@ApiOperation(value = "新增地址")
@ApiImplicitParam(name = "address", value = "实体JSON对象", required = true, paramType = "body", dataType = "UmsAddress")
@PostMapping
public Result add(@RequestBody UmsAddress address) {
public <T> Result<T> add(@RequestBody @Validated UmsAddress address) {
Long memberId = JwtUtils.getUserId();
address.setMemberId(memberId);
address.setId(null);
if (ADDRESS_DEFAULTED.equals(address.getDefaulted())) { // 修改其他默认地址为非默认
iUmsAddressService.update(new LambdaUpdateWrapper<UmsAddress>()
.eq(UmsAddress::getMemberId, memberId)
.eq(UmsAddress::getDefaulted, 1)
.eq(UmsAddress::getDefaulted, ADDRESS_DEFAULTED)
.set(UmsAddress::getDefaulted, 0)
);
}
@ -59,15 +61,12 @@ public class AddressController {
@ApiOperation(value = "修改地址")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "部门id", required = true, paramType = "path", dataType = "Long"),
@ApiImplicitParam(name = "address", value = "实体JSON对象", required = true, paramType = "body", dataType = "UmsAddress")
})
@PutMapping(value = "/{id}")
public Result update(
@PathVariable Long id,
@RequestBody UmsAddress address) {
@PutMapping
public <T> Result<T> update(@RequestBody @Validated UmsAddress address) {
Long memberId = JwtUtils.getUserId();
if (address.getDefaulted().equals(1)) { // 修改其他默认地址为非默认
if (ADDRESS_DEFAULTED.equals(address.getDefaulted())) { // 修改其他默认地址为非默认
iUmsAddressService.update(new LambdaUpdateWrapper<UmsAddress>()
.eq(UmsAddress::getMemberId, memberId)
.eq(UmsAddress::getDefaulted, 1)
@ -81,7 +80,7 @@ public class AddressController {
@ApiOperation(value = "删除地址")
@ApiImplicitParam(name = "ids", value = "id集合字符串英文逗号分隔", required = true, paramType = "query", dataType = "String")
@DeleteMapping("/{ids}")
public Result delete(@PathVariable String ids) {
public <T> Result<T> delete(@PathVariable String ids) {
boolean status = iUmsAddressService.removeByIds(Arrays.asList(ids.split(",")));
return Result.judge(status);
}
@ -89,21 +88,20 @@ public class AddressController {
@ApiOperation(value = "修改地址【部分更新】")
@ApiImplicitParams({
@ApiImplicitParam(name = "id", value = "用户ID", required = true, paramType = "path", dataType = "Long"),
@ApiImplicitParam(name = "address", value = "实体JSON对象", required = true, paramType = "body", dataType = "UmsAddress")
})
@PatchMapping(value = "/{id}")
public Result patch(@PathVariable Long id, @RequestBody UmsAddress address) {
@PatchMapping
public <T> Result<T> patch(@RequestBody UmsAddress address) {
Long userId = JwtUtils.getUserId();
LambdaUpdateWrapper<UmsAddress> updateWrapper = new LambdaUpdateWrapper<UmsAddress>()
.eq(UmsAddress::getMemberId, userId);
if (address.getDefaulted() != null) {
updateWrapper.set(UmsAddress::getDefaulted, address.getDefaulted());
if (address.getDefaulted().equals(1)) { // 修改其他默认地址为非默认
if (ADDRESS_DEFAULTED.equals(address.getDefaulted())) { // 修改其他默认地址为非默认
iUmsAddressService.update(new LambdaUpdateWrapper<UmsAddress>()
.eq(UmsAddress::getMemberId, userId)
.eq(UmsAddress::getDefaulted, 1)
.eq(UmsAddress::getDefaulted, ADDRESS_DEFAULTED)
.set(UmsAddress::getDefaulted, 0)
);
}

View File

@ -47,6 +47,10 @@
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
</dependencies>

View File

@ -0,0 +1,31 @@
package com.youlai.common.constraints;
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* 校验城市地名等是否合法不接受null
*
* @author Gadfly
* @since 2021-08-06 16:02
*/
@Documented
@Constraint(validatedBy = CityValidator.class)
@Target({METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE})
@Retention(RUNTIME)
public @interface CheckCityValid {
/* 校验字段类型 */
CityType value() default CityType.CITY;
String message() default "{city.valid}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}

View File

@ -0,0 +1,14 @@
package com.youlai.common.constraints;
import lombok.Data;
/**
* @author Gadfly
* @since 2021-08-06 16:46
*/
@Data
public class CityEntity {
private String value;
private String name;
private String parent;
}

View File

@ -0,0 +1,9 @@
package com.youlai.common.constraints;
/**
* @author Gadfly
* @since 2021-08-06 16:02
*/
public enum CityType {
PROVINCE,CITY,AREA
}

View File

@ -0,0 +1,88 @@
package com.youlai.common.constraints;
import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSONUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.io.InputStream;
import java.util.List;
/**
* @author Gadfly
* @since 2021-08-06 16:03
*/
public class CityValidator implements ConstraintValidator<CheckCityValid, String> {
private CityType type;
@Autowired
private StringRedisTemplate redisTemplate;
@Override
public void initialize(CheckCityValid annotation) {
this.type = annotation.value();
}
@SneakyThrows
@Override
public boolean isValid(String inputValue, ConstraintValidatorContext context) {
if (inputValue == null) {
return false;
}
String jsonStr = redisTemplate.opsForValue().get("constant:city");
if (!StringUtils.hasText(jsonStr)) {
ClassPathResource resource = new ClassPathResource("city.json");
InputStream inputStream = resource.getInputStream();
String line = IoUtil.readUtf8(inputStream);
redisTemplate.opsForValue().set("constant:city", line);
jsonStr = line;
}
List<CityEntity> cityJson = JSONUtil.toList(jsonStr, CityEntity.class);
CityEntity entity;
switch (type) {
case PROVINCE: {
entity = cityJson.stream().filter(item -> inputValue.equals(item.getName()) && item.getParent() == null)
.findFirst()
.orElse(null);
break;
}
default:
case CITY: {
entity = cityJson.stream().filter(item -> {
// 找出名字相符且有父节点的entity
if (inputValue.equals(item.getName()) && item.getParent() != null) {
// 找出没有父节点的父节点
CityEntity parentEntity = cityJson.stream()
.filter(parent -> item.getParent().equals(parent.getValue()) && parent.getParent() == null)
.findFirst().orElse(null);
return parentEntity != null;
}
return false;
}).findFirst().orElse(null);
break;
}
case AREA: {
entity = cityJson.stream().filter(item -> {
// 找出名字相符且有父节点的entity
if (inputValue.equals(item.getName()) && item.getParent() != null) {
// 找出有父节点的父节点
CityEntity parentEntity = cityJson.stream()
.filter(parent -> item.getParent().equals(parent.getValue()) && parent.getParent() != null)
.findFirst().orElse(null);
return parentEntity != null;
}
return false;
}).findFirst().orElse(null);
break;
}
}
return entity != null;
}
}

View File

@ -0,0 +1,11 @@
# \u901A\u7528\u5F02\u5E38\u4FE1\u606F
id.positive=id\u5FC5\u987B\u4E3A\u6B63\u6574\u6570
page.count.min=\u5206\u9875\u6570\u91CF\u5FC5\u987B\u4E3A\u6B63\u6574\u6570
page.count.max=\u5206\u9875\u6570\u91CF\u5FC5\u987B\u5C0F\u4E8E{value}
page.number.min=\u5206\u9875\u9875\u7801\u5FC5\u987B\u4E3A\u6B63\u6574\u6570
date.past=\u65E5\u671F\u5FC5\u987B\u662F\u8FC7\u53BB\u7684\u65F6\u95F4
date.interval=\u7ED3\u675F\u65E5\u671F\u5FC5\u987B\u65E9\u4E8E\u5F00\u59CB\u65E5\u671F
text.length.min=\u6700\u5C0F\u957F\u5EA6\u5FC5\u987B\u5927\u4E8E{min}
text.length.max=\u6700\u5927\u957F\u5EA6\u5FC5\u987B\u5C0F\u4E8E{max}
phone.valid=\u5FC5\u987B\u662F\u5927\u964611\u4F4D\u624B\u673A\u53F7
zipcode.valid=\u90AE\u7F16\u5FC5\u987B\u4E3A6\u4F4D\u6570\u5B57

File diff suppressed because one or more lines are too long