SimpleController 增加一个抛出异常的方法 。
@RestControllerpublic class SimpleController {@PostMapping("/users")public String register(@Valid @RequestBody UserInfoIDto userInfoIDto){System.out.println("开始注册用户...");return "success";}@GetMapping("/users")public Response<UserInfoIDto> list() {UserInfoIDto userInfoIDto = new UserInfoIDto();userInfoIDto.setUsername("monday");userInfoIDto.setAge(30);userInfoIDto.setPhone("123456789");if (true) {throw new APIException(ErrorCodeEnum.ERROR);}// 为了保持数据格式统一,必须使用Response包装一下return new Response<>(userInfoIDto);}}
文章插图
报错返回的格式 。
文章插图
不报错,返回的格式 。
文章插图
6. 去掉接口中的Response包装@RestControllerAdvice既可以全局拦截异常也可拦截指定包下正常的返回值,可以对返回值进行修改 。
@RestControllerAdvice(basePackages = {"com.example.validator.controller"})public class ResponseControllerAdvice implements ResponseBodyAdvice<Object> {/*** 对那些方法需要包装,如果接口直接返回Response就没有必要再包装了** @param returnType* @param aClass* @return 如果为true才会执行beforeBodyWrite*/@Overridepublic boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> aClass) {return !returnType.getParameterType().equals(Response.class);}@Overridepublic Object beforeBodyWrite(Object data, MethodParameter returnType, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest request, ServerHttpResponse response) {// String类型不能直接包装,所以要进行些特别的处理if (returnType.getGenericParameterType().equals(String.class)) {ObjectMapper objectMapper = new ObjectMapper();try {// 将数据包装在Response里后,再转换为json字符串响应给前端return objectMapper.writeValueAsString(new Response<>(data));} catch (JsonProcessingException e) {throw new APIException(ErrorCodeEnum.ERROR);}}// 这里统一包装return new Response<>(data);}}
@RestControllerpublic class SimpleController {@GetMapping("/users")public UserInfoIDto list() {UserInfoIDto userInfoIDto = new UserInfoIDto();userInfoIDto.setUsername("monday");userInfoIDto.setAge(30);userInfoIDto.setPhone("123456789");// 直接返回值,不需要再使用Response包装return userInfoIDto;}}
文章插图
7. 每个校验错误都对应不同的错误码
@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.FIELD})public @interface ValidateErrorCode {/** 校验错误码 code */int value() default 100000;}
@Datapublic class UserInfoIDto {@NotBlank@Email@ValidateErrorCode(value = https://www.isolves.com/it/cxkf/kj/2020-11-19/20000)private String email;@NotBlank@Pattern(regexp="^((13[0-9])|(15[^4,/D])|(18[0,3-9]))/d{8}$", message="手机号格式不正确")@ValidateErrorCode(value = 30000)private String phone;}
校验异常获取注解中的错误码 。@ExceptionHandler(MethodArgumentNotValidException.class)public Response<String> methodArgumentNotValidException(MethodArgumentNotValidException e) throws NoSuchFieldException {// 从异常对象中拿到ObjectError对象ObjectError objectError = e.getBindingResult().getAllErrors().get(0);// 参数的Class对象,等下好通过字段名称获取Field对象Class<?> parameterType = e.getParameter().getParameterType();// 拿到错误的字段名称String fieldName = e.getBindingResult().getFieldError().getField();Field field = parameterType.getDeclaredField(fieldName);// 获取Field对象上的自定义注解ValidateErrorCode annotation = field.getAnnotation(ValidateErrorCode.class);if (annotation != null) {return new Response<>(annotation.value(),objectError.getDefaultMessage());}// 然后提取错误提示信息进行返回return new Response<>(ErrorCodeEnum.VALIDATE_FAILED.getCode(), objectError.getDefaultMessage());}
文章插图
文章插图
8. 个别接口不统一包装响应有时候第三方接口回调我们的接口,我们的接口必须按照第三方定义的返回格式来,此时第三方不一定和我们自己的返回格式一样,所以要提供一种可以绕过统一包装的方式 。
@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD})public @interface NotResponseWrap {}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 矮脚乌龙茶的冲泡方法,优质乌龙茶和劣质乌龙茶的判别
- 核能发电的原理及其优缺点介绍
- 边销茶增值税政策,民贸企业和边销茶享受免征增值税优惠
- 养柴犬好吗 柴犬好养吗,柴犬优缺点分析
- 从AI香水到AI美妆 算法能否求出审美最优解?
- 使用区分优先级的负载分流法确保Netflix的可靠性
- 如何做到全屋WIFI无死角,MESH组网对比有哪些优势?
- 实木家具哪种板材好 实木家具的优点
- 近吸式抽油烟机有哪些优缺点
- 优雪电饭煲使用教程 优雪电饭煲合格吗