阿超
>
spring实现Validator校验和全局异常处理
开整!
首先引入依赖
1 2 3 4 5 6 7 8 9 10 11 12 13
| <dependency> <groupId>org.hibernate.validator</groupId> <artifactId>hibernate-validator</artifactId> <version>6.1.5.Final</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.73</version> </dependency>
|
在需要校验的实体类上加注解,这里我们写个接口,给它分个组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| package com.ruben.pojo;
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;
import javax.validation.constraints.NotBlank;
@Data @NoArgsConstructor @AllArgsConstructor public class User { @NotBlank(message = "用户名不能为空", groups = {UserCheck.class}) private String username; @NotBlank(message = "密码不能为空", groups = UserCheck.class) private String password;
public interface UserCheck {
} }
|
然后在方法上加上注解,并指定分组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
@PostMapping("login") public Map<String, Object> login(@Validated({User.UserCheck.class}) @RequestBody User user) { Map<String, Object> map = new HashMap<>(1 << 2); String myUsername = "achao"; String myPassword = "ruben"; if (myUsername.equals(user.getUsername()) && myPassword.equals(user.getPassword())) { map.put("success", true); map.put("code", 200); map.put("msg", "登录成功!"); } else { map.put("success", false); map.put("code", -629); map.put("msg", "登录失败,用户名密码错误!"); } return map; }
|
这时候,我们发现已经抛出异常了
我们尝试去捕获这个异常MethodArgumentNotValidException
首先写个全局异常处理器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| package com.ruben.resolver;
import com.alibaba.fastjson.support.spring.FastJsonJsonView; import org.springframework.http.HttpStatus; import org.springframework.web.servlet.HandlerExceptionResolver; import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.HashMap; import java.util.Map;
public class GlobalExceptionResolver implements HandlerExceptionResolver { @Override public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) { e.printStackTrace(); ModelAndView modelAndView = new ModelAndView(); FastJsonJsonView fastJsonJsonView = new FastJsonJsonView(); Map<String, Object> map = new HashMap<>(1 << 2); map.put("success", false); map.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value()); map.put("msg", "内部错误"); fastJsonJsonView.setAttributesMap(map); modelAndView.setView(fastJsonJsonView); return modelAndView; } }
|
然后在springmvc
里一配
1 2
| <bean id="handlerExceptionResolver" class="com.ruben.resolver.GlobalExceptionResolver"/>
|
我们随便写个int i = 2/0;
的异常,发现全局异常处理器测试通过
然后精彩部分来了,我们debug
发现这个MethodArgumentNotValidException
异常全局异常处理器根本没进去!!!
那这样就没办法了吗?No No No!
这里我们采用AOP
的方式
首先自定义个注解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package com.ruben.annotation;
import java.lang.annotation.*;
@Documented @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Validator { String value() default "bindingResult"; }
|
写完,在我们的方法上加上我们的注解和参数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
|
@Validator @PostMapping("login") public Map<String, Object> login(@Validated({User.UserCheck.class}) @RequestBody User user, BindingResult bindingResult) { Map<String, Object> map = new HashMap<>(1 << 2); String myUsername = "achao"; String myPassword = "ruben"; if (myUsername.equals(user.getUsername()) && myPassword.equals(user.getPassword())) { map.put("success", true); map.put("code", 200); map.put("msg", "登录成功!"); } else { map.put("success", false); map.put("code", -629); map.put("msg", "登录失败,用户名密码错误!"); } return map; }
|
然后写个简单的AOP
来处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| package com.ruben.aop;
import com.ruben.annotation.Validator; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.context.support.DefaultMessageSourceResolvable; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.validation.BindingResult;
import java.util.HashMap; import java.util.Map; import java.util.stream.Collectors;
@Aspect @Component public class ValidatorAop {
@Around("@annotation(validator)") public Object validateParam(ProceedingJoinPoint joinPoint, Validator validator) { String value = validator.value(); String[] parameterNames = ((MethodSignature) joinPoint.getSignature()).getParameterNames(); BindingResult bindingResult = null; for (int i = 0; i < parameterNames.length; i++) { if (value.equals(parameterNames[i])) { bindingResult = (BindingResult) joinPoint.getArgs()[i]; } } Map<String, Object> map = new HashMap<>(1 << 2); if (bindingResult != null && bindingResult.hasErrors()) { map.put("success", false); map.put("code", HttpStatus.BAD_REQUEST); map.put("msg", bindingResult.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(" "))); return map; } try { return joinPoint.proceed(); } catch (Throwable throwable) { throwable.printStackTrace(); } return null; } }
|
顺便放上一张我们的参数和提示截图
大功告成!