比如这两种怎样更好
public ActionResult GetSomething()
{
return _service.GetSometing(); //<- 返回包装好的结果
}
public ActionResult Getsomething()
{
try
{
return Ok(_service.Getsomething());
}
catch (ExceptionA ea)
{
return BadRequset();
}
catch (ExceptionB eb)
{
return NotFound();
}
}
同理还有参数校验要放在哪里头整。。
1
warcraft1236 2021-12-06 13:55:57 +08:00
validator 可以做校验的事情
|
2
justNoBody 2021-12-06 13:56:20 +08:00
选第二种,参数校验分情况。service 里面也需要有一定业务层上的校验,但基本的前端参数校验是建议放 controller 的。
|
3
X0ray 2021-12-06 14:01:33 +08:00
Exception 都在 Global Exception Handler 里面处理
所以,我更推荐不带异常处理的 return Ok(_service.Getsomething()) |
4
VeryZero 2021-12-06 14:17:58 +08:00
个人不喜欢在 service 里包装返回值,不利于复用。典型情况就是分页查询,有人喜欢 service 返回的是带分页信息的包装类,这样一旦有不分页的查询请求,就得再写一遍 service 。
|
5
justNoBody 2021-12-06 14:35:58 +08:00
@VeryZero 确实是,分页这种可以用工具类抽象成模版方法,或者用代理模式来解决,不要直接改 service
|
6
johnsona 2021-12-06 15:00:13 +08:00 via iPhone
ctroller 一把锁
|
7
wfd0807 2021-12-06 15:32:42 +08:00
看见过好多人纠结这个问题,尤其是 java spring 技术栈的
有些说逻辑复用、抽象、和展示层节藕,都对,但不是 service 层独有的特性 service 层的本质是“事务脚本”(这是 spring 官方某个大佬的观点,忘记出处了) 明白 service 是事务脚本以后,责任边界就很清晰了 |
8
wolfie 2021-12-06 15:34:22 +08:00
校验 Validator
业务异常,Service 直接抛出来,ControllerAdvise 或者自定义切面。 |
9
Inside 2021-12-06 15:38:54 +08:00 1
以下是我遵循的一些规范,供参考。
---- # 数据库访问 ⼒求在 controller 层向 datasource 层发起访问,不在 service 层发起。 # WHY ?! 在⼊⼝处就知道当前请求到底访问了哪些数据,无需⼀层层抽象来回跟踪,有助于减轻心智负担、事务控制。 有助于 service 层保持无状态,service 层需要什么数据,在方法参数中声明完整。 把 controller 视为组织者,service 视为参与者。 数据的获取、写⼊,由组织者负责。 数据的处理及运算,由参与者负责。 |
10
Edsie 2021-12-06 15:44:04 +08:00 1
Controller 层:数据清洗、数据组装
Service 层:具体的业务逻辑 你的 Controller 层太薄了,Service 层异常直接抛出就行,在 Controller 层做 ExceptionHandler 捕获。 参数校验可以看下 Java 的 Bean Validation JSR303 规范,但是大部分人都是在 Service 层做参数校验... 《凤凰架构》有一篇文章说的不错,(可以提供一些思路,条条框框太多也不是好事) http://icyfenix.cn/architect-perspective/general-architecture/system-security/verification.html |
11
Jooooooooo 2021-12-06 15:47:50 +08:00
后一种好
如果哪天要复用 service 后一种会更方便点. |
12
aababc 2021-12-06 15:48:18 +08:00
@Inside 我们最开始想希望遵循这个规则,但是数据的写入很难在 controller 中全部处理的,我们有一个下单的业务,数据的提供 用户,需要购买的产品 这些都是在 controller 中查询而后传入到 service 中,但是下单的具体的流程很难抽离到 controller 中。这样带来的问题就是,事物的嵌套不过好在很多框架都有事务的传播机制。
|
13
Leviathann 2021-12-06 16:08:13 +08:00
@Edsie 感觉这个很难分清,因为很多 crud 的业务逻辑就是数据组装。。
|
14
Edsie 2021-12-06 16:19:45 +08:00
@Leviathann 是的,所以也不要被条条框框限制,尽量遵循原则
|
15
Saxton 2021-12-06 16:26:15 +08:00
validator 不香吗
|
16
wx497657341 2021-12-06 16:26:35 +08:00
route
middleware controller request validator service logic entity transformer |
17
thtznet 2021-12-06 16:28:12 +08:00
选下面的方式,控制器层对 DTO 校验,然后直接传入 DTO 到应用层,控制器层因为要返回 HTTP Status ,所以你需要 try catch 包一下,具体的错误在应用层里进行 throw ,当然如果应用 DDD 的话,应用层也不要写业务,应用层调用领域层,业务写在领域层。
|
18
unco020511 2021-12-06 16:29:19 +08:00
一般场景不特别处理异常,异常统一捕获就行了
|
19
yiheweigui 2021-12-06 16:41:53 +08:00 6
自己给自己做的项目:
无 service ,无 dao ,只有 controller 和 util controller 的 action 访问一切,mybatic 的 mapper 直接放 controller 上或在 controller 手写 sql 。c 井就直接 dapper 放 controller 上访问任意,加入 redis 什么乱七八糟的各种库都在 util 或 controller 的注入上。 如若发现复用的获取数据或其他逻辑,则只把复用的提出来封装 service 或者 bll ,所以这一层顶多是复用的,如果不复用坚决没有这个,就是一个方法在很多地方都在用。 目的:看代码的人打开一个文件,查看一个方法,就能看出到底是在做什么,改动的时候非常方便。 如果一个方法很长,使用代码折叠 region 和详细注释。 如果抽象类确实有多个实现子类,才使用继承,而且一旦使用抽象类,必有多肽,绝对有多个不同子类逻辑会调用。 否则类就是类,基本不用 interface 。 异常统一处理。 给公司做的项目 dao ,service ,controller ,util ,bean ,各种加。 一个方法代码不超过 200 行,各种封装函数。 多使用 interface 和 impl ,管球他基本上只有一个子类。 dao ,service ,bean 什么的,每一层 interface ,impl 起码两个文件。 加的越多越复杂,越提现分层思想,越增加代码行数,文件数量也大,越在 jira ,禅道,tpad 这种东西上可以写工作量。 绝不做统一异常处理,controller 每个都 try catch ,耦合度越大越好。 如若 util 层增加一个接口方法,或者接口方法增加参数,连着 dao ,service ,controller ,bean 等到处修改。 这样在 git 提交的时候,发现改动文件多,在 jira 上工作量就写得漂亮。 关键是,整天开会,开完就这么写,速度也不快,让别人感觉自己非常忙,别人拿代码一看,确实封装方法多,绕来绕去,看一个功能起码打开五六个文件。 以前自己不喜欢这么做,但是公司的规范,企业文化把人逼成这样。 目前被他们搞疯了,已经去精神病院治疗抑郁症。 |
20
gowk 2021-12-07 11:31:56 +08:00
@yiheweigui 哈哈,C#,Java 混着写,确实容易疯
|