spring+spring mvc+spring data+MongoDB的一些编写规范
莫名奇妙的最近接触了很多这个框架写的代码。
这个框架写的代码,只要逻辑不规范就基本上很难看的懂。特别是关于数据库操作的那些方面。真的是痛苦到极点。
根据我最近的一些痛苦经历,在这里做一些思考,与总结
关于包的一些规范
妈的老子遇到一些神经病,把service层每一个类都单独建了一个包,每一个打开阅读是哪个酸爽,无法用言语来形容。基本上包应该util(工具包),controller(控制器包),dao(数据库访问接口包) daoImpl(数据库访问接口实现包),service(业务逻辑包),serviceImpl(业务逻辑层实现包),其他的有特殊功能的再单独建包
controller层的一些规范
mvc中关于c这一层基本上没有多大的问题,都是按部就班的来写就是了。
但是关于控制器上的路径,应该将不变的路径用静态变量的形式写在一个类里,然后在写在控制器上面,后面再加上本控制器特有的路径
@RequestMapping(AppConfig.API+"/test")
当然每个方法上面的额注释肯定是少不了的,再忙也要写注释
model层的一些思考
这次改代码最不好的经历就在这一层,哎,有关抱怨我估计都可以写一篇一千字的文章。我相信别人看我的代码只会抱怨更多,不会更少。
首先就是关于这个包的问题,怎么可能每一个类都建一个包呢?肯定是一类的代码才能建立一个包,哎
关于bean的一些规划
java web中的bean一般分为数据库的bean,非数据库的bean。
数据bean,设计一个顶层的抽象的class,然后里面有一些通用的属性,通用的属性一般要包括,objectId createtime,lastmodifyDate,时间的类型一般都是datatime,当然这些属性的类型不能是private只能是protected,数据库bean中的每一个注解上的@Document()我建议是放在一个类中,用静态常量的形式保存起来
再是根据数据库中的每个表设计各自的bean,这里的bean中的属性也建议设置成protected。
再就是用于承担数据的bean,这些bean用于组成返回数据,或者是
承接数据库查询返回的数据(有的时候做多表查询的时候,这肯定是关系型数据库中的东西),这里的bean拓展与数据库bean,然后这里的bean可以有private属性
关于数据库操作方法(dao)的一些设计
首先做一个统一的功能接口,这个功能接口最好是带泛型的,将一些公用的功能放置到这里例如 根据主键查询,插入数据等等吧
然后设计一个抽象的实现类(也可以设计成带泛型的),将基本的方法实现。
最后再由各个具体操作类来继承这个抽象的实现类
关于全局异常处理的思考
@ControllerAdvice
public class CustomRestExceptionHandler extends ResponseEntityExceptionHandler
全局异常处理固然是好的,但是在公司原来的代码中,将他们处理封装成返回信息就不后台打印出异常信息,导致这边有异常后,根本不知道是哪里的异常。
我建议就是,做全局异常处理时,应该讲这些信息,在控制台众打印出来,再处理之后将封装后的信息返回给前端
关于mysql时的一些bean的设计我感觉也能参照这里bean的设计方式
说这么多最重要的就是写注释,一定要写注释,写的越详细越好
项目中常用的注解
打算把这些项目用的注解都备注一下
@Aspect
注解的方式配置aop,spring 默认是不开启注解方式配置的需要在配置xml中添加
<aop:aspectj-autoproxy/>
@Pointcut(“execution(*)”)
用于设置面向切面的那个切面是什么
@After(“execution()) / @After()
标识在什么方法后面执行,这里也可像上面那样直接在execution中写方法,也可以在里面写@pointcut标识的本类的方法
@Before()
前置通知 和上面的用法相同
@Around()
环绕通知 ,用法同上
@ResponseBody
返回的数据将放在response body中
@controller
标识这是一个 控制器,同时也标识这是一个spring bean
@RestController
上面两个注解相加 就是这个注解
@Autowired @Resource
都是将值装配到指定的句柄上,前面那个是spring的注解,后面的是java ee的注解,却别肯定是有的。
@Qualifier
当 @Autowired注入时,项目中有相同的类名的时候,用来却别加载哪一个,使用@Resource 可以指定name
@RequestBody
注解用于将Controller的方法参数,根据HTTP Request Header的content-Type的内容,通过适当的HttpMessageConverter转换为JAVA类,当
POST或者PUT的数据是JSON格式或者XML格式,而不是普通的键值对形式.
而且和@RequestParam不能共用,用了这个注解,所有的上传参数都用该封装到上传的json\xml数据中
@Valid
验证注释
@NotBlank(message=”“)
用于返回值是String 返回的值不能是空并且长度不能是0,message发生错误时返回的消息
@Size(min= max= message=)
标识返回数据长度的范围
@XmlRootElement(name=)
用于标识 返回xml时这个类对应xml中的父节点
@XmlElement
标识 返回xml中的子节点
@PathVariable
可以将url上的值映射到参数上
@RequestMapping(value = "/{test}/")
public BuildingVo list(@PathVariable String test){}
这里可以将请求url中的test的值对应到参数test上
@Id
spring data的注解,用于标识这个属性对应数据库中的id
@Filed
spring data注解 用于标识这是数据库中的一个属性
@createDate
spring data的注解 当数据被insert到数据库的时候,将设置这个值。
@LastModifiedDate
标识最后一次修改的时间,和上面相同
@JsonSerialize(using = CustomDateTimeSerializer.class)
注解作用于getter上,将序列化成json时按照后面using的方法编程和想要的格式,下面是一个序列化时间的类
public class CustomDateTimeSerializer extends JsonSerializer<DateTime> {
private DateTimeFormatter formatter =
DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
@Override
public void serialize(DateTime dateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
jsonGenerator.writeString(formatter.print(dateTime));
}
}
@JsonInclude(JsonInclude.Include.NON_EMPTY)
序列化成json时,如果是空的话就不要序列化
@Document(collection = “firewaterSup”)
对应的mongodb 的collection的name,作用于类上