首先提倡下Hibernate的验证器,功能强大且使用方面,Hibernate Validator提供包括国际化,传统的字符空,非法的输入等,而且给了很友善的message信息。
public class BeanValidators {
/**
* 调用JSR303的validate方法, 验证失败时抛出ConstraintViolationException, 而不是返回constraintViolations.
*/
public static void validateWithException(Validator validator, Object object, Class<?>... groups)
throws ConstraintViolationException {
Set constraintViolations = validator.validate(object, groups);
if (!constraintViolations.isEmpty()) {
throw new ConstraintViolationException(constraintViolations);
}
}
/**
* 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>中为List<message>.
*/
public static List<String> extractMessage(ConstraintViolationException e) {
return extractMessage(e.getConstraintViolations());
}
/**
* 辅助方法, 转换Set<ConstraintViolation>为List<message>
*/
public static List<String> extractMessage(Set<? extends ConstraintViolation> constraintViolations) {
List<String> errorMessages = new ArrayList<String>();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getMessage());
}
return errorMessages;
}
/**
* 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>为Map<property, message>.
*/
public static Map<String, String> extractPropertyAndMessage(ConstraintViolationException e) {
return extractPropertyAndMessage(e.getConstraintViolations());
}
/**
* 辅助方法, 转换Set<ConstraintViolation>为Map<property, message>.
*/
public static Map<String, String> extractPropertyAndMessage(Set<? extends ConstraintViolation> constraintViolations) {
Map<String, String> errorMessages = new HashMap<String, String>();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.put(violation.getPropertyPath().toString(), violation.getMessage());
}
return errorMessages;
}
/**
* 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>为List<propertyPath message>.
*/
public static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), " ");
}
/**
* 辅助方法, 转换Set<ConstraintViolations>为List<propertyPath message>.
*/
public static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations) {
return extractPropertyAndMessageAsList(constraintViolations, " ");
}
/**
* 辅助方法, 转换ConstraintViolationException中的Set<ConstraintViolations>为List<propertyPath + separator + message>.
*/
public static List<String> extractPropertyAndMessageAsList(ConstraintViolationException e, String separator) {
return extractPropertyAndMessageAsList(e.getConstraintViolations(), separator);
}
/**
* 辅助方法, 转换Set<ConstraintViolation>为List<propertyPath + separator + message>.
*/
public static List<String> extractPropertyAndMessageAsList(Set<? extends ConstraintViolation> constraintViolations,
String separator) {
List<String> errorMessages = new ArrayList<String>();
for (ConstraintViolation violation : constraintViolations) {
errorMessages.add(violation.getPropertyPath() + separator + violation.getMessage());
}
return errorMessages;
}
}
结合HibernateValidator,添加自定义的exception
public class CustormizeException extends RuntimeException {
private static final long serialVersionUID = -3703423976960486177L;
private int errorCode;
public CustormizeException(ResultCode statusCode) {
this(statusCode, null);
}
public CustormizeException(ResultCode resultCode, String message) {
super(resultCode.name() + (message == null ? "" : " " + message));
this.errorCode = resultCode.code();
}
public String toString() {
return String.format("{\"errorCode\":\"%s\",\"errorMsg\":\"%s\"}", errorCode, this.getMessage());
}
public int getErrorCode() {
return errorCode;
}
public boolean checkStatus(ResultCode resultCode) {
return errorCode == resultCode.code();
}
}
增加异常处理的切面处理器,能够很快的捕获信息,反馈给各个终端设备,而不至于抛出恶心的代码异常信息。
@ControllerAdvice
public class CustormizeExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(value = {CustormizeException.class})
public final ResponseEntity<?> handleException(CustormizeException exception, WebRequest request) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("text/plain; charset=UTF-8"));
return handleExceptionInternal(exception,
exception.getCode() + ":" + exception.getMessage(),
headers,
exception.status,
request);
}
@ExceptionHandler(value = {ConstraintViolationException.class})
public final ResponseEntity<?> handleException(ConstraintViolationException exception, WebRequest request) {
Map<String, String> errors = BeanValidators.extractPropertyAndMessage(exception.getConstraintViolations());
String errorBody = JSON.toJSONString(errors, true);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.parseMediaType("text/plain; charset=UTF-8"));
return handleExceptionInternal(exception,
errorBody,
headers,
HttpStatus.BAD_REQUEST,
request);
}
}
总结:
异常处理其实不会让你头疼,但是我们常常忽略把异常丢给用户,这种事情成妾做不到,只能通过切面的方式在方法后捕获,然后进行反馈。