加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

后端开发实践系列——Spring Boot项目模板

发布时间:2019-07-24 15:50:23 所属栏目:建站 来源:无知者云
导读:在我的工作中,我从零开始搭建了不少软件项目,其中包含了基础代码框架和持续集成基础设施等,这些内容在敏捷开发中通常被称为第0个迭代要做的事情。但是,当项目运行了一段时间之后再来反观,我总会发现一些不足的地方,要么测试分类没有分好,要么基本的

在设计异常处理的框架时,需要考虑以下几点:

  • 向客户端提供格式统一的异常返回
  • 异常信息中应该包含足够多的上下文信息,最好是结构化的数据以便于客户端解析
  • 不同类型的异常应该包含唯一标识,以便客户端精确识别

异常处理通常有两种形式,一种是层级式的,即每种具体的异常都对应了一个异常类,这些类最终继承自某个父异常;另一种是单一式的,即整个程序中只有一个异常类,再以一个字段来区分不同的异常场景。层级式异常的好处是能够显式化异常含义,但是如果层级设计不好可能导致整个程序中充斥着大量的异常类;单一式的好处是简单,而其缺点在于表意性不够。

本文的示例项目使用了层级式异常,所有异常都继承自一个AppException:

  1. public abstract class AppException extends RuntimeException { 
  2.     private final ErrorCode code; 
  3.     private final Map<String, Object> data = newHashMap(); 

这里,ErrorCode枚举中包含了异常的唯一标识、HTTP状态码以及错误信息;而data字段表示各个异常的上下文信息。

在示例系统中,在没有找到订单时抛出异常:

  1. public class OrderNotFoundException extends AppException { 
  2.     public OrderNotFoundException(OrderId orderId) { 
  3.         super(ErrorCode.ORDER_NOT_FOUND, ImmutableMap.of("orderId", orderId.toString())); 
  4.     } 

在返回异常给客户端时,通过一个ErrorDetail类来统一异常格式:

  1. public final class ErrorDetail { 
  2.     private final ErrorCode code; 
  3.     private final int status; 
  4.     private final String message; 
  5.     private final String path; 
  6.     private final Instant timestamp; 
  7.     private final Map<String, Object> data = newHashMap(); 

最终返回客户端的数据为:

  1.   requestId: "d008ef46bb4f4cf19c9081ad50df33bd", 
  2.   error: { 
  3.     code: "ORDER_NOT_FOUND", 
  4.     status: 404, 
  5.     message: "没有找到订单", 
  6.     path: "/order", 
  7.     timestamp: 1555031270087, 
  8.     data: { 
  9.       orderId: "123456789" 
  10.     } 
  11.   } 

可以看到,ORDER_NOT_FOUND与data中的数据结构是一一对应的,也即对于客户端来讲,如果发现了ORDER_NOT_FOUND,那么便可确定data中一定存在orderId字段,进而完成精确的结构化解析。

后台任务与分布式锁

除了即时完成客户端的请求外,系统中通常会有一些定时性的例行任务,比如定期地向用户发送邮件或者运行数据报表等;另外,有时从设计上我们会对请求进行异步化处理。此时,我们需要搭建后台任务相关基础设施。Spring原生提供了任务处理(TaskExecutor)和任务计划(TaskSchedulor)机制;而在分布式场景下,还需要引入分布式锁来解决并发冲突,为此我们引入一个轻量级的分布式锁框架ShedLock。

启用Spring任务配置如下:

  1. @Configuration 
  2. @EnableAsync 
  3. @EnableScheduling 
  4. public class SchedulingConfiguration implements SchedulingConfigurer { 
  5.  
  6.     @Override 
  7.     public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { 
  8.         taskRegistrar.setScheduler(newScheduledThreadPool(10)); 
  9.     } 
  10.  
  11.     @Bean(destroyMethod = "shutdown") 
  12.     @Primary 
  13.     public TaskExecutor taskExecutor() { 
  14.         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 
  15.         executor.setCorePoolSize(2); 
  16.         executor.setMaxPoolSize(5); 
  17.         executor.setQueueCapacity(10); 
  18.         executor.setTaskDecorator(new LogbackMdcTaskDecorator()); 
  19.         executor.initialize(); 
  20.         return executor; 
  21.     } 
  22.  

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读