最近完成了一个后端项目,过程中遇到了一些难点和第一次遇到的BUG 分享一下,做个记录 ~~
1、通过注解判断参数vo是否为空,并做全局异常处理
在开发中,controller层需要经常对vo参数进行格式判断,这样就可能在多个请求方法中出现格式判断,所以为了降低代码冗余,通过在注解来进行格式判断。
实现思路:添加依赖,在需要进行格式判断的类中添加判断注解,如果我们需要实现一些自己的判断,可以实现自定义注解。这样基本就已经实现完了,但是。还要考虑的就是,如果入参的格式不符合我们的要求,validation 就会抛出异常,为了友好的返回结果,我们就会做全局异常处理。
第一部分:格式验证
-
添加依赖 <!--validation验证依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
-
在入参时需要进行格式判断的类中添加判断注解
@Data
public class LoginVo {
@NotNull
@IsMobile
private String mobile;
@NotNull
@Length(min = 32)
private String password;
}
-
实现自定义注解并注册到validation 组件中
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER, TYPE_USE })
@Retention(RUNTIME)
@Documented
@Constraint(validatedBy = {IsMobileValidator.class})
public @interface IsMobile {
boolean required() default true;
String message() default "手机号码格式错误";
Class<?>[] groups() default { };
Class<? extends Payload>[] payload() default { };
}
IsMobileValidator.java
public class IsMobileValidator implements ConstraintValidator<IsMobile,String> {
private boolean required = false;
@Override
public void initialize(IsMobile constraintAnnotation) {
required = constraintAnnotation.required();
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (required){
return ValidatorUtil.isMobile(value);
}else {
if (StringUtils.isEmpty(value)){
return true;
}else {
return ValidatorUtil.isMobile(value);
}
}
}
}
ValidatorUtil.java
public class ValidatorUtil {
private static final Pattern mobile_pattern = Pattern.compile("^1[3|4|5|7|8][0-9]{9}$");
public static boolean isMobile(String mobile){
if (StringUtils.isEmpty(mobile)) {
return false;
}
Matcher matcher = mobile_pattern.matcher(mobile);
return matcher.matches();
}
}
最后在我们需要使用的地方,通过 @Valid 开启就行。
第二部分:全局异常处理
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public RespBean ExceptionHandler(Exception e) {
}
}
2、根据cookie访问页面,参数中没有user信息,如何实现User自动映射?
这里也是为了降低代码冗余,实现User 自动映射
实现思路:添加参数解析器,实现我们的自动注入逻辑
-
配置参数解析器 WebMvcConfig配置类中重写
@Override
public void addArgumentResolvers(List argumentResolvers) {
argumentResolvers.add(new CurrentUserArgumentResolver());
}
-
实现参数解析器逻辑
@Slf4j
public class CurrentUserArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(CurrentUser.class);
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer modelAndView, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
Object currentUserInfo = webRequest.getAttribute("currentUser", RequestAttributes.SCOPE_REQUEST);
if(null == currentUserInfo)
log.warn("---------------用户未登录---------------");
return currentUserInfo;
}
}
-
定义声明注解
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CurrentUser {
}
3、redis通过RedisTemplate实现分布式锁解决预减库存
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.concurrent.TimeUnit;
@Component
public class LockUtil {
@Autowired
private StringRedisTemplate redisTemplate;
public boolean lock(String key, String value, long timeout) {
return redisTemplate.opsForValue().setIfAbsent(key, value, timeout, TimeUnit.SECONDS);
}
public Long executeDecrToZero(String key){
String luaScript=
"if (redis.call('exists', KEYS[1]) == 1) then\n" +
"local stock = tonumber(redis.call('get', KEYS[1]));\n" +
"if (stock > 0) then\n" +
"redis.call('incrby', KEYS[1], -1);\n" +
"return stock;\n" +
"end;\n" +
"return 0;\n" +
"end;";
RedisScript<Long> redisScript = new DefaultRedisScript<>(luaScript,Long.class);
return (Long) redisTemplate.execute(redisScript,Collections.singletonList(key),Collections.EMPTY_LIST);
}
}
4、application.yml中格式问题
第一次遇到这种问题,我的application.yml 中password 类似为123456Niess 这种密码,在本机启动时不会报错,但是我生成jar 包部署到服务器上后,启动时会报错,排查了很久,才发现是password 的格式错误。
解决方法:有特殊字符或者类似这种格式用引号括起来就好了,例如"123456Niess"
5、Maven中导包爆红
一般我们都会把maven仓库和idea相关的config设置好,然后基本上就不会出现问题。
但是不排除有时候我们将一个下载下来的项目,用idea 打开后maven 会爆红,不管怎么点击右上方刷新还是会存在
通用的解决方案:
- 将出问题的包找到
maven 仓库目录将相关包删除,然后重新导入 - 如果还是爆红,那就把
pom.xml 里面的内容剪切再粘贴就好
如果你是公司的项目的话,它有的包会依赖于公司私有服务器上,报红很正常,只需要找的mt要一份maven的config设置一下就好。
|