Skip to content

Commit

Permalink
3.0版本
Browse files Browse the repository at this point in the history
  • Loading branch information
qinyujie3 committed May 12, 2023
1 parent 622f98f commit f2aab04
Show file tree
Hide file tree
Showing 12 changed files with 242 additions and 25 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.feiniaojin</groupId>
<artifactId>graceful-response</artifactId>
<version>2.1</version>
<version>3.0</version>
<name>Graceful Response</name>
<description>Help Spring Boot web project responses gracefully!</description>
<url>https://github.com/feiniaojin/graceful-response.git</url>
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/com/feiniaojin/gracefulresponse/AutoConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import com.feiniaojin.gracefulresponse.advice.GlobalExceptionAdvice;
import com.feiniaojin.gracefulresponse.advice.NotVoidResponseBodyAdvice;
import com.feiniaojin.gracefulresponse.advice.ValidationExceptionAdvice;
import com.feiniaojin.gracefulresponse.advice.VoidResponseBodyAdvice;
import com.feiniaojin.gracefulresponse.api.ResponseFactory;
import com.feiniaojin.gracefulresponse.api.ResponseStatusFactory;
Expand Down Expand Up @@ -30,6 +31,12 @@ public GlobalExceptionAdvice globalExceptionAdvice() {
return new GlobalExceptionAdvice();
}

@Bean
@ConditionalOnMissingBean(value = ValidationExceptionAdvice.class)
public ValidationExceptionAdvice validationAdvice() {
return new ValidationExceptionAdvice();
}

@Bean
@ConditionalOnMissingBean(NotVoidResponseBodyAdvice.class)
public NotVoidResponseBodyAdvice notVoidResponseBodyAdvice() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ public ExceptionAliasRegister doRegisterExceptionAlias(Class<? extends Throwable
throw new RuntimeException();
}

aliasForMap.put(exceptionAliasFor.aliasFor(), exceptionAliasFor);
Class<? extends Throwable>[] classes = exceptionAliasFor.aliasFor();
for (Class<? extends Throwable> c : classes) {
aliasForMap.put(c, exceptionAliasFor);
}

return this;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.feiniaojin.gracefulresponse;

import com.feiniaojin.gracefulresponse.defaults.DefaultConstants;
import org.springframework.boot.context.properties.ConfigurationProperties;

/**
Expand Down Expand Up @@ -31,22 +32,27 @@ public class GracefulResponseProperties {
/**
* 默认的成功返回码
*/
private String defaultSuccessCode = "0";
private String defaultSuccessCode = DefaultConstants.DEFAULT_SUCCESS_CODE;

/**
* 默认的成功提示
*/
private String defaultSuccessMsg = "ok";
private String defaultSuccessMsg = DefaultConstants.DEFAULT_SUCCESS_MSG;

/**
* 默认的失败码
*/
private String defaultFailCode = "1";
private String defaultErrorCode = DefaultConstants.DEFAULT_ERROR_CODE;

/**
* 默认的失败提示
*/
private String defaultFailMsg = "error";
private String defaultErrorMsg = DefaultConstants.DEFAULT_ERROR_MSG;

/**
* Validate异常码,不提供的话默认DefaultConstants.DEFAULT_ERROR_CODE
*/
private String defaultValidateErrorCode = DefaultConstants.DEFAULT_ERROR_CODE;

public boolean isUseValidationMsg() {
return useValidationMsg;
Expand Down Expand Up @@ -80,20 +86,20 @@ public void setDefaultSuccessMsg(String defaultSuccessMsg) {
this.defaultSuccessMsg = defaultSuccessMsg;
}

public String getDefaultFailCode() {
return defaultFailCode;
public String getDefaultErrorCode() {
return defaultErrorCode;
}

public void setDefaultFailCode(String defaultFailCode) {
this.defaultFailCode = defaultFailCode;
public void setDefaultErrorCode(String defaultErrorCode) {
this.defaultErrorCode = defaultErrorCode;
}

public String getDefaultFailMsg() {
return defaultFailMsg;
public String getDefaultErrorMsg() {
return defaultErrorMsg;
}

public void setDefaultFailMsg(String defaultFailMsg) {
this.defaultFailMsg = defaultFailMsg;
public void setDefaultErrorMsg(String defaultErrorMsg) {
this.defaultErrorMsg = defaultErrorMsg;
}

public String getResponseClassFullName() {
Expand All @@ -111,4 +117,12 @@ public Integer getResponseStyle() {
public void setResponseStyle(Integer responseStyle) {
this.responseStyle = responseStyle;
}

public String getDefaultValidateErrorCode() {
return defaultValidateErrorCode;
}

public void setDefaultValidateErrorCode(String defaultValidateErrorCode) {
this.defaultValidateErrorCode = defaultValidateErrorCode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.annotation.Order;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
Expand All @@ -28,6 +29,7 @@
* @since 0.1
*/
@ControllerAdvice
@Order(200)
public class GlobalExceptionAdvice implements ApplicationContextAware {

private final Logger logger = LoggerFactory.getLogger(GlobalExceptionAdvice.class);
Expand Down Expand Up @@ -89,7 +91,7 @@ private ResponseStatus fromExceptionClass(Class<? extends Throwable> clazz) {
}
}

return responseStatusFactory.defaultFail();
return responseStatusFactory.defaultError();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package com.feiniaojin.gracefulresponse.advice;

import com.feiniaojin.gracefulresponse.GracefulResponseProperties;
import com.feiniaojin.gracefulresponse.api.ResponseFactory;
import com.feiniaojin.gracefulresponse.api.ResponseStatusFactory;
import com.feiniaojin.gracefulresponse.api.ValidationStatusCode;
import com.feiniaojin.gracefulresponse.data.Response;
import com.feiniaojin.gracefulresponse.data.ResponseStatus;
import org.springframework.core.annotation.Order;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExecutionChain;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@ControllerAdvice
@Order(100)
public class ValidationExceptionAdvice {

@Resource
private RequestMappingHandlerMapping mapping;

@Resource
private ResponseStatusFactory responseStatusFactory;

@Resource
private ResponseFactory responseFactory;

@Resource
private GracefulResponseProperties gracefulResponseProperties;

@ExceptionHandler(value = {BindException.class, ValidationException.class, MethodArgumentNotValidException.class})
@ResponseBody
public Response exceptionHandler(Exception e) throws Exception {

if (e instanceof BindException) {
ResponseStatus responseStatus = this.fromBindException(e);
return responseFactory.newInstance(responseStatus);
}

if (e instanceof MethodArgumentNotValidException) {
ResponseStatus responseStatus = this.fromMethodArgumentNotValidException(e);
return responseFactory.newInstance(responseStatus);
}

if (e instanceof ConstraintViolationException) {
ResponseStatus responseStatus = this.fromConstraintViolationException(e);
return responseFactory.newInstance(responseStatus);
}

return responseFactory.newFailInstance();
}

private ResponseStatus fromMethodArgumentNotValidException(Exception e) throws Exception {
MethodArgumentNotValidException me = (MethodArgumentNotValidException) e;
List<ObjectError> allErrors = me.getBindingResult().getAllErrors();
String msg = allErrors.stream().map(s -> s.getDefaultMessage()).collect(Collectors.joining(";"));
String code = this.determineErrorCode();
return responseStatusFactory.newInstance(code, msg);
}

private String determineErrorCode() throws Exception {
Method method = this.currentControllerMethod();
ValidationStatusCode validateStatusCode = method.getAnnotation(ValidationStatusCode.class);
if (validateStatusCode == null) {
validateStatusCode = method.getDeclaringClass().getAnnotation(ValidationStatusCode.class);
}
if (validateStatusCode != null) {
return validateStatusCode.code();
}
return gracefulResponseProperties.getDefaultValidateErrorCode();
}

private Method currentControllerMethod() throws Exception {
RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) requestAttributes;
HandlerExecutionChain handlerChain = mapping.getHandler(sra.getRequest());
HandlerMethod handler = (HandlerMethod) handlerChain.getHandler();
Method method = handler.getMethod();
return method;
}

private ResponseStatus fromConstraintViolationException(Exception e) throws Exception {

ConstraintViolationException exception = (ConstraintViolationException) e;
Set<ConstraintViolation<?>> violationSet = exception.getConstraintViolations();
String msg = violationSet.stream().map(s -> s.getConstraintDescriptor().getMessageTemplate()).collect(Collectors.joining(";"));
String code = this.determineErrorCode();
return responseStatusFactory.newInstance(code, msg);
}

private ResponseStatus fromBindException(Exception e) throws NoSuchFieldException {

String code;

BindException bindException = (BindException) e;
FieldError fieldError = bindException.getFieldError();
String fieldName = fieldError.getField();
Object target = bindException.getTarget();
Field declaredField = target.getClass().getDeclaredField(fieldName);
declaredField.setAccessible(true);
ValidationStatusCode annotation = declaredField.getAnnotation(ValidationStatusCode.class);
declaredField.setAccessible(false);

//属性上找不到注解,尝试获取类上的注解
if (annotation == null) {
annotation = target.getClass().getAnnotation(ValidationStatusCode.class);
}

if (annotation != null) {
code = annotation.code();
} else {
code = gracefulResponseProperties.getDefaultValidateErrorCode();
}

String msg = bindException.getAllErrors()
.stream().map(s -> s.getDefaultMessage())
.collect(Collectors.joining(";"));

return responseStatusFactory.newInstance(code, msg);
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package com.feiniaojin.gracefulresponse.api;


import java.lang.annotation.*;
import com.feiniaojin.gracefulresponse.defaults.DefaultConstants;

import java.lang.annotation.*;

/**
* 异常映射别名,把某个异常设置为外部异常的别名,以便自定义错误码和提示信息
Expand All @@ -21,19 +22,19 @@
*
* @return 异常对应的错误码
*/
String code() default "ERROR";
String code() default DefaultConstants.DEFAULT_ERROR_CODE;

/**
* 异常信息.
*
* @return 异常对应的提示信息
*/
String msg() default "Poor network quality!";
String msg() default DefaultConstants.DEFAULT_ERROR_MSG;

/**
* 作为某个异常的别名
* 作为某些异常的别名
*
* @return
*/
Class<? extends Throwable> aliasFor();
Class<? extends Throwable>[] aliasFor();
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public interface ResponseStatusFactory {
*
* @return
*/
ResponseStatus defaultFail();
ResponseStatus defaultError();


/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.feiniaojin.gracefulresponse.api;

import com.feiniaojin.gracefulresponse.defaults.DefaultConstants;

import java.lang.annotation.*;

/**
* 指定参数校验的异常码
*/
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface ValidationStatusCode {

/**
* 异常对应的错误码.
*
* @return 异常对应的错误码
*/
String code() default DefaultConstants.DEFAULT_ERROR_CODE;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.feiniaojin.gracefulresponse.defaults;

/**
* 默认的响应码和提示信息
*/
public class DefaultConstants {

/**
* 默认的成功响应码
*/
public static final String DEFAULT_SUCCESS_CODE = "0";

/**
* 默认的成功提示信息
*/
public static final String DEFAULT_SUCCESS_MSG = "ok";

/**
* 默认的错误码
*/
public static final String DEFAULT_ERROR_CODE = "1";

/**
* 默认的错误提示
*/
public static final String DEFAULT_ERROR_MSG = "error";

}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ public Response newSuccessInstance(Object payload) {
@Override
public Response newFailInstance() {
Response bean = this.newEmptyInstance();
bean.setStatus(responseStatusFactory.defaultFail());
bean.setStatus(responseStatusFactory.defaultError());
return bean;
}

Expand Down
Loading

0 comments on commit f2aab04

Please sign in to comment.