转Java
开发不久,请教各位:
项目概况
项目基于
SSM
框架,分层结构为controller
->service(interface & implementation)
->mapper
,因为项目比较简单,基本就是贫血模型,model
放在entity
包下,跟数据库表一一对应。
现在我请教的问题如下:
controller
里面的Method如果参数比较多,会用一个类对象去接收,一般是放在dto
包下,并且类名命名为FooDTO
吗?返回给前端的对象,如果要求不高,并且单表直接Select出来,可以直接返回
Entity
或者List<Entity>
。但是,如果是多张表join
出来的结果,是不是需要定义一个类,比如命名为BarDTO
,这个BarDTO
通过MyBatis
的ResultMap
生成,并且经过mapper -> service -> controller -> ajax
?第1点、第2点是不是在
dto
包下建立input
、output
包更好?input
放controller
参数的类,output
用于存放service
返回值的类controller
和service
之间传递的参数一般是不是直接传DTO
对象,然后在service
中在构造entity
去调用mapper
方法?第4点,如果类对象成员比较多,势必
service
方法充斥着很多set
方法,如何解决呢?DTO
的validation
是在controller
里面做,还是在service
里面做呢?
感谢各位不吝赐教!
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里做。