Part IV. Spring Boot Features(Spring Boot 的特性)SpringApplication
通常放在了main函数中,作为spring-boot的启动类
public static void main(String[] args) {
SpringApplication.run(MySpringConfiguration.class, args);
}
1. Customizing the Banner(自定义Banner)
Banner将会在系统启动的时候打印出来,4中方式设置
在classpath中添加一个文件banner.txt
通过参数banner.location来设置文件的位置,设置文件的编码banner.charset(默认使用UTF-8)
在classpath中添加一个文件banner.gif, banner.jpg or banner.png
通过参数banner.image.location来设置图片文件的位置
在banner.txt文件中可以设置下面的参数:
${application.version}
${application.formatted-version}
${spring-boot.version}
${spring-boot.formatted-version}
${application.title}
通过程序来设置banner
实现这个接口中org.springframework.boot.Banner 的printBanner()方法,在通过SpringApplication.setBanner(…)
来设置自己实现的Banner
也可以使用spring.main.banner-mode来设置是否启用或者关闭打印banner功能,可选参数log,off
2. Customizing SpringApplication
通常使用SpringApplication的静态方法运行,为了设置更多的参数,可以直接new一个SpringApplication
public static void main(String[] args) {
SpringApplication app = new SpringApplication(MySpringConfiguration.class);
app.setBannerMode(Banner.Mode.OFF);
app.run(args);
}
虽然可以通过编程的方式来实现配置参数,但是官方建议使用application.properites来配置。更多配置参数参考SpringApplication Javadoc
3. Application events and listeners
顺序如下: ApplicationStartedEvent,ApplicationEnvironmentPreparedEvent,ApplicationPreparedEvent,ApplicationReadyEvent,ApplicationFailedEvent
使用SpringApplication.addListeners(…)添加事件监听器
4. Accessing application arguments(访问application的参数)
可以依赖注入org.springframework.boot.ApplicationArguments,ApplicationArguments提供了访问application参数的方法;
也可以直接把需要的参数作为属性,使用@Value来访问
5. Using the ApplicationRunner or CommandLineRunner
如果想要在SpringApplication.run(...)执行完成前对参数做一些特殊处理,可以使用ApplicationRunner,CommandLineRunner这两个接口
@Component
public class MyBean implements CommandLineRunner {
public void run(String... args) {
// Do something...
}
}
6. Application exit
所有Spring管理的类在结束之前需要做一些事,可以使用DisposableBean接口或者@PreDestroy注解,
如果需要在Application容器结束后返回一些特殊的Code,可以实现org.springframework.boot.ExitCodeGenerator 接口
Externalized Configuration
1. Application property files
Spring-boot会从application.properties中寻找配置属性,application.properties可以放在如下位置:
放在当前项目根目录下
放在当前项目根目录下的/config中
放在classpath根目录下(推荐)
放在claasspath根目录下/config中
注意:目录最深的覆盖上层的熟悉
也可以通过spring.config.name,spring.config.location在命令行参数中指定参数文件的名字和加载位置
2. Profile-specific properties
通常我们需要对测试环境,开发环境,正式环境配置不同的参数,我们可以写多个配置文件,
格式 application-{profile}.properties,然后再applicatioin.properties中使用spring.profiles.active来指定使用哪一个或多个配置文件(多个文件使用逗号分隔),特定的配置文件中的属性将会覆盖application.propreties中的属性
也可以使用 @Profile("...") 来指定使用哪个文件
@Configuration
@Profile("production")
public class ProductionConfiguration {
// ...
}
在application.properties中的参数可以项目使用,比如:
app.name=MyApp app.description=${app.name} is a Spring Boot application 3. Type-safe Configuration Properties
使用@Value("${property}")来依赖注入属性有时候会很麻烦,尤其是多个属性需要注入。Spring-boot提供一种更加方便的方式@ConfigurationProperties。
首先建立一个类
@ConfigurationProperties(prefix="connection")
public class ConnectionProperties {
private String username;
private InetAddress remoteAddress;
// ... getters and setters
}
在@EnableConfigurationProperties中指定建立的配置类
@Configuration
@EnableConfigurationProperties(ConnectionProperties.class)
public class MyConfiguration {
}
在需要使用的类中使用@Autowired注入ConnectionProperties
另一种方式,可以不用使用EnableConfigurationProperties(ConnectionProperties.class), 直接在ConnectionProperties上添加@Component
4. Relaxed binding(简便的绑定方式)
@ConfigurationProperties(prefix="person")
public class OwnerProperties {
private String firstName;
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
}
5. @ConfigurationProperties Validation
Spring-boot 支持使用JSR-303的方式对@ConfigurationProperties的注解类的属性进行校验,并且使用@Valid 来触发校验
@Component
@ConfigurationProperties(prefix = "connection")
public class ConnectionProperties {
@NotEmpty
private String userName;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
@Valid
private ConnectionProperties connectionProperties;
@RequestMapping("/login")
String login() {
return "Login Successful!=" + connectionProperties.getUserName();
}
}
6. @ConfigurationProperties vs. @Value
Feature | @ConfigurationProperties | @Value |
---|---|---|
Relaxed binding | Yes | No |
Meta-data support | Yes | No |
evaluation | No | Yes |
7. Programmatically setting profiles(编程的方式来设置profiles)
你可以在application启动之前调用方法 SpringApplication.setAdditionalProfiles(…);你也可以通过使用ConfigurableEnvironment接口来实现
Logging(系统日志配置)
1. 使用不同颜色输出日志
spring.output.ansi.enabled 可选的参数 :
ALWAYS ,DETECT , NEVER 参考api supported value
2. 配置日志文件
logging.file 配置日志文件名称
logging.path 配置日志文件的路径
logging.file | logging.path | Example Description |
---|---|---|
(none) | (none) | 控制台输出 |
指定日志文件名 | (none) | my.log项目根目录下输出日志文件 |
(none) | 指定目录 | /var/log在指定目录下生成日志文件 |
当日志文件达到10m将会重新在新的文件中输出
3. 配置日志输出级别
logging.level.root=WARN
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR
4. 配置日志输出的格式
logging.pattern.console : 配置控制台输出格式
logging.pattern.file : 配置日志文件输出格式
Developing web applications(开发web应用)
Spring-boot对大部分应用提供了spring mvc 自动配置。自动配置了下面一些特性:
Inclusion of ContentNegotiatingViewResolver and BeanNameViewResolver beans.
Support for serving static resources, including support for WebJars (see below).
Automatic registration of Converter, GenericConverter, Formatter beans.
Support for HttpMessageConverters (see below).
Automatic registration of MessageCodesResolver (see below).
Static index.html support.
Custom Favicon support.
-
Automatic use of a ConfigurableWebBindingInitializer bean (see below).
如果你想要配置spring mvc 的一些拦截器, formatters, view controllers等等,你可以创建一个类继承于WebMvcConfigurerAdapter;例如:自己配置一个拦截器@Configuration
@ComponentScan(basePackages = "com.spring.boot.controller3")
public class WebConfigure extends WebMvcConfigurerAdapter {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor()).addPathPatterns("/user/**");
}
}
如果你想要自己实现RequestMappingHandlerMapping, RequestMappingHandlerAdapter,ExceptionHandlerExceptionResolver, 你可以自己实现WebMvcRegistrationsAdapter
1. HttpMessageConverters
Spring-boot已经包含了常用的HttpMessageConverter,比如自动转换对象为JSON或者XML;如果需要自己定义一些HttpMessageConverter,可以使用Spring-boot的HttpMessageConverters类:
@Configuration
public class MyConfiguration {
@Bean
public HttpMessageConverters customConverters() {
HttpMessageConverter> additional = ...
HttpMessageConverter> another = ...
return new HttpMessageConverters(additional, another);
}
}
2. Static Content(静态资源)
默认情况下Spring-boot使用的是Spring-mvc中的ResourceHttpRequestHandler来处理静态资源,默认静态资源的位置是在classpath目录下或者ServletContext根目录下的/static (or /public or /resources or/META-INF/resources);你也可以添加自己的处理方式,通过使用WebMvcConfigurerAdapter中的addResourceHandlers方法。
你也可以自己定义静态资源的位置,使用配置参数spring.resources.staticLocations
Spring-boot也支持静态资源缓存,使用版本号,参考spring-boot文档静态资源处理
3. ConfigurableWebBindingInitializer
默认Spring-boot使用的是WebBindingInitializer来初始化WebDataBinder,你可以创建自己的一个WebBindingInitializer,然后使用@Bean,那么Spring-boot将会使用自己定义的来配置Spring-mvc.参考ConfigurableWebBindingInitializer的实现。
5. Template engines
Spring-boot自动配置支持以下模板引擎:
FreeMarker
Groovy
Thymeleaf
Velocity (deprecated in 1.4)
Mustache
注意:JSP在Spring-boot中尽量避免使用,当使用内嵌的Servlet服务器的时候会有一些限制。参考文档
使用这些模板引擎,它们默认情况下都会在src/main/resources/templates目录下寻找模板。
6. Error Handling
我们可以通过使用@ControllerAdvice为一些特殊的Controller处理一些特殊的Exception
@ControllerAdvice(basePackageClasses = FooController.class)
public class FooControllerAdvice extends ResponseEntityExceptionHandler {
@ExceptionHandler(YourException.class)
@ResponseBody
ResponseEntity> handleControllerException(HttpServletRequest request, Throwable ex) {
HttpStatus status = getStatus(request);
return new ResponseEntity<>(new CustomErrorType(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);
}
}
7. Custom error pages
为了对不同的错误状态码显示不同不错误页面,我们可以在/error目录下面添加一个文件;这个文件可以是html,也可以是模板;文件的名称可以状态码,也可以是模板,比如:
src/
+- main/
+- java/
| +
更多复杂的映射,还可以使用ErrorViewResolver来实现:
public class MyErrorViewResolver implements ErrorViewResolver {
@Override
public ModelAndView resolveErrorView(HttpServletRequest request,
HttpStatus status, Map
// Use the request or status to optionally return a ModelAndView
return ...
}
}
我们也可以通过使用springmvc的特性来处理不同的异常,比如:@ExceptionHandler,@ControllerAdvice。其他没有被处理的异常都会被ErrorController拦截处理
8. CORS support(跨站点资源访问)
在Spring-mvc中已经支持跨站点资源访问,只需要在需要访问的类或方法上面添加注解@CrossOrigin,也可以配置全局的跨站点访问 参考文档。
Spring-boot配置全局的跨站点访问:
@Configuration
public class MyConfiguration {
@Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**");
}
};
}
}
l9. Embedded servlet container support(内嵌的servlet容器)
Spring-boot 已经内嵌了Tomcat,Jetty服务器,默认监听的端口是8080
9.1 Registering Servlets, Filters, and listeners
当使用Spring boot的嵌入式servlet容器时,可以通过Spring bean或扫描Servlet组件的方式注册Servlet、Filter和Servlet规范的所有监听器(例如HttpSessionListener)。
当urlMapping不是很复杂时,可以通过ServletRegistrationBean、FilterRegistrationBean 和ServletListenerRegistrat
@Configuration
@ComponentScan(basePackages = "com.spring.boot.controller3")
public class WebConfigure extends WebMvcConfigurerAdapter {
@Bean
public ServletRegistrationBean getLogServlet(LogServlet logServlet) {
return new ServletRegistrationBean(logServlet, "/logServlet");
}
}
@Component
public class LogServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.print("Log Servlet welcome!");
writer.close();
}
}
当使用@ServletComponentScan扫描Servlet组件时,Servlet、过滤器和监听器可以是通过@WebServlet、@WebFilter和@WebListener自动注册
@Configuration
@ServletComponentScan(basePackages = "com.spring.boot.component")
public class WebConfigure extends WebMvcConfigurerAdapter {
}
@WebServlet(urlPatterns = {"/logServlet2"})
public class LogServlet2 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doGet(req, resp);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.print("Log Servlet2 welcome!");
writer.close();
}
}
9.2 Servlet Context Initialization
对于这种内嵌的Servlet容器,在初始化的时候不会去执行javax.servlet.ServletContainerInitializer这个接口,而是执行spring的接口org.springframework.web.WebApplicationInitializer。如果你需要在spring-boot的应用中去处理初始化的工作,可以注册一个Spring Bean实现接口org.springframework.boot.context.embedded.ServletContextInitializer
@Component
public class AppServletContextInitializer implements ServletContextInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
System.out.println("============ AppServletContextInitializer ===============");
}
}
9.3 Customizing embedded servlet containers(配置嵌入的Servlet容器)
-
在applicat-ion.properties中配置参数
server.port : 配置监听的端口
server.address : 监听地址
server.session.timeout : session过期时间
server.session.persistence : 是否需要持久化session
server.session.store-dir : session存储位置
更多其他配置参考类 ServerProperties
-
通过编程的方式实现
import org.springframework.boot.context.embedded.*;
import org.springframework.stereotype.Component;
@Component
public class CustomizationBean implements EmbeddedServletContainerCustomizer {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.setPort(9000);
}
}
实现EmbeddedServletContainerCustomizer接口,编程配置参数
-
如果以上两种方式你觉得不灵活,你可以使用 TomcatEmbeddedServletContainerFactory,JettyEmbeddedServletContainerFactoryor UndertowEmbeddedServletContainerFactory
@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
factory.setPort(9000);
factory.setSessionTimeout(10, TimeUnit.MINUTES);
factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/notfound.html"));
return factory;
}
Working with SQL databases(使用SQL数据库)
1. 配置数据库连接池
1. Spring-boot能够自动配置数据库连接池DataSource,自动选择的规则:
2. 因为Tomcat的连接池效率和并发性都比较高,所以如果允许,都会选择使用
3. 否则,如果HikariCP允许,就会选择HikariCP
4. 如果Tomcat pooling datasource和HikariCP都不能使用,那么将会选择使用 DBCP
5. 最后,以上3中都不能使用,就会选择使用DBCP2
如果你使用了spring-boot-starter-jdbc, spring-boot-starter-data-jpa ,那么Spring-boot将会自动配置tomcat-jdbc
也可以通过使用spring.datasource.type来手动配置使用哪种,比如:配置阿里巴巴开源项目druid
更多的数据库参数配置,参考类DataSourceProperties
2. Using JdbcTemplate
Spring-boot会自动配置JdbcTemplate,可以直接使用@Autowire来注入使用
@Component
public class MyBean {
private final JdbcTemplate jdbcTemplate;
@Autowired
public MyBean(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
// ...
}
3. JPA and ‘Spring Data’
在Spring-boot应用中,可以使用spring-boot-starter-data-jpa作为一个开始,会包含一下依赖:
Hibernate — One of the most popular JPA implementations.
Spring Data JPA — Makes it easy to implement JPA-based repositories.
Spring ORMs — Core ORM support from the Spring Framework.
3.1 Entity Classes And Spring Data JPA Repositories
默认情况下,Spring-boot会扫描主要配置类(有注解@EnableAutoConfiguration or@SpringBootApplication)下面的所有包,任何被@Entity, @Embeddable or @MappedSuperclass注解的类都会作为实体;任何继承了Repository or CrudRepository的接口都会被作为 Repository,不需要任何@Component or Repository
如果你想要自定义寻找的Entity的存放位置,可以使用注解@EntityScan。
Caching 参考文档
Sending email
Spring框架提供了一个发送邮件的类JavaMailSender。
如果在容器中找不到一个存在的JavaMailSender,配置了参数spring.mail.host并且相关包存在(spring-boot-starter-mail导入相关包),那么就会自动创建一个JavaMailSender。
邮件配置参数都是以spring.mail开头,更多参数配置参考类: MailProperties
#发送邮件配置
spring.mail.host=smtp.sina.cn
[email protected]
spring.mail.password=asdewq
@RestController
@RequestMapping("/mail")
public class MailController {
@Autowired
private JavaMailSender mailSender;
@RequestMapping("/send")
public String sendMail() {
SimpleMailMessage mailMessage = new SimpleMailMessage();
mailMessage.setTo("[email protected]");
mailMessage.setFrom("[email protected]");
mailMessage.setSubject(" 测试简单文本邮件发送! ");
mailMessage.setText(" 测试我的简单邮件发送机制!! ");
mailSender.send(mailMessage);
return "send mail success...";
}
}
Spring Session 参考文档
Monitoring and management over JMX 参考文档