2-3 jsr303参数校验和全局异常处理

1、定义注解(IsMobile),规则

①在 LoginController类中:

public Result<Boolean> doLogin(@Valid LoginVo loginVo) {//loginVo 相当于是表单之中提交的数据

②在LoginVo类中:

import com.mydre.miaosha.validator.IsMobile;
public class LoginVo {
@NotNull
@Length(min=32)
private String password;
@NotNull
@IsMobile  //这里可以自己定义一个校验器
private String mobile;

public String getPassword() {

③定义IsMobile:

@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@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类

package com.mydre.miaosha.validator;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.apache.commons.lang3.StringUtils;
import com.mydre.miaosha.util.ValidatorUtil;
public class IsMobileValidator implements ConstraintValidator<IsMobile, String>{
private boolean required = false;
public void initialize(IsMobile constraintAnnotation) {//初始化函数,为类的成员变量赋值
required = constraintAnnotation.required();
}
public boolean isValid(String value, ConstraintValidatorContext context) {
if(required){//如果是必须的
return ValidatorUtil.isMobile(value);//当返回false的时候,就会自动把IsMobile中的message属性封装为错误
}else{//如果不是必须的
if(StringUtils.isEmpty(value)){
return true;
}else{//如果有了值,就判断格式
return ValidatorUtil.isMobile(value);
}
}
}

}

当校验不通过时,会抛出异常。这时如果没有定义全局异常处理器进行处理(对异常进行封装和返回)。则会发生400错误(即只有请求的发起,却没有收到正常的响应(response),因为还没有来得及return就抛出了异常(这种异常没有被处理))。

返回的不正常的响应如下:

{
"timestamp": 1527036396354,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.validation.BindException",
"errors": [{
"codes": ["IsMobile.loginVo.mobile", "IsMobile.mobile", "IsMobile.java.lang.String", "IsMobile"],
"arguments": [{
"codes": ["loginVo.mobile", "mobile"],
"arguments": null,
"defaultMessage": "mobile",
"code": "mobile"
}, true],
"defaultMessage": "手机号码格式错误",
"objectName": "loginVo",
"field": "mobile",
"rejectedValue": "25874589632",
"bindingFailure": false,
"code": "IsMobile"
}],
"message": "Validation failed for object='loginVo'. Error count: 1",
"path": "/login/do_login"

}

要针对特定的异常信息进行捕获和处理。如BindException。

⑤service汇总的登陆业务方法入下:

public boolean login(LoginVo loginVo) {
if(loginVo == null){
throw new GlobalException(CodeMsg.SERVER_ERROR);
}
String mobile = loginVo.getMobile(); //表单输入的手机号
String formPass = loginVo.getPassword(); //表单输入的密码
//验证手机号是否存在
MiaoshaUser user = getById(Long.parseLong(mobile));//把mobile当做id,Long.parseLong用于将字符串转为数字的
if(user == null){
//return CodeMsg.MOBILE_NOT_EXIST;
throw new GlobalException(CodeMsg.MOBILE_NOT_EXIST);
}
//验证密码
String dbPass = user.getPassword(); //获取数据库中的密码
String salt = user.getSalt(); //盐
String calculatorDbPass = MD5Util.formPassToDBPass(formPass, salt); //计算出来的数据库中的密码
if(!dbPass.equals(calculatorDbPass)){//使用equals方法来比较两个字符串
//return CodeMsg.PASSWORD_ERROR;
throw new GlobalException(CodeMsg.PASSWORD_ERROR);
}
//抛出的异常需要在全局异常处理器中进行处理
return true;//没有异常则返回登陆成功
}

⑥定义全局异常处理器

package com.mydre.miaosha.exception;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import com.mydre.miaosha.result.CodeMsg;
import com.mydre.miaosha.result.Result;
@ControllerAdvice //切面
@ResponseBody //把异常定义为ResponseBody(响应信息)
public class GlobalExceptionHandler {//请求信息连带着使用@Valid注解对请求信息进行校验产生的异常信息都将传递进来
@ExceptionHandler(value=Exception.class) //所有的异常都需要拦截
public Result<String> exceptionHandler(HttpServletRequest request, Exception e){//Exception也是系统传过来的
if(e instanceof GlobalException){
GlobalException gl_ex = (GlobalException)e;
CodeMsg cm = gl_ex.getCm();
return Result.error(cm);
}
else if(e instanceof BindException){
BindException ex = (BindException)e;
List<ObjectError> errors = ex.getAllErrors();
ObjectError ob_er = errors.get(0);
String er_msg = ob_er.getDefaultMessage();
return Result.error(CodeMsg.BIND_ERROR.fillArgs(er_msg));
}else{
return Result.error(CodeMsg.SERVER_ERROR);//如果不是绑定异常,就返回一个服务端异常
}
}

}

⑦在LoginController中进行调用

miaoshaUserService.login(loginVo); //实际上,在这一步的login方法的内部执行过程中,可能会抛出异常,好在使用全局异常处理器捕获了异常。
return Result.success(true);

猜你喜欢

转载自blog.csdn.net/jiuweideqixu/article/details/80417538