在将SpringMVC项目转移到Springboot上的过程当中,主要作了如下的事情java
本篇文章除了介绍作了些什么和怎么作以外,会多不少多余的废话,关于对原理的一些探讨,知其然也要知其因此然。web
在传统的Spring项目中,多个profile的配置方式首先是在pom.xml文件中写入多个profile,再经过启动项目前先执行一个maven文件来预加载选定的profile环境。加载完以后,执行项目的时候,会根据已加载的Environment,来决定去将哪一个.properties文件load到全局变量中。spring
而在Springboot中对多个profile的管理就很是简单了。sql
能够在jar包用命令行运行时选择profile数据库
java -jar example.jar --spring.profiles.active=test
复制代码
或者在application.properties这个全局配置中配置spring-mvc
在application.properties中添加spring.profiles.active=test
复制代码
以上两种方法都可启动“test"这个profile,前者在执行上的优先级要高于后者。tomcat
(顺便一提,在Springboot里面,这两种方式本质上都是用“外部化配置”的方式,来对Environment进行编辑和替换)bash
另外,每一个独立的profiles的配置方式为以"application-xxx.properties"格式,针对每一个不一样环境,例如:session
当咱们须要测试是否正常载入了profile的时候,能够在对应的.properties文件中写入mvc
server.port=9080
复制代码
在启动的时候就能够看到,是否已经启动了这个端口。
在这里能够顺便提一下Springboot加载配置文件的顺序
- home目录下的devtools全局设置属性( ~/.spring-boot-devtools.properties ,若是devtools激活)。
- 测试用例上的@TestPropertySource注解。
- 测试用例上的@SpringBootTest#properties注解。
- 命令行参数
- 来自 SPRING_APPLICATION_JSON 的属性(环境变量或系统属性中内嵌的内联JSON)。
- ServletConfig 初始化参数。
- ServletContext 初始化参数。
- 来自于 java:comp/env 的JNDI属性。
- Java系统属性(System.getProperties())。
- 操做系统环境变量。
- RandomValuePropertySource,只包含 random.* 中的属性。
- 没有打进jar包的Profile-specific应用属性( application-{profile}.properties 和YAML变量)。
- 打进jar包中的Profile-specific应用属性( application-{profile}.properties 和YAML变量)。
- 没有打进jar包的应用配置( application.properties 和YAML变量)。
- 打进jar包中的应用配置( application.properties 和YAML变量)。
- @Configuration 类上的 @PropertySource 注解。
- 默认属性(使用 SpringApplication.setDefaultProperties 指定)。
在上一面一小节写了针对不一样环境的properties配置,这里会写关于若是将这些属性写入到全局变量中,方便后面其余地方直接调用。
/**
* 全局变量
*/
public class Global {
public static String examplePath;
@Value("${example_path}")
public void setExamplePath(String example) {
Global.examplePath = examplePath;
}
}
复制代码
经过这样子,咱们便将.properties文件中的
example_path=http://localhost:9090
复制代码
这个属性读到了全局变量中。
在传统的Spring项目中,用Mybatis链接数据库
这一切都是在xml配置文件中配置的,比较繁琐。在Springboot中会尽可能去避免这样子的xml配置。
Mybatis如今已经为Springboot提供了支持,咱们只须要添加MyBatis-Spring-Boot-Starter这个依赖,它就会为咱们去作好如下的事情:
因此,在Springboot的Mybatis配置中,咱们须要去作如下几件事情:
spring.datasource.url=jdbc:oracle:thin:@//localhost:1234/example
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.maxActive=10
spring.datasource.maxIdle=5
spring.datasource.maxWait=-1
复制代码
经过这种方式,咱们便在Spring上下文中注册了datasource这个bean。
/**
* Created by WuTaoyu on 2017/12/7.
*/
@Configuration
@EnableTransactionManagement
@MapperScan("com.example.db.dao")
public class MybatisConfig {
@Autowired
private DataSource dataSource;
@Bean(name = "sqlSessionFactory")
public SqlSessionFactory sqlSessionFactoryBean() {
SqlSessionFactoryBean sqlsession = new SqlSessionFactoryBean();
sqlsession.setDataSource(dataSource);
try {
//添加XML目录
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlsession.setMapperLocations(resolver.getResources("classpath:mapping/*.xml"));
return sqlsession.getObject();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Bean
public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
@Bean
public PlatformTransactionManager annotationDrivenTransactionManager() {
return new DataSourceTransactionManager(dataSource);
}
@Bean(name = "exampleSequence")
public OracleSequenceMaxValueIncrementer exampleSequenceBean(){
OracleSequenceMaxValueIncrementer exampleSequence = new OracleSequenceMaxValueIncrementer();
exampleSequence.setIncrementerName("EXAMPLE_SEQ");
exampleSequence.setDataSource(dataSource);
return exampleSequence;
}
}
复制代码
@MapperScan是扫描这个包下面的mapper。
另外这里mapper.xml的位置,是在resource文件夹下面建了一个mapping文件夹,放在下面。
这里的做用跟XML比较相似,是将传统的xml表达方式用.java文件来描述出来,本质上仍是将datasource一步步注入。
因为示例用的是oracle数据库,因此最后一个exampleSequence是示范如何添加序列。
例如:
@Mapper
public interface UserMapper {
...
}
复制代码
Logback支持用properties的方式外部化配置,可是对于比较细的配置来讲,仍是要沿用xml配置。
为了让xml文件从.properties文件读取一些路径之类可能须要常常修改的静态配置,须要在logback-spring.xml中配置
<property resource="application.properties" />
<property name="log.root.level" value="${log.root.level}" />
<property name="log.path" value="${log.path}" />
<property name="log.moduleName" value="${log.module}" />
复制代码
这样子就能够将application.properties文件中的
log.path=/home/logs/example
log.root.level=INFO
log.module=example
复制代码
读入到logback-spring.xml中,而后再去调用。
WebConfig的主要做用是替代web.xml和spring-mvc.xml进行一些基础配置。
传统的Spring项目都有配置一个web.xml文件,这个文件的做用是:当咱们把war包放入应用容器(例如tomcat)中运行时,容器会根据web.xml去加载filter(过滤器)、servlet、error-page、welcome-file-list、listener(监听器)、context-param(上下文参数)、resource-ref(资源配置)等配置。
包括ContextLoaderListener这个监听器,就是在这里加载进去,用于在启动容器的时候,自动装配ApplicationContext的配置信息。
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
复制代码
这个ApplicationContext是Spring IOC的核心(继承自BeanFactory),全部单例的Bean会在这个时候就被实例化。
以及,SpringMVC中很重要的一个DispatcherServlet也是在这里加载进去,并制定根据哪一个xml文件来配置DispatcherServlet。
<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<!--<async-supported>true</async-supported>-->
</servlet>
复制代码
spring-mvc.xml是SpringMVC的配置文件,在这里能够配置咱们引入的、须要定制化的bean,例如ViewResolver、multipartResolver、HTTP消息转换器、自定义的拦截器等等。
以上都与Springboot无关,主要是为了知其然也知其因此然,若是不感兴趣的能够不看。
再讲回Springboot的配置。Springboot有一个说法叫“约定优于配置”,就是尽可能用约定的方式,而不是特意去针对性地配置(须要特殊配置的时候再去配置)。
引入spring-boot-starter-web这个“开箱即用”的依赖以后,spring-boot-starter-web下包含了一个spring-boot-autoconfigure。
有了这个依赖以后,就可使用@EnableAutoCongiguration注解。这个注解就会根据引入的依赖来猜想你须要的Spring配置并帮你配置好。由于已经引入了spring-boot-starter-web的话,这个注解就会将web相关的配置配置好。
另外,@SpringBootApplication这个注解中已经包含了@EnableAutoCongiguration注解。因此只要在启动类ExampleServerApplication上注解@SpringBootApplication就能够自动把web配置给配置好了。
固然,咱们可能还有一些特殊的配置,这时候就能够建立一个WebConfig去定制
/**
* Created by WuTaoyu on 2017/12/8.
*/
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(marshallingHttpMessageConverter());
}
public MarshallingHttpMessageConverter marshallingHttpMessageConverter(){
MarshallingHttpMessageConverter marshallingHttpMessageConverter = new MarshallingHttpMessageConverter();
List<MediaType> mediaTypes = new ArrayList<MediaType>();
mediaTypes.add(MediaType.TEXT_XML);
mediaTypes.add(MediaType.APPLICATION_XML);
XStreamMarshaller xStreamMarshaller=new XStreamMarshaller();
marshallingHttpMessageConverter.setSupportedMediaTypes(mediaTypes);
marshallingHttpMessageConverter.setMarshaller(xStreamMarshaller);
marshallingHttpMessageConverter.setUnmarshaller(xStreamMarshaller);
return marshallingHttpMessageConverter;
}
//配置文件上传
@Bean(name = {"multipartResolver"})
public MultipartResolver multipartResolver(){
CommonsMultipartResolver commonsMultipartResolver=new CommonsMultipartResolver();
commonsMultipartResolver.setDefaultEncoding("utf-8");
commonsMultipartResolver.setMaxUploadSize(10485760000L);
commonsMultipartResolver.setMaxInMemorySize(40960);
return commonsMultipartResolver;
}
//异常处理
@Bean
public ExceptionHandler exceptionResolver(){
ExceptionHandler exceptionHandler = new ExceptionHandler();
return exceptionHandler;
}
//拦截器
@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(new LogInterceptor()).addPathPatterns("/**");
super.addInterceptors(registry);
}
}
复制代码
我写的这个示例文件里面作了几件事情:
这个算是一个题外话,但也是我实际遇到的问题之一。
在实际运行的Springboot项目的时候,我发现了一些在传统Spring项目中没有报错的问题,就是多余的bean注入。
在传统Spring项目中,这是没有报错的,可是在Springboot项目中就报错了。我猜想是由于要注入bean的类方法名取的比较精简的时候,与Springboot自己自动配置的一些bean重复了,就会报错。
因此,把有些不须要注入的bean去掉吧。