本文旨在提供业务访问的高效性,针对异常校验进行新的思路规划设计:
先校验正常的业务流程,不匹配再走异常,而不是一开始就校验异常(提高80%效率)
适用于:业务异常校验场景
8-2定律:业务中80%以上的场景都是正常的,剩余20%可能需要考虑异常
例如:国际业务中,校验到方 洲/省 城市 邮编
传统校验,从上到下:
提示1:到方洲/省份不对,提示洲/省份错误
提示1:如果城市不正确,提示城市错误
提示2:如果邮编不正确,提示邮编错误
改进异常校验:先校验正确业务场景,不匹配再逐层走异常校验逻辑 即
1.洲/省 +城市 + 邮编 有,走正常逻辑,异常走
2.城市 + 邮编 有,走正常逻辑,异常走;提示异常信息
3.邮编 有,走正常逻辑,异常走;提示异常信息
对于异常可以使用优雅的AOP思想返回异常信息处理;需要的异常自定义定义
- import com.system.entity.BusinessException;
- import org.springframework.stereotype.Component;
- import org.springframework.web.bind.annotation.ControllerAdvice;
- import org.springframework.web.bind.annotation.ExceptionHandler;
- import org.springframework.web.servlet.ModelAndView;
- import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
-
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Objects;
-
- /**
- * description:
- */
- @Component
- @ControllerAdvice
- public class GlobalExceptionAdvice {
-
- @ExceptionHandler
- public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Exception e) {
- ModelAndView modelAndView = new ModelAndView();
- MappingJackson2JsonView mappingJackson2JsonView = new MappingJackson2JsonView();
- Map
hashMap = new HashMap<>(); - if (Objects.nonNull(e)) {
- if (e instanceof BusinessException) {
- BusinessException e1 = (BusinessException) e;
- hashMap.put("code", e1.getCode());
- hashMap.put("success", false);
- hashMap.put("msg", e1.getMsg());
- }
- if (e instanceof IllegalArgumentException) {
- IllegalArgumentException e1 = (IllegalArgumentException) e;
- hashMap.put("code", 400);
- hashMap.put("success", false);
- hashMap.put("msg", e1.getMessage());
- } else {
- hashMap.put("code", 500);
- hashMap.put("success", false);
- hashMap.put("msg", e.getMessage());
- }
- }
- modelAndView.addAllObjects(hashMap);
- modelAndView.setView(mappingJackson2JsonView);
- return modelAndView;
- }
- }
import lombok.Data;
/**
* description:
*/
@Data
public class BusinessException extends RuntimeException{
private int code;
private int msg;
}
如果需要自定义注解场景可以使用拦截器处理方案
步骤1:自定义注解
import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface ResponseNotNull {
}
步骤2 自定义拦截器
import com.system.annotations.ResponseNotNull;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
/**
* description:
*/
@Service
public class ResponseNotNullInterceptor implements HandlerInterceptor {
private static final String RESPONSE_NOT_NULL_RESULT = "response_not_null_result";
/**
* 在请求前置中设置
*
* @param request
* @param response
* @param handler
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (Objects.nonNull(handler) && handler instanceof HandlerMethod) {
ResponseNotNull annotation = AnnotationUtils.findAnnotation(((HandlerMethod) handler).getMethod(), ResponseNotNull.class);
if (Objects.nonNull(annotation)) {
request.setAttribute(RESPONSE_NOT_NULL_RESULT, RESPONSE_NOT_NULL_RESULT);
return true;
}
}
return HandlerInterceptor.super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
步骤3 注册拦截器
import com.system.interceptors.ResponseNotNullInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* description: 拦截器添加地方
*/
@Configuration
public class AllWebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new ResponseNotNullInterceptor());
}
}
步骤4 返回处理
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.system.common.ResponseResult;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import java.util.Objects;
/**
* description:
*/
@Component
public class ResponseNotNullAdvice implements ResponseBodyAdvice {
private static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
private static final String RESPONSE_NOT_NULL_RESULT = "response_not_null_result";
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
Object attribute = RequestContextHolder.getRequestAttributes().getAttribute(RESPONSE_NOT_NULL_RESULT, RequestAttributes.SCOPE_SESSION);
if (Objects.nonNull(attribute)) {
return true;
}
return false;
}
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
if (body instanceof ResponseResult) {
return JSON.parseObject(JSON.toJSONString(body, YYYY_MM_DD_HH_MM_SS, JSONWriter.Feature.PrettyFormat));
}
return body;
}
}
上面采用了一些其他工具jar包如下:
com.alibaba.fastjson2 fastjson2 2.0.18