Java Web MVC Package如何组织的疑问

Java开发不久,请教各位:

项目概况

项目基于SSM框架,分层结构为controller -> service(interface & implementation) -> mapper,因为项目比较简单,基本就是贫血模型,model放在entity包下,跟数据库表一一对应

现在我请教的问题如下:

  1. controller里面的Method如果参数比较多,会用一个类对象去接收,一般是放在dto包下,并且类名命名为FooDTO吗?

  2. 返回给前端的对象,如果要求不高,并且单表直接Select出来,可以直接返回Entity或者List<Entity>。但是,如果是多张表join出来的结果,是不是需要定义一个类,比如命名为BarDTO,这个BarDTO通过MyBatisResultMap生成,并且经过mapper -> service -> controller -> ajax

  3. 第1点、第2点是不是在dto包下建立inputoutput包更好?inputcontroller参数的类,output用于存放service返回值的类

  4. controllerservice之间传递的参数一般是不是直接传DTO对象,然后在service中在构造entity去调用mapper方法?

  5. 第4点,如果类对象成员比较多,势必service方法充斥着很多set方法,如何解决呢?

  6. DTOvalidation是在controller里面做,还是在service里面做呢?

感谢各位不吝赐教!

阅读 5.4k
3 个回答

Q1:controller里面的Method如果参数比较多,会用一个类对象去接收,一般是放在dto包下,并且类名命名为FooDTO吗?

A1:的确是放在dto包下面,但是我们这里的命名不会是FooDto,因为光看这个名字看不出这个类到底是干嘛的。我们针对查询的:FooQueryParam,针对数据操作的:FooXXXCmd,XXX代表CRUD

Q2:返回给前端的对象,如果要求不高,并且单表直接Select出来,可以直接返回Entity或者List<Entity>。但是,如果是多张表join出来的结果,是不是需要定义一个类,比如命名为BarDTO,这个BarDTO通过MyBatis的ResultMap生成,并且经过mapper -> service -> controller -> ajax?

A2:这个我们不会叫做BarDto,而是叫做BarVm,Vm代表ViewModel,意思是专供显示用的Model,它可以根据具体情况将Entity的结果进行转换(比如身份证打码),组合(多个Entity组合成一个Vm)等动作。

如果这个数据不是显示的,就是一种数据,那么一般叫做BarData之类的,根据具体业务起不同的名字,总之不会叫Dto,就好像你不会给一个类取名为BarObject一样。

Q3:第1点、第2点是不是在dto包下建立input、output包更好?input放controller参数的类,output用于存放service返回值的类

A3:不建议这么分,一个controller可能会有多种业务方法,倾向于根据业务方法分包,会更清晰一点。

Q4:controller和service之间传递的参数一般是不是直接传DTO对象,然后在service中在构造entity去调用mapper方法?

A4:service方法一般来说不应该接收Dto参数,因为Dto是比较随意的,而且会和Http请求联系在一起,如果前端代码变了,那么Service也很容易跟着变,这样不好。

我建议是Controller将Dto转换成service需要的参数类型,然后去调用service,这样service代码就会稳定。

Q5:第4点,如果类对象成员比较多,势必service方法充斥着很多set方法,如何解决呢?

A5:你可以使用Dozer,或者Orika Mapper之类的工具,将Dto的属性copy到entity上,它们的原理是通过反射,将两个类里的同名属性做copy。

Q6:DTO的validation是在controller里面做,还是在service里面做呢?

A6:你可以借用Spring MVC提供的validation功能做一些简单的校验,比如@NotNull,@NotEmpty之类的。

但是如果你的这个FooSaveCmd有一些业务逻辑校验,比如不允许注册同名账号,那么这个校验得在service里做。

咋感觉是为了规范而规范,公司有公司的习惯,自己有自己的习惯,能解决问题,维护方便才是重点,一般都是实践中找出最好的方式,或者看他人源码。所以你这个不好回答,或者没啥意义!
1.如果是维护他人的代码,尽量按照之前 coder 编码的风格
2.如果没有公司的约束,自己搭建的结构,个人觉得其实都不重要,至少保证结构清晰,至于以后会遇到什么问题,再具体分析,具体修改
楼下提到的阿里的Java规范,你可以看看


我的一些看法
1.controller里面的Method如果参数比较多,会用一个类对象去接收,一般是放在dto包下,并且类名命名为FooDTO吗?
:数据传输对象:xxxDTO,xxx 为业务领域相关的名称

2.返回给前端的对象,如果要求不高,并且单表直接Select出来,可以直接返回Entity或者2.List<Entity>。但是,如果是多张表join出来的结果,是不是需要定义一个类,比如命名为BarDTO,这个BarDTO通过MyBatis的ResultMap生成,并且经过mapper -> service -> controller -> ajax?
:联表查询出来的数据,DO 设计的时候,我是会考虑的,当然你也可以用 DTO,但是你要知道 DTO 如果设计的过多,分的太细,也是不好维护的

3.第1点、第2点是不是在dto包下建立input、output包更好?input放controller参数的类,output用于存放service返回值的类
4.controller和service之间传递的参数一般是不是直接传DTO对象,然后在service中在构造entity去调用mapper方法?
:还是那个问题,DTO 这个东西如果分的太多,太细,代码维护和可读性会有问题,关于页面展示的可以用 VO;其实传递普通的基本的数据类型也是可以的呀,listUser(Interger groudId),getUser(String userid),这个结构不是也很清晰吗,listUser(xxDTO xx),getUser(xxDTO xx)

5.第4点,如果类对象成员比较多,势必service方法充斥着很多set方法,如何解决呢?
:充斥着很多set方法,我觉得ok呀,你可以封装成一个方法,这本身就是属于业务的一部分

6.DTO的validation是在controller里面做,还是在service里面做呢?
:具体还是看业务逻辑吧!

建议查看下阿里的JAVA开发规范,里面对dto、vo、po层的命名进行了规范,可能每个公司的规范都不一样,但至少养成自己的命名风格。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题