石家庄网站建站公司,阿里云服务器怎么用,娄底网站建设的公司,推广比较好的网站简介#xff1a;在Java程序开发中#xff0c;命名和应用分层无疑是广大后端同胞的两大“痛点”#xff0c;本文提供一种基于领域模型的轻量级应用分层结构设计#xff0c;供大家参考。下面按分层结构、分层明细、调用关系、各层规范和通用代码工具展开介绍。 作者 | 阿卓 来…简介在Java程序开发中命名和应用分层无疑是广大后端同胞的两大“痛点”本文提供一种基于领域模型的轻量级应用分层结构设计供大家参考。下面按分层结构、分层明细、调用关系、各层规范和通用代码工具展开介绍。 作者 | 阿卓 来源 | 阿里技术公众号
序言
在Java程序开发中命名和应用分层无疑是广大后端同胞的两大“痛点”本文提供一种基于领域模型的轻量级应用分层结构设计供大家参考。下面按分层结构、分层明细、调用关系、各层规范和通用代码工具展开介绍。
一 分层结构 web前端请求层
通过调用业务层服务处理前端的请求。
biz业务层
提供封装好的能力并通过对能力进行组装、编排进行业务逻辑处理。
dal数据层
对底层数据源进行增删改查操作。
client外部请求层
定义暴露给其他应用的接口。
common外部公共层
定义暴露给外部的公共类。
facade外观层
通过调用业务层服务处理外部应用的请求。
二 分层明细
web前端请求层 biz业务层 dal数据层 client外部请求层 common外部公共层 facade外观层 start启动类
qatest测试类
三 调用关系 注意点
服务和服务直接可以互相调用服务可以调用多个域的域能力域能力是封装好的最小颗粒度的能力不可互相调用查询服务直接调用manager不调用域能力
四 各层规范
web前端请求层
定义统一的异常处理切面处理业务异常和其他运行时异常
biz业务层
内部服务不做异常处理和返回result封装类异常都抛给web层和facade层处理。查询服务和其他服务区分开单独放在一个包中能力唯一对应一个域且是封装好的最小颗粒度的能力。外部服务要在remote中做好异常处理和封装业务层中的common类为仅在应用内部使用的公共类
dal数据层
mapper要按不同类型的数据源分开存放如adb和xdb。
common外部公共层
common只存放暴露给外部的实体类、常量和枚举暴露给外部的dto只保留外部必要的字段其他字段如feature等不可存在。
facade外观层
定义统一的异常处理切面处理业务异常和其他运行时异常facade层的hsf实现类只做简单的参数校验和转化不要写业务逻辑。
五 通用代码和工具
web前端请求层
统一异常处理切面
RestControllerAdvice
public class RestExceptionHandler {ResponseStatus(HttpStatus.OK)ExceptionHandler(Exception.class)public Result system(HttpServletRequest req, Exception e) {AllLoggers.EXCEPTION.error(RestExceptionHandler.system|servlet:{}|method:{}|code:{}|msg:{},req.getServletPath(),req.getMethod(), e.getMessage(), e);return Result.error(ResultCode.BASE.SYSTEM_ERROR);}ResponseStatus(HttpStatus.OK)ExceptionHandler(BusinessException.class)public Result business(HttpServletRequest req, BusinessException e) {AllLoggers.EXCEPTION.error(RestExceptionHandler.business|servlet:{}|method:{}|code:{}|msg:{},req.getServletPath(),req.getMethod(), e.getMessage(), e);return Result.error(e.getErrorCode(), e.getErrorMessage());}
}
biz业务层
统一日志打印工具类
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;public interface AllLoggers {/*** 应用日志*/Logger APPLICATION LoggerFactory.getLogger(APPLICATION);/*** 异常日志*/Logger EXCEPTION LoggerFactory.getLogger(EXCEPTION);/*** 业务日志*/Logger BIZ LoggerFactory.getLogger(BIZ);/*** hsf日志*/Logger HSF LoggerFactory.getLogger(HSF);/*** 入口日志*/Logger MTOP LoggerFactory.getLogger(MTOP);} ?xml version1.0 encodingUTF-8?configuration !-- https://github.com/spring-projects/spring-boot/blob/v1.5.13.RELEASE/spring-boot/src/main/resources/org/springframework/boot/logging/logback/defaults.xml -- include resourceorg/springframework/boot/logging/logback/defaults.xml / property resourceapplication.properties /property property nameAPP_NAME valuetoms / property nameLOG_PATH value${user.home}/${APP_NAME}/logs / property nameLOG_FILE value${LOG_PATH}/toms-root.log / appender nameAPPLICATIONclassch.qos.logback.core.rolling.RollingFileAppender file${LOG_FILE}/toms-root.log /file encoder pattern ![CDATA[%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%level] [traceId:%X{EAGLEEYE_TRACE_ID}] [%class:%line] - %m %n ]] /pattern charsetUTF-8 /charset /encoder rollingPolicy classch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy fileNamePattern${LOG_PATH}/logs_saved/toms-root.%d{yyyy-MM-dd}.%i.log /fileNamePattern maxHistory5 /maxHistory maxFileSize1GB /maxFileSize totalSizeCap20GB /totalSizeCap /rollingPolicy /appender appender nameCONSOLE classch.qos.logback.core.ConsoleAppender encoder pattern${CONSOLE_LOG_PATTERN} /pattern charsetutf8 /charset /encoder /appender !--业务日志-- appender nameTOMS-BIZ-APPENDERclassch.qos.logback.core.rolling.RollingFileAppender File${LOG_PATH}/toms-biz.log /File rollingPolicy classch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy FileNamePattern${LOG_PATH}/logs_saved/toms-biz.%d{yyyy-MM-dd}.%i.log /FileNamePattern maxHistory5 /maxHistory maxFileSize2GB /maxFileSize totalSizeCap20GB /totalSizeCap /rollingPolicy encoder pattern ![CDATA[%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%level] [traceId:%X{EAGLEEYE_TRACE_ID}] [%class:%line] - %m %n ]] /pattern charsetUTF-8 /charset /encoder /appender !--hsf日志-- appender nameTOMS-HSF-APPENDERclassch.qos.logback.core.rolling.RollingFileAppender File${LOG_PATH}/toms-hsf.log /File rollingPolicy classch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy FileNamePattern${LOG_PATH}/logs_saved/toms-hsf.%d{yyyy-MM-dd}.%i.log /FileNamePattern maxHistory5 /maxHistory maxFileSize2GB /maxFileSize totalSizeCap20GB /totalSizeCap /rollingPolicy encoder pattern ![CDATA[%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%level] [traceId:%X{EAGLEEYE_TRACE_ID}] [%class:%line] - %m %n ]] /pattern charsetUTF-8 /charset /encoder /appender !-- 通用错误日志 -- appender nameTOMS-ERROR-APPENDERclassch.qos.logback.core.rolling.RollingFileAppender File${LOG_PATH}/toms-error.log /File filter classch.qos.logback.classic.filter.LevelFilter levelERROR /level onMatchACCEPT/onMatch onMismatchDENY/onMismatch /filter rollingPolicy classch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy FileNamePattern${LOG_PATH}/logs_saved/toms-error.%d{yyyy-MM-dd}.%i.log /FileNamePattern maxHistory5 /maxHistory maxFileSize2GB /maxFileSize totalSizeCap10GB /totalSizeCap /rollingPolicy encoder pattern ![CDATA[%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%level] [traceId:%X{EAGLEEYE_TRACE_ID}] [%class:%line] - %m %n ]] /pattern charsetUTF-8 /charset /encoder /appender !-- 异常日志 -- appender nameTOMS-EXCEPTION-APPENDERclassch.qos.logback.core.rolling.RollingFileAppender File${LOG_PATH}/toms-exception.log /File rollingPolicy classch.qos.logback.core.rolling.TimeBasedRollingPolicy FileNamePattern${LOG_PATH}/logs_saved/toms-exception.%d{yyyy-MM-dd}.log /FileNamePattern maxHistory5 /maxHistory /rollingPolicy encoder pattern![CDATA[%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%level] [traceId:%X{EAGLEEYE_TRACE_ID}] [%class:%line] - %m %n ]] /pattern charsetUTF-8 /charset /encoder /appender logger nameHSF level${logback.info.level} additivityfalse appender-ref refTOMS-HSF-APPENDER/ /logger logger nameBIZ level${logback.info.level} additivityfalse appender-ref refTOMS-BIZ-APPENDER/ appender-ref refTOMS-ERROR-APPENDER/ /logger logger nameEXCEPTION level${logback.info.level} additivityfalse appender-ref refTOMS-EXCEPTION-APPENDER/appender-ref refTOMS-ERROR-APPENDER/ /logger root levelINFO appender-ref refCONSOLE / /root/configuration
单位转化工具类
public class UnitConvertUtils {/*** 米和千米的进率*/public static final double RATE_OF_METRE_AND_KILOMETRE 1000d;public static final int INT_RATE_OF_METRE_AND_KILOMETRE 1000;/*** 分和元的进率*/public static final double RATE_OF_FEN_AND_YUAN 100d;/*** 立方厘米和立方米的进率*/public static final double INT_RATE_OF_CM3_AND_M3 1000000d;/*** 米转千米** param toConvert* return 异常返回null*/public static Double convertMetre2Kilometre(Long toConvert) {if (toConvert null) {return null;}return toConvert / RATE_OF_METRE_AND_KILOMETRE;}/*** 千米转米** param toConvert* return 异常返回null*/public static Long convertKilometre2Metre(Double toConvert) {if (toConvert null) {return null;}BigDecimal bigDecimal BigDecimal.valueOf(toConvert);BigDecimal factorBigDecimal BigDecimal.valueOf(RATE_OF_METRE_AND_KILOMETRE);return bigDecimal.multiply(factorBigDecimal).longValue();}/*** 元转分** param toConvert* return 异常返回null*/public static Long convertYuan2Fen(Double toConvert) {if (toConvert null) {return null;}BigDecimal bigDecimal BigDecimal.valueOf(toConvert);BigDecimal factorBigDecimal BigDecimal.valueOf(RATE_OF_FEN_AND_YUAN);return bigDecimal.multiply(factorBigDecimal).longValue();}/*** 元转分** param toConvert* return 异常返回null*/public static Long convertYuan2Fen(String toConvert) {if (toConvert null) {return null;}BigDecimal bigDecimal BigDecimal.valueOf(ConvertUtils.convertString2Double(toConvert));BigDecimal factorBigDecimal BigDecimal.valueOf(RATE_OF_FEN_AND_YUAN);return bigDecimal.multiply(factorBigDecimal).longValue();}/*** 分转元** param price* return*/public static String convertFen2Yuan(Long price) {if (price null) {return null;}return BigDecimal.valueOf(price).divide(new BigDecimal(RATE_OF_FEN_AND_YUAN)).toString();}/*** 里程米转换为千米** param distance* return*/public static Double meter2Kilometer(Long distance) {if (distance null) {return null;}BigDecimal meter BigDecimal.valueOf(distance);BigDecimal kilometer meter.divide(new BigDecimal(INT_RATE_OF_METRE_AND_KILOMETRE));return kilometer.doubleValue();}/*** 立方厘米转立方米** param volume* return*/public static String convertCm32M3(Long volume) {if (volume null) {return null;}return BigDecimal.valueOf(volume).divide(new BigDecimal(INT_RATE_OF_CM3_AND_M3)).toString();}}原文链接
本文为阿里云原创内容未经允许不得转载。