浅谈 SpringMVC 中各层职责的设计

2,951 阅读4分钟

SpringMVC

SpringMVC应该是目前web开发最常用的框架。他的项目结构也相对固定,一般都会有以下几层。

  • controller层
  • service层
  • mapper接口层
  • 实体层
  • 可能还有什么 DTO VO 等层次。

这里主要讲下controller层 和 service层,因为我实际工作中发现,什么该放在controller层,什么该放在 service层,似乎每家公司都有自己的做法。

最近一个项目是这样安排的

public class DepartmentController {
    @Autowired
    private DepartmentService departmentService;

    /**
     * 删除部门
     * @param departmentId
     * @return
     */
    @RequestMapping(value = "/department", method= RequestMethod.DELETE)
    public Result delete(String departmentId){
        return departmentService.delete(departmentId);
    }
}


public class DepartmentService {
    @Autowired
    private DepartmentMapper departmentMapper;
    @Autowired
    private UserService userService;

    /**
     * 删除部门
     * @param departmentId
     * @return
     */
    @RequestMapping(value = "department", method= RequestMethod.DELETE)
    public Result delete(String departmentId){
        if(departmentId == null || "".equals(departmentId)){
            return new FailResult("部门id不合法");
        }
        //删除部门前,查看部门下是否存在人员
        Result result =  userService.getUserList(departmentId);
        //拆解result 找出结果
        List<User> List = result.getDate();
        if(if list != null && list.size > 0){
            return new FailResult("部门下是否存在人员");
        }
        int i =  departmentService.delete(departmentId);
        if(i == 1){
            return new SuccessResult<Boolean>(true);
        }
        return new FailResult("删除失败");
    }
}

上面代码中,Controller层的任务非常简单,接收前端的参数然后传给service,service处理完后返回最终结果,至于 参数传没穿,格式对不对,甚至最后返回结果的封装,都放到service中去处理。
我们可以看到service的任务非常集中,非常重,而Controller的任务非常轻,就只做了一个转发的操作。其实这样分配非常不合理,特别是 最终返回结果的封装,非常不应该放在service里面。
上面代码中我们想删除一个部门,先要判断部门下是否存在人员,于是我们调用人员的service,结果他返回的是给前端展示的对象,于是我们不得不,拆解对象,取出我们想要的结果,非常麻烦。如果他把Result的封装放在Controller层就非常方便了,service层可以直接返回处理结果。

经过这次项目后,我一直在思考,Controller层和service层的职责应该怎样设计才好。下面说下我的看法。

Controller层

Controller层是前端直接接触的层,离用户最近,同时也代表着一个接口。
他的任务应该是你按照我的要求传递规定的参数,并且参数的值也合法的话,我就返回给你想要的结果。
从上面分析可以看出Controller层关注点在两个方面,请求参数,和响应结果。

因此,controller层的任务是

  • 在调用业务层(Serivce)之前,保证业务所需要的参数的个数和内容都要合法。换句话说,在调用service之前,service要求的每个参数都要有,并且在内容上要合法,而不要把这些操作延迟都service中去做。
    这样设计的理由也很简单,你参数都不对,还有必要进入业务层去执行吗?
  • 不要让业务层(Serivce)返回最终结果(前端需要的结果)。这个也很好理解
    • mapper层应该返回查询数据库的结果。
    • service层应该返回业务结果
    • controller层应该根据业务层的返回结果做判断,然后封装成前端需要的最终结果

所以Controller层的职责总结起来就两点。

  • 在调用业务方法之前,保证业务方法所需参数的合法性
  • 接收业务方法的返回值,根据返回值做判断,然后封装成前端需要的最终结果

Service层

service层负责的是业务的处理,它的关注的是业务,不应该做与业务没有直接关系的事情。 比如:

  • 检查业务参数的合法性。乍一看好像跟业务相关,但我们换一个角度思考,业务参数不合法就没有必要进入到业务方法里面来,再说业务参数是Controller层传递过来的,你把不合法的参数传递进来是想干什么。
  • 业务层只返回业务结果,不返回最终结果。这点很容易理解,应为业务结果不一定就是最终结果,业务层只要负责好自己的业务就好了,至于最终结果,当然是由接口(Controller)层去返回。

这样设计的原因是希望各层职责分明,每层负责自己的事,这样做还有一个好处,那就是,不会存在某层非常 “重”,而某层又非常 “轻” 的情况。