服务层和控制器中的代码分离

Posted

技术标签:

【中文标题】服务层和控制器中的代码分离【英文标题】:Code Separation in Service Layer and Controller 【发布时间】:2019-04-13 17:31:28 【问题描述】:

我已经为我的应用程序的重置密码和其他部分编写了代码, 我想将服务层与 dao 和控制器分开; 我的控制器代码是:

@RequestMapping(value = "", method = RequestMethod.PUT)
public ResponseModel resetPassword(@Valid @RequestBody AuthenticationRequestModel authenticationRequestModel, HttpServletRequest request) 
    String ip = WebUtils.getClientIp(request);
    Optional<SecuritySMS> securitySMS = securitySMSService.getLastValidSMS(authenticationRequestModel.getMobile());
    if (!securitySMS.isPresent()) 
        return new ResponseModel(messages.get("sms.security.expired"), ResponseModel.ResponseStatus.ERROR);
    
    SecuritySMS sms = securitySMS.get();
    if (!sms.isConfirmed()) 
        return new ResponseModel(messages.get("sms.security.expired"), ResponseModel.ResponseStatus.ERROR);
     else if (!sms.getIp().equalsIgnoreCase(ip)) 
        return new ResponseModel(messages.get("sms.security.ip.changed"), ResponseModel.ResponseStatus.ERROR);
    
    Optional<User> user = userService.findByMobile(sms.getMobile());
    if (!user.isPresent()) 
        return new ResponseModel(messages.get("sms.reset.user.nonexistent"), ResponseModel.ResponseStatus.ERROR);
    

    userService.updatePassword(user.get(), authenticationRequestModel.getPassword());
    return authHelper.loginWithHttpResponse(authenticationRequestModel);

我对将代码移动到服务层感到困惑;上述方法是正确的还是必须将某些代码(例如下面的代码)移至服务层?如果我将此代码移动到服务层,我怎样才能得到响应?布尔值(不可接受,因为我想向用户返回正确的消息),字符串还是异常?;

String ip = WebUtils.getClientIp(request);
Optional<SecuritySMS> securitySMS = securitySMSService.getLastValidSMS(authenticationRequestModel.getMobile());
if (!securitySMS.isPresent()) 
    return new ResponseModel(messages.get("sms.security.expired"), ResponseModel.ResponseStatus.ERROR);

SecuritySMS sms = securitySMS.get();
if (!sms.isConfirmed()) 
    return new ResponseModel(messages.get("sms.security.expired"), ResponseModel.ResponseStatus.ERROR);
 else if (!sms.getIp().equalsIgnoreCase(ip)) 
    return new ResponseModel(messages.get("sms.security.ip.changed"), ResponseModel.ResponseStatus.ERROR);

Optional<User> user = userService.findByMobile(sms.getMobile());
if (!user.isPresent()) 
    return new ResponseModel(messages.get("sms.reset.user.nonexistent"), ResponseModel.ResponseStatus.ERROR);

【问题讨论】:

【参考方案1】:

MVS 只是一种简化,并不是完美的方法。这就是为什么它提出了这么多类似的问题。

控制器应该输入多少逻辑? 模型应该包含任何逻辑吗? 视图应该包含逻辑吗?

这样的问题很难回答,但控制器需要验证输入并在需要时重定向到视图。您的代码确实看起来很像域逻辑,稍后应该在服务中使用,但它显然更容易在您的控制器中管理。对于领域逻辑(也称为业务逻辑、业务规则和领域知识),我们可以将其解释为做出关键业务决策的逻辑。

确实,您是在 Controller 中做出决定,但在服务中管理这些决定会使解决方案复杂化。所以,我就把它留在那里,反正最后,除了你和你的团队之外,没有人会为这段代码做出贡献,所以如果你对它感到满意,那很好。

但是,如果您要移动代码,我建议您使用异常。在我看来,服务应该只返回所需的模型或资源。最好使用异常处理错误。

【讨论】:

以上是关于服务层和控制器中的代码分离的主要内容,如果未能解决你的问题,请参考以下文章

排球计分程序——总结

struts中的action是控制层,为啥不是业务层呢?控制层和业务层有啥区别?怎么样分辨呢?

11.3 Go 开发博客

Android开发在代码中控制UI界面

动作过滤器:如何调用服务层和异步方法

一个项目中说系统分为表现层控制层逻辑层DAO层和最终数据库五层架构