背景
自从接触springboot以来,约定优于配置的概念就一直被不断的提及,如何理解约定优于配置也是面试中被问得比较多的问题之一。之前一直模模糊糊的知道大概意思,但是 就是说不清楚,最近静下心来总结一下自己 对约定优于配置的理解,也算是对自己的知识体系的加深和巩固。
为什么靠右走
先说个大家都能理解的例子,比如说,刚开始人们在马路上走的时候,都是各走各的,杂乱无章,反正没人管,然后呢,某个或者说某些人,感觉这样不安全,也不方便,于是为了自己的安全考虑,每次刻意从马路的右边走,这样其实可以避开来往的大部分人,方便自己也方便他人。后来,越来越多的人,感觉这样的确不错,都跟着从右边走,到最后,靠右走,成了大家默认的习惯,或者用约定来描述更合适。
这样,对于约定应该有了个大概的认识吧。
配置文件的问题
比如,我开发一个项目,我是不是的规划自己的项目文档结构,哪里放代码,哪里放资源,编译的class文件放哪,用什么工具打包,打包的文件放哪里?
如果是web项目,那么,我是不是需要导入各种jar包,比如
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.3.12.RELEASE</version>
</dependency>
要在配置文件application-web.xml
中,配置
<!-- 1.开启注解扫描 -->
<context:component-scan base-package="com.*.web" />
<!-- 2.支持所有MVC注解 -->
<mvc:annotation-driven/>
<!-- 3.配置默认的url处理器 -->
<mvc:default-servlet-handler/>
<!-- 4.配置视图解析器,重新定义一些配置 -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
</bean>
<!-- 5.配置文件上传解析器 -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding" value="UTF-8" />
<!-- 设置最大允许的大小(字节)。-1表示没有限制(默认) 1024*1024*5=5MB -->
<property name="maxUploadSize" value="5242880" />
<!--被允许的最大的内存的大小,Default is 10240 bytes -->
<property name="maxInMemorySize" value="40960" />
<!-- 一个类似懒加载的属性.可以定义该属性.让解析文件的时候再抛异常,然后Controller中定义异常处理的方法 -->
<property name="resolveLazily" value="true" />
</bean>
<!-- 6.配置jackson解析器 -->
<bean id="mappingJacksonHttpMessageConverter"
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
为了数据的一致性,需要配置事务:
<!-- ================= 事务配置开始 ===================== -->
<!-- 事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="marketDataSource"></property>
</bean>
<!-- 切入点 配置-->
<aop:config>
<aop:advisor pointcut="execution(* com.*.service.*.*.*(..))"
advice-ref="txAdvice"/>
</aop:config>
<!-- 事物(通知)属性 -->
<tx:advice id="txAdvice">
<tx:attributes>
<!-- SUPPORTS:方法在某个事务范围内被调用,则方法成为该事务的一部分
在事务范围外被调用,则方法在没有事务的环境下执行 -->
<tx:method name="get*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="list*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="query*" read-only="true" propagation="SUPPORTS"/>
<tx:method name="find*" read-only="true" propagation="SUPPORTS"/>
<!-- REQUIRED:业务方法需要在一个事务中运行。如果方法运行时,
已经处在一个事务中,那么加入到该事务,否则为自己创建一个新的事务 -->
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<!-- ================= 事务配置结束 ==================== -->
这样的繁琐的配置,是不是很烦?如果不小心配置错了,排查问题,还得非你不少功夫
springboot的优势
这不,带着良心的Spingboot来了,springboot项目,约定如下:
src.main.java // 代码文件夹
src.main.resources // 资源文件夹
src.test.java // 测试代码
src.test.resources // 测试资源
target // 编译后的class文件和 jar文件
哦,是web项目啊,我这有个spring-boot-starter-web
,自动配置spring
和springmvc
,还内置了tomcat
,,不用配置上面那么些烦琐的配置,试试,很方便的。
需要处理事务啊,可以使用 Transactional
,你可以很方便,多维度的控制自己事务,比如
@Transactional(rollbackFor=Exception.class)
//可以配置在Action Service,可以配置在类上,也可以配置在方法级别
还需要MQ支持啊,我还有个spring-boot-starter-rabbitmq
,也不需要你多配置其他东西,默认的配置足够满足你的要求。
当然了,springboot提供的都是 默认配置,你可以根据自己项目需要,自己修改 ,比如我不想用内置tomcat,那么你可以改用jetty
,netty
也都是可以的,
这样看来,使用springboot
很方便快捷,这就是约定优于配置的魅力
到现在,对于约定优于配置的理解,是不是很有感觉了呢
小结
其实,从某种程度上说,约定其实也是一种配置,只不过是私有配置,如果不做修改,那就是约定配置。就好比,我制定了一个游戏规则,我自己玩的不亦乐乎,大家一起玩的话,只要你能接收我的游戏规则,那就一起玩,没问题,如果不能接受,那么就提建议或者自己去玩咯
当然,如果这个私有规则,大家都能接受,就会成为一种规范,就好比最开始的那个靠右走的例子,现在靠右行驶就写到交通法规里面了