本文的目的是简单介绍Spring Boot的一些入门配置的Quick Start,帮助快速上手;
不涉及Spring Boot的概念的介绍讲解,如需了解请参考Spring Boot 官方文档;
有关Spring Boot的优缺点和适用场景的文章已经很多,还请自行Baidu/Google;
-
开始
Spring Boot采用约定优于配置的方式,相比原来Spring框架,配置有了大幅的简化,不仅配置文件写起来简单多了,而且pom.xml的依赖配置也进行了优化,具体请参考Spring Boot Starter
org.springframework.boot
spring-boot-starter-parent
2.0.0.BUILD-SNAPSHOT
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-maven-plugin
只需要这样几行简单的配置,就能写基于Spring MVC的Hello World了
@RestController
class HelloWorld {
@RequestMapping("/")
String home() {
return "Hello World!";
}
}
然后写个入口
@SpringBootApplication
@EnableAutoConfiguration
public class Application {
private static final Logger logger = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
启动main方法,运行、调试都很简单
-
加上日志
开始一个项目的时候,日志是比不可少的,先把日志加上,避免了System.out.println的泛滥。
Spring Boot的默认配置文件是 application.properties
, 不使用默认配置的选项全都在这里定义
Spring Boot 默认使用logback,无需任何配置就可以使用了,并提供了
logging.config= # Location of the logging configuration file. For instance
classpath:logback.xml
for Logback
logging.exception-conversion-word=%wEx # Conversion word used when logging
exceptions.logging.file= # Log file name. For instancemyapp.log
logging.level.*= # Log levels severity mapping. For instancelogging.level.org.springframework=DEBUG
logging.path= # Location of the log file. For instance/var/log
logging.pattern.console= # Appender pattern for output to the console. Only supported with the default logback setup.logging.pattern.file= # Appender pattern for output to the file. Only supported with the default logback
setup.logging.pattern.level= # Appender pattern for log level (default %5p). Only supported with the default logback
setup.logging.register-shutdown-hook=false # Register a shutdown hook for the logging system when it is initialized.
如果有更具体配置,如async appender,remote appender等还需使用原有的XML配置文件,如果使用默认配置文件名logback-spring.xml
,则可以直接生效,无需添加一行配置
如果想使用log4j2或其他的请参考howto logging
-
写个测试
注:standalone的Spring Boot程序只允许在jar中存在一个main方法
所以原来习惯写个main方法来测试代码的同学,是时候了解怎样写测试了,请移步到Junit深造
首先,添加依赖
org.springframework.boot
spring-boot-starter-test
test
测试的starter已经包含了测试工具:Junit
Hamcrest
Mockito
等,可以直接上手写case了
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureTestDatabase
public class UserVehicleControllerApplicationTests {
@Autowired
private MockMvc mvc;
@Autowired
private ApplicationContext applicationContext;
@MockBean
private UserVehicleService userVehicleService;
@Test
public void getVehicleWhenRequestingTextShouldReturnMakeAndModel() throws Exception {
given(this.userVehicleService.getVehicleDetails("sboot")).willReturn(new
VehicleDetails("Honda", "Civic"));
this.mvc.perform(get("/sboot/vehicle").accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk()).andExpect(content().string("Honda Civic"));
}
@Test
public void welcomeCommandLineRunnerShouldBeAvailable() throws Exception {
assertThat(this.applicationContext.getBean(WelcomeCommandLineRunner.class).isNotNull();
}
}
测试例子请看 spring-boot-sample-test
-
数据库连接池
数据库连接池也是大多数项目的标配,在Spring Boot中引入也十分简单
以mysql为例,pom中添加依赖:
mysql
mysql-connector-java
5.1.26
com.zaxxer
HikariCP
2.4.7
compile
请使用tomcat 和 C3p0 连接池的同学移驾 HikariCP 补课
application.properties
中添加:
datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8
datasource.username=user
datasource.password=password
spring.datasource.url=${datasource.url}
spring.datasource.username=${datasource.username}
spring.datasource.password=${datasource.password}
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.max-lifetime=30000
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.data-source-properties.prepStmtCacheSize=250
spring.datasource.hikari.data-source-properties.prepStmtCacheSqlLimit=2048
spring.datasource.hikari.data-source-properties.cachePrepStmts=true
spring.datasource.hikari.data-source-properties.useServerPrepStmts=true
这样Spring Boot会自动识别这些配置并加载jdbcTemplate和dataSource的bean
-
Mybatis
Hibernate,JPA,JOOQ的同学请参考 [Working With Database](29. Working with SQL databases)
Mybatis 开发了自己的starter依赖
org.mybatis.spring.boot
mybatis-spring-boot-starter
1.1.1
然后就可以像往常一样编写Dao了
@Mapper
public interface DemoDao {
@Select("select * from test")
public List get();
@Insert("insert into test (name,age) values (#{name},#{age})")
void insert(@Param("name") String name, @Param("age") String age);
}
当然如果遇到要写一些复杂的SQL或者需要include SQL的话,使用xml文件来写SQL会更方便,只需给定xml文件的未知即可 mybatis-mapper-locations=classpath*:**/mapper/*
详细Mybatis的请参考 mybatis-spring-boot-autoconfigure
-
数据库管理 Flyway
Flyway的具体使用方法请移步官网参考
添加pom依赖
org.flywaydb
flyway-core
配置中加入:
flyway.enabled=true
flyway.schemas=test
脚本默认位置:classpath:db\migration
搞定,程序启动自动执行数据库脚本
-
Redis
废话不说了
pom
org.springframework.boot
spring-boot-starter-data-redis
properties
spring.redis.database=0
spring.redis.host=127.0.0.1
spring.redis.password=
spring.redis.pool.max-active=-1
spring.redis.pool.max-idle=100
spring.redis.port=6379
spring.redis.timeout=0
code
@AutowiredRedisTemplate redisTemplate;
-
异常处理之ExceptionHandler
当Controller抛出异常后需要进行处理,以返回友好信息给clients
@ControllerAdvice(basePackageClasses = CoreApplication.class)
public class DemoControllerAdvice {
@ExceptionHandler(DemoException.class)
@ResponseBody
ResponseEntity> handleControllerException(HttpServletRequest request, Throwable ex) {
HttpStatus status = getStatus(request);
return new ResponseEntity(new DemoError(status.value(), ex.getMessage()), status);
}
@ExceptionHandler(Exception.class)
@ResponseBody
ResponseEntity> handleException(HttpServletRequest request, Throwable ex) {
HttpStatus status = getStatus(request);
return new ResponseEntity(new DemoError(status.value(), ex.getMessage()), status);
}
private HttpStatus getStatus(HttpServletRequest request) {
Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR;
}
return HttpStatus.valueOf(statusCode);
}
}
-
异常处理之ErrorController
容器处理失败的请求会自动转到 /error
来处理,实现ErrorController接口来自定义该异常的处理机制
@RestController
public class DemoErrorController implements ErrorController {
@Autowired
ErrorAttributes errorAttributes;
@RequestMapping(value = "/error")
public ResponseEntity
-
自定义拦截器
与Spring MVC一样,定义一个拦截器
public class DemoInterceptor implements HandlerInterceptor {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.info("pre handle");
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
logger.info("post handle");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response,Object handler, Exception ex) throws Exception {
logger.info("after completion");
}
}
然后在WebMvcConfigurerAdapter
的子类中把定义好的拦截器添加到容其中
@Configuration
public class DemoConfiguration extends WebMvcConfigurerAdapter {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new DemoInterceptor()).addPathPatterns("/**");
}
}
其他的与Spring MVC一样
-
多环境处理
开发过程中,总会遇到本机环境、CI环境,测试环境、UAT环境、生产环境等等不同环境间的切换,往往因为环境的不同需要写不同的配置文件,又要有不同的脚本去替换这些配置文件,然后又要有一套版本管理系统把配置文件、脚本管理起来。
在Spring Boot中,这些问题统统可以自动处理。我们可以通过定义一个启动参数来指定当前启动的环境是那个,那么该环境的配置文件就会被加载执行。
启动参数:java -jar -Dspring.profiles.active=production app.jar
Spring Boot 首先会加载默认的配置文件application.properties
,然后会根据指定的参数加载特定环境的配置文件application-*.properties
,例如:application-production.properties
而我们要做的只是将配置文件放到指定的config路径下即可。
-
定时器
增加定时器也很容易,使用@EnableScheduling
注解
@Configuration
@EnableScheduling
public class DemoJob {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
@Scheduled(cron="${Demo.Cron.Expression}")
public void fire() {
logger.info("scheduler fired");
}
}
定义Cron Expression
Demo.Cron.Expression=0 0/1 * * * ?
如果需要在不同的环境有不同的执行策略,可以通过在不同环境的配置文件中定义不同Expression来做
如果只需要在某些环境中执行,还可以指定bean的加载环境:
@EnableScheduling
@Profile({ "UAT", "Production" })
public class DemoJob{...}
这样,只有在指定了环境是UAT或Production时,Spring Boot才会初始化这个bean
-
加个开机提示
在配置文件中加入
# BANNER banner.charset=UTF-8 banner.location=classpath:banner.txt
-
Spring Boot Actuator
Spring Boot提供了一些监控管理应用程序的功能,例如JVM运行时资源监控、应用负载等
请自行查阅文档吧。
注:这些监控管理功能一定要配合Security使用,要有权限控制,建议生产环境时将这些权限控制在本机或内网。
-
最后
到这里,一个简单的Spring Boot Web 应用应该可以顺利跑起来了,请在使用前认真阅读官方文档。
-
Demo 下载
整理好会提供。