当前位置: 首页> 房产> 政策 > 俱乐部logo免费设计在线生成_尼高品牌设计_扬州网站seo_新产品如何快速推广市场

俱乐部logo免费设计在线生成_尼高品牌设计_扬州网站seo_新产品如何快速推广市场

时间:2025/7/28 4:37:55来源:https://blog.csdn.net/2302_76435884/article/details/147030433 浏览次数:0次
俱乐部logo免费设计在线生成_尼高品牌设计_扬州网站seo_新产品如何快速推广市场

目录

一、统一数据返回格式

1.引入统一数据返回格式

2.学习使用统一数据返回格式

support方法

beforeBodyWrite方法

统一数据返回格式具体逻辑

 使用统一数据返回格式存在的问题

解决方法:

 统一数据返回格式的优点

 统一数据返回格式代码实现(包含了拦截器):

二、统一异常处理


 

一、统一数据返回格式

 在Spring框架中实现统一数据返回格式是构建规范化API的核心需求,它能让所有接口的响应保持一致的JSON结构,方便前端处理。

1.引入统一数据返回格式

  • 添加统一数据返回格式之前:

不同的接口返回的格式不一样,杂乱无章,很混乱,对于前端来说不方便处理(上图只是其中一个接口)。

  • 添加统一数据返回格式之后:

可以看到,添加之后, 不同接口的返回数据的格式变得更加规范,方便前端处理。

2.学习使用统一数据返回格式

统一的数据返回格式使用 @ControllerAdvice 和 ResponseBodyAdvice 的方式实现 @ControllerAdvice 表示控制器通知类。添加 ResponseAdvice 来实现 ResponseBodyAdvice 接口,并在类上添加 @ControllerAdvice 注解。

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, 
MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest 
request, ServerHttpResponse response) {return Result.success(body);}
}

support方法

该方法是判断是否要执行 beforeBodyWrite 方法,true为执行,false不执行,通过该方法可以选择哪些类或哪些方法的response要进行处理,其他的不进行处理。

beforeBodyWrite方法

对响应数据结果进行统一处理

统一数据返回格式具体逻辑

以下面的代码为例:

@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {return Result.SUCCESS(body);}

 补充:Result是一个实体类,封装了对应格式的属性(status,message...)以及静态方法,其中SUCCESS就是其中一个静态方法。

 当controller的接口方法返回 不同类型的值时,会把该接口方法的返回值作为body参数,然后再调用Result.SUCCESS(body),让该接口方法的返回值被Result.SUCCESS(body)的值替代。总结就是:通过 ResponseBodyAdvice 将 Controller 方法的返回值统一包装为 Result 对象

  • 比如:

当接口返回类型boolean且返回true时,true作为body,然后再调用Result.SUCCESS(body),最后该接口返回值得到了封装后的结果。

 使用统一数据返回格式存在的问题

当接口返回值类型为String时,会抛出异常:

异常表示为:Result类型的不能转换为String类型。其中只有返回结果为String类型时才会有这种错误发生。

原因:当接口返回的数据类型是String时,Spring会选择 StringHttpMessageConverter,该转换器只能处理 String 类型的返回值,又因为使用了统一数据返回格式,该接口实际返回的是Result类型的对象,而 StringHttpMessageConverter无法将 Result 对象转换为String,导致抛出异常:“Result cannot be cast to java.lang.String”。

解决方法:
  • 可以手动序列化Result对象为JSON字符串,最终返回的是一个String类型的JSON字符串,与控制器中声明的String返回类型兼容。
  • 同时我们还可以进行优化:把接口返回值类型为Result的进行单独处理,避免出现嵌套的情况。
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {ObjectMapper mapper = new ObjectMapper();//supports方法是判断是否要执行beforeBodyWrite方法,true为执行,false不执行@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@SneakyThrows@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {//body为其他接口的返回结果//返回结果更加灵活,避免出现嵌套情况if (body instanceof Result){return body;}//如果返回结果为String类型,使用SpringBoot内置提供的Jackson来实现信息的序列化if (body instanceof String){return mapper.writeValueAsString(Result.SUCCESS(body));}//如果返回结果为其他类型,把返回结果作为参数return Result.SUCCESS(body);}
}

 统一数据返回格式的优点

  • 方便前端程序员能更好的接收和解析后端数据接口返回的数据;
  • 降低前端程序员和后端程序员的沟通成本,按照某个格式实现就可以了,因为所有接口都是这样返回的;
  • 有利于项目统一数据的维护和修改;
  • 有利于后端技术部门的统一规范的标准制定,不会出现奇怪的返回内容。

 统一数据返回格式代码实现(包含了拦截器):

  • 常量层
public class Constants {public static final String SUCCESS = "SUCCESS";public static final String FAILURE = "FAILURE";
}
  • 实现统一功能类:ResponseAdvice
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {ObjectMapper mapper = new ObjectMapper();//supports方法是判断是否要执行beforeBodyWrite方法,true为执行,false不执行@Overridepublic boolean supports(MethodParameter returnType, Class converterType) {return true;}@SneakyThrows@Overridepublic Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {//body为其他接口的返回结果//返回结果更加灵活if (body instanceof Result){return body;}//如果返回结果为String类型,使用SpringBoot内置提供的Jackson来实现信息的序列化if (body instanceof String){return mapper.writeValueAsString(Result.SUCCESS(body));}//如果返回结果为其他类型,把返回结果作为参数return Result.SUCCESS(body);}
}
  • 实体层User
@Data
public class User {private String username;private String password;
}
  •  实体层Result
@Data
public class Result<T> {private String status;private T message;public static <T>Result<T> SUCCESS(T message) {Result<T> result = new Result<>();result.setStatus(Constants.SUCCESS);result.setMessage(message);return result;}public static <T>Result<T> FAIL(T message) {Result<T> result = new Result<>();result.setStatus(Constants.FAILURE);result.setMessage(message);return result;}
}
  • 控制层
@RestController
@RequestMapping("/user")
public class UserController {@AutowiredGetUser getUser;@RequestMapping("/login")public Result login(String username, String password, HttpServletRequest request) {User user = getUser.getUser(username, password);if (user == null) {return Result.FAIL("账号或密码错误");}request.getSession().setAttribute("user", user);return Result.SUCCESS("账号密码正确,登录成功!!");}@RequestMapping("/enter")public String Enter(){return "进入enter成功哈哈";}
}
  • Service层
@Service
public class GetUser {public User getUser(String username, String password) {if (username == null || password == null) {return null;}if (!"zhangsan".equals(username) ||!"123".equals(password)) {return null;}User user = new User();user.setUsername("zhangsan");user.setPassword("123");return  user;}
}
  • 注册拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {//自定义拦截器对象@Autowiredprivate LoginInterceptor loginInterceptor;@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(loginInterceptor).addPathPatterns("/**")//排除拦截的页面,登录页.excludePathPatterns("/user/login");}
}
  • 定义拦截器
@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request,HttpServletResponse response, Object handler) throws Exception {log.info("拦截开始");HttpSession session = request.getSession();User user = (User) session.getAttribute( "user");if (user == null) {log.info("被拦截");return false;}else {log.info("不拦截,放行");return true;}}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response,Object handler, ModelAndView modelAndView) throws Exception {log.info("enter方法执行后");}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {log.info("LoginInterceptor 视图渲染完毕后执⾏,最后执⾏");}
}

二、统一异常处理

统一异常处理使用的是 @ControllerAdvice + @ExceptionHandler 来实现的,@ControllerAdvice 表示控制器通知类,@ExceptionHandler是异常处理器,两个结合表示出现异常的时候执行某个通知,也就是执行某个方法事件。

@ControllerAdvice
@ResponseBody
public class ErrorAdvice {@ExceptionHandlerpublic Object handler(Exception e) {return Result.fail(e.getMessage());}
}

类名,方法名和返回值可以自定义,重要的是注解

使用@ResponseBody 是为了处理返回数据的接口,让返回的结果为序列化的数据(JSON/XML),而不是视图(HTML页面)。

以上代码表示,如果代码出现Exception异常(包括Exception的子类),就返回一个Result的对象,Result对象的设置参考  Result.fail(e.getMessage())。

    public static <T>Result<T> FAIL(T message) {Result<T> result = new Result<>();result.setStatus(Constants.FAILURE);result.setMessage(message);return result;}

在统一数据返回格式的代码基础上,我们可以针对不同的异常,返回不同的结果。

@ControllerAdvice
@ResponseBody
public class ErrorAdvice {@ExceptionHandlerpublic Object handler(Exception e) {return Result.FAIL(e.getMessage());}@ExceptionHandlerpublic Object handler(ArithmeticException e) {return Result.FAIL("发生ArithmeticException异常,异常信息:"+e.getMessage());}@ExceptionHandlerpublic Object handler(NullPointerException e) {return Result.FAIL("发生NullPointerException异常:"+e.getMessage());}
}

创建控制类模拟制造异常:

@RestController
@RequestMapping("/test")
public class TestController {@RequestMapping("/t1")public Integer t1(){String a = null;return a.length();}@RequestMapping("/t2")public Integer t2(){int a = 10/0;return a;}
}

运行结果:

 当有多个异常通知时,匹配顺序为当前类及其子类向上一次匹配 。

关键字:俱乐部logo免费设计在线生成_尼高品牌设计_扬州网站seo_新产品如何快速推广市场

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: