Spring Boot 学习(3)
文 by / 林本托
Tips
做一个终身学习的人。
Tips
代码路径:https://github.com/iqcz/Springbootdemo/tree/master/code01/ch3
Web 框架行为调整
在此章节中,主要包括如下内容:
- 配置路由匹配模式;
- 配置自定义静态路径映射;
- 通过EmbeddedServletContainerCustomizer调优Tomcat;
- 选择嵌入式servlet容器;
- 添加自定义连接。
一. 配置路由匹配模式
当我们构建Web应用程序时,并不总是使用一些默认的配置。 有时,我们要创建包含字符“.”的 RESTful 风格的 URL。“.”字符在Spring作为分隔符定义格式,例如path.xml中的点,或者我们可能不想识别路径尾部的斜杠,如/home/
等。 Spring为我们提供了对这些问题提供了一种轻松的实现。
在前面的第二节中,我们介绍了WebConfiguration
类,它继承了WebMvcConfigurerAdapter
类。 通过继承,可以重写面向过滤器,格式化,还有其他格式的方法。 同样,还可以重写配置路径匹配的方法。
假设ISBN格式允许使用点来将图书编号与修订版本分开,看起来像“[isbn-number].[revision]”的格式。
我们将配置我们的应用程序不使用“.*”的后缀模式匹配,并且在解析参数时不忽略点之后的值。 我们执行以下步骤:
首先,需要在WebConfiguration
类中,加入如下内容:
@Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseSuffixPatternMatch(false).
setUseTrailingSlashMatch(true);
}
同时,需要引入import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
类。
然后,执行./gradlew clean bootRun
命令。
在浏览器中,输入 http://localhost:8080/books/978-1-78528-415-1.1 , 然后会看到如下结果:
如果输入正确的 ISBN,会看到如下的结果:
我们来看看具体做了什么事情。 configurePathMatch(PathMatchConfigurer configurer)
方法有能力设置我们自己的行为,希望Spring如何将请求URL路径与控制器参数相匹配:
configurer.setUseSuffixPatternMatch(false)
方法表示不想使用“.*”后缀,不忽略最后一个点号后面的字符。这转换为Spring解析整个978-1-78528-415-1.1作为BookControlle
r的{isbn}参数。所以, “http://localhost:8080/books/978-1-78528-415-1.1” 和 http://localhost:8080/books/978-1-78528-415-1” 是两个不同的 URL。configurer.setUseTrailingSlashMatch(true)
方法表示我们想使用“/”在URL中作为匹配,即使 URL 中不存在“/”。 所以,“http://localhost:8080/books/978-1-78528-415-1” 和 “http://localhost:8080/books/978-1-78528-415-1/” 效果是一样的。
如果要进一步配置路径匹配的方式,可以提供自己的PathMatcher
和UrlPathHelper
实现,但这些在最极端和自定义的情况下都是必需的,一般情况下不推荐使用。
二. 配置自定义静态路径映射
在前面的内容中,我们讲解了如何调整请求的URL路径映射,并将其转换为控制器方法。 除此而外,还可以控制、Web应用程序处理静态文件,这些文件可能存在与文件系统中,或可部署的归档文件中。
假设我们想通过应用程序的 http://localhost:8080/internal/application.properties 的静态网址公开我们的内部application.properties 文件。 要开始执行此操作,请继续执行下面的步骤。
首先,在WebConfiguration
类中,重写addResourceHandlers
方法:
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/internal/**")
.addResourceLocations("classpath:/");
}
执行./gradlew clean bootRun
。服务启动以后,在浏览器中输入:http://localhost:8080/internal/application.properties,在我的环境里,系统是 macOS,浏览器是 Chrome,会下载application.properties文件,可能会根据每个人的操作系统和浏览器的不同,行为会不一样。
我们重写的addResourceHandlers(ResourceHandlerRegistry registry)
是WebMvcConfigurer
类的另一个配置方法,它能够为静态资源URL定义自定义映射,并将它们与文件系统或应用程序类路径上的资源进行连接。 在上面例子中,定义了一个通过“/ internal” URL可以访问的文件的映射,以便在我们的应用程序的“classpath:/”中查找。 (对于生产环境,可能不想将整个类路径暴露为静态资源)所以让我们来看看我们做了什么,如下所示:
registry.addResourceHandler("/internal/**")
方法,向ResourceHandlerRegistry
类添加一个资源处理程序来处理我们的静态资源,并返回ResourceHandlerRegistration
,这可以用于以链式方式进一步配置映射。“/internal/**”是一个路径模式,用于使用PathMatcher
与请求URL进行匹配。 我们已经看到在上一个示例中如何配置PathMatcher
,但是默认情况下使用AntPathMatcher
实现。 可以配置多个URL模式以匹配特定的资源位置。addResourceLocations("classpath:/")
方法在新创建ResourceHandlerRegistration
类实例时被调用,它定义了应该从中加载资源的目录。 这些应该是有效的文件系统或类路径目录,并且可以有多个输入。 如果提供了多个位置,将按照输入的顺序进行检查。
我们还可以使用setCachePeriod(Integer cachePeriod)
方法为给定资源配置缓存间隔。
三. 通过EmbeddedServletContainerCustomizer调优Tomcat
Spring Boot公开了许多服务器属性,可以通过简单地设置application.properties中的值来配置诸如PORT,SSL和其他内容的服务器属性。 但是,如果需要进行更复杂的调优,Spring Boot提供了一个EmbeddedServletContainerCustomizer
接口,以编程方式定义配置。
即使会话超时可以通过将application.properties中的server.session-timeout属性设置为我们所需的值(几秒钟)来轻松配置,但是我们仍然使用EmbeddedServletContainerCustomizer
来演示该功能。
我们希望session保持一分钟。 为了实现这一点,在WebConfiguration
类中添加一个EmbeddedServletContainerCustomizer
,其中包含以下内容:
@Bean
public
EmbeddedServletContainerCustomizer
embeddedServletContainerCustomizer() {
return new EmbeddedServletContainerCustomizer() {
@Override
public void
customize(ConfigurableEmbeddedServletContainer
container) {
container.setSessionTimeout(1, TimeUnit.MINUTES);
}
};
}
出于演示的目的,通过调用getSession()
方法来请求会话的请求对象,这将强制其创建。 为此,我们将添加一个新的请求映射到BookController
类,代码如下:
@RequestMapping(value = "/session", method = RequestMethod.GET)
public String getSessionId(HttpServletRequest request) {
return request.getSession().getId();
}
启动 ./gradlew clean bootRun
。
在浏览器中输入 http://localhost:8080/books/session,看到如下结果:
如果我们等待一分钟以上,然后重新加载此页面,则session id将更改为新的 session id。
EmbeddedServletContainerCustomizer
接口定义了自定义customize(ConfigurableEmbeddedServletContainer container)
方法。 这实际上对于使用Java 8的人来说是一个很好的方便,因为返回一个lambda表达式,而不是创建该类的实现。 在这种情况下,它将如下所示:
public EmbeddedServletContainerCustomizer
embeddedServletContainerCustomizer() {
return (ConfigurableEmbeddedServletContainer container) -> {
container.setSessionTimeout(1, TimeUnit.MINUTES);
};
}
在应用程序启动期间,Spring Boot自动配置检测定制器的存在,并调用customize(...)
方法,将引用传递给servlet容器。 在具体的情况下,实际上得到了一个TomcatEmbeddedServletContainerFactory
实现的实例; 但是根据使用的servlet容器的种类不同,如Jetty或Undertow,实现方式将有所不同。
四. 选择嵌入式servlet容器
尽管Tomcat是Spring Boot中的默认嵌入式容器,但并不限于此。 Spring Boot提供Jetty和Undertow的等容器的支持,因此我们可以选择不同的容器。
如果决定使用Jetty作为servlet容器,需要在的构建文件中添加Jetty相关的模块。
首先,由于Tomcat已经作为Spring Boot的传递性依赖,所以我们需要通过将以下内容添加到build.gradle中,将其从构建依赖关系树中排除:
configurations {
compile.exclude module: "spring-boot-starter-tomcat"
}
我们还需要添加Jetty的编译依赖关系:
compile("org.springframework.boot:spring-boot-starter-jetty")
因为WebConfiguration
类中的RemoteIpFilterl
类,是 Tomcat提供的类,所以,我们需要把这块代码注释掉。
/*
@Bean
public RemoteIpFilter remoteIpFilter() {
return new RemoteIpFilter();
}
*/
运行 ./gradlew clean bootRun
。这时查看控制台,出现如下信息,说明Jetty 已经运行了。
这就是Spring Boot的自动配置的强大。 我们必须从构建文件中删除Tomcat依赖关系,以防止Tomcat和Jetty之间的依赖冲突。 Spring Boot对类路径中的类进行条件扫描,并根据其检测到的内容,确定将使用哪个servlet容器。
如果我们查看EmbeddedServletContainerAutoConfiguration
类的源代码,会看到以下条件判读,用于检查Jetty包中是否存在Servlet.class
,Server.class
和Loader.class
中,以确定是否应使用JettyEmbeddedServletContainerFactory
:
/**
* Nested configuration if Jetty is being used.
*/
@Configuration
@ConditionalOnClass({ Servlet.class, Server.class, Loader.class})
@ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
public static class EmbeddedJetty {
@Bean
public JettyEmbeddedServletContainerFactory
jettyEmbeddedServletContainerFactory() {
return new JettyEmbeddedServletContainerFactory();
}
}
@ConditionalOnClass
注解告诉Spring Boot ,当 Jetty 的org.eclipse.jetty.server.Server
和org.eclipse.jetty.util.Loader
类存在 classpath 中,则使用EmbeddedJetty
配置。
五. 添加自定义连接
企业应用程序开发和部署中的另一个常见的情况是使用两个单独的HTTP端口连接器运行应用程序:一个用于HTTP,另一个用于HTTPS。
前面例子中,我们使用了 Jetty 容器,下面的例子,还是使用默认的 tomcat,所以,需要注释掉以前的所有 Jetty 的配置。
为了创建HTTPS连接,我们需要一些东西; 但最重要的是,需要生成用于加密和解密与浏览器的SSL通信的证书密钥库。
如果你使用的是Unix或Mac,可以运行以下命令:
$JAVA_HOME/bin/keytool -genkey -alias tomcat -keyalg RSA
如果是 Windows 系统,使用下面命令:
"%JAVA_HOME%\bin\keytool" -genkey -alias tomcat -keyalg RSA
在创建密钥库期间,你应该输入适合您的信息,包括密码,名称等。 我们将使用默认密码:changeit。 执行完成后,新生成的密钥库文件将在系统主目录(.keystore)出现。
Tips
可以在以下位置找到有关证书密钥库信息:
https://tomcat.apache.org/tomcat-8.0-doc/ssl-howto.html#Prepare_the_Certificate_Keystore
密钥库创建完成后,需要创建一个单独的属性文件,以便存储HTTPS连接的配置,例如端口等。 之后,创建一个配置属性绑定对象,并使用它来配置新的连接。 执行以下步骤:
首先,在src/main/resources目录下创建tomcat.https.properties文件,下面是具体的内容:
custom.tomcat.https.port=8443
custom.tomcat.https.secure=true
custom.tomcat.https.scheme=https
custom.tomcat.https.ssl=true
custom.tomcat.https.keystore=${user.home}/.keystore
custom.tomcat.https.keystore-password=changeit
接下来,在WebConfiguration类中,创建一个静态内部类TomcatSslConnectorProperties
,代码如下:
@ConfigurationProperties(prefix = "custom.tomcat.https")
public static class TomcatSslConnectorProperties {
private Integer port;
private Boolean ssl= true;
private Boolean secure = true;
private String scheme = "https";
private File keystore;
private String keystorePassword;
// 省略了getter 和 setter 方法
public void configureConnector(Connector connector) {
if (port != null)
connector.setPort(port);
if (secure != null)
connector.setSecure(secure);
if (scheme != null)
connector.setScheme(scheme);
if (ssl!= null)
connector.setProperty("SSLEnabled", ssl.toString());
if (keystore!= null && keystore.exists()) {
connector.setProperty("keystoreFile", keystore.getAbsolutePath());
connector.setProperty("keystorePassword", keystorePassword);
}
}
}
现在,需要将新创建的tomcat.http.properties文件添加为Spring Boot属性源,并启用TomcatSslConnectorProperties
绑定。 这可以通过在WebConfiguration
类的类声明之上添加以下代码来完成:
@Configuration
@PropertySource("classpath:/tomcat.https.properties")
@EnableConfigurationProperties(WebConfiguration.TomcatSslConnectorProperties.class)
public class WebConfiguration extends WebMvcConfigurerAdapter {...}
最后,需要创建一个EmbeddedServletContainerFactory
类的bean,用于添加HTTPS连接。 通过将以下代码添加到WebConfiguration
类来实现:
@Bean
public EmbeddedServletContainerFactory servletContainer(TomcatSslConnectorProperties properties) {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
tomcat.addAdditionalTomcatConnectors(createSslConnector(properties)
);
return tomcat;
}
private Connector createSslConnector(TomcatSslConnectorProperties properties) {
Connector connector = new Connector();
properties.configureConnector(connector);
return connector;
}
启动./gradlew clean bootRun
。
在浏览器中输入:https://localhost:8443/internal/tomcat.https.properties,
点击箭头所指部分,然后就会下载 tomcat.https.properties 文件。
上面的程序有一些改动,除了生成密钥库,还创建了tomcat.https.properties配置文件,和创建了TomcatSslConnectorProperties
用于属性绑定。以前,在配置DataSource时,我们已经处理了对application.properties中各种设置的更改。 那时候,我们并不需要创建任何绑定对象,因为Spring Boot已经定义了它们。
如前所述,Spring Boot已经公开了许多属性来配置应用程序设置,包括服务器配置的一整套设置。 这些值绑定到内部Spring Boot类:ServerProperties。
Tips
常见应用程序属性的完整列表可以在Spring Boot参考文档中找到:http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
我们只是简单模仿了 Spring Boot 创建了一个配置文件,并绑定了文件中的属性。之所以没有使用已经存在的“server”前缀,而是选择了“custom.tomcat”的原因是由于ServerProperties
在检测到未知配置字段时禁止重用命名空间并在属性绑定期间抛出异常,因为它将一直在我们这个例子。
@ConfigurationProperties(prefix = "custom.tomcat.https")
对于TomcatSslConnectorProperties
对象来说是一个非常重要的注解。它告诉 Spring Boot 自动绑定“custom.tomcat.https”前缀的属性与TomcatSslConnectorProperties
类中声明的属性。为了进行绑定,除了定义类中的字段之外,定义getter和setter也是非常重要的。 还值得一提的是,在绑定过程中,Spring将自动尝试将属性值转换为适当的数据类型。 例如,custom.tomcat.https.keystore的值自动绑定到一个专用的文件密钥库字段对象。
Tips
我们之前了解的转换器,也可以转换自定义数据类型。
下一步是告诉Spring Boot在属性列表中包含在tomcat.https.properties中定义的属性。 这通过在WebConfiguration类中
的@PropertySource("classpath:/tomcat.https.properties")
注解来实现。
导入属性值之后,需要告诉Spring Boot自动创建一个TomcatSslConnectorProperties
的实例供我们使用。 这是通过添加以下注释来完成的:
@EnableConfigurationProperties(WebConfiguration.TomcatSslConnectorProperties.class)
完成所有属性的设置和完成后,我们将继续执行代码创建第二个连接。 EmbeddedServletContainerFactory bean
的创建为Spring Boot提供了一个工厂类来创建EmbeddedServletContainer
。 添加静态内部类TomcatSslConnectorProperties中
的configureConnector(Connector connector
)方法提供了一个很好的地方来封装和整合配置新创建的Connector实例所需的所有设置。
Spring Boot 学习(3)的更多相关文章
- Spring Boot学习大全(入门)
Spring Boot学习(入门) 1.了解Spring boot Spring boot的官网(https://spring.io),我们需要的一些jar包,配置文件都可以在下载.添置书签后,我自己 ...
- Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客
==他的博客应该不错,没有细看 Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客 http://blog.csdn.net/u012706811/article/det ...
- Spring boot学习1 构建微服务:Spring boot 入门篇
Spring boot学习1 构建微服务:Spring boot 入门篇 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框 ...
- spring boot 学习资料
spring boot 学习资料: 学习资料 网址 Spring Boot Cookbook-极客学院 http://wiki.jikexueyuan.com/project/spring-boot- ...
- Spring Boot学习笔记2——基本使用之最佳实践[z]
前言 在上一篇文章Spring Boot 学习笔记1——初体验之3分钟启动你的Web应用已经对Spring Boot的基本体系与基本使用进行了学习,本文主要目的是更加进一步的来说明对于Spring B ...
- spring boot 学习(十四)SpringBoot+Redis+SpringSession缓存之实战
SpringBoot + Redis +SpringSession 缓存之实战 前言 前几天,从师兄那儿了解到EhCache是进程内的缓存框架,虽然它已经提供了集群环境下的缓存同步策略,这种同步仍然需 ...
- 转载:spring boot学习
Spring Boot学习 Spring Boot是为了简化Spring应用的创建.运行.调试.部署等而出现的,使用它可以做到专注于Spring应用的开发,而无需过多关注XML的配置. 简单来说,它提 ...
- Spring Boot学习路线
Spring Boot 学习路线,本文计划根据作者近几年的工作.学习经验,来分析和制定一个学习使用 Spring Boot技术的步骤路线图. SpringBoot是伴随着Spring4.0诞生的: S ...
- 我的Spring Boot学习记录(二):Tomcat Server以及Spring MVC的上下文问题
Spring Boot版本: 2.0.0.RELEASE 这里需要引入依赖 spring-boot-starter-web 这里有可能有个人的误解,请抱着怀疑态度看. 建议: 感觉自己也会被绕晕,所以 ...
- 15 个优秀开源的 Spring Boot 学习项目,一网打尽!
Spring Boot 算是目前 Java 领域最火的技术栈了,松哥年初出版的 <Spring Boot + Vue 全栈开发实战>迄今为止已经加印了 8 次,Spring Boot 的受 ...
随机推荐
- 在ASP.NET MVC4中配置Castle
---恢复内容开始--- Castle是针对.NET平台的一个非常优秀的开源项目,重点是开源的哦.它在NHibernate的基础上进一步封装,其原理基本与NHibernate相同,但它较好地解决NHi ...
- Java基础学习
1,基本类型和引用类型 基本类型就是一个盒子,数据本身就保存在盒子里面,引用类型的盒子里放的是数据的五:地址,通过这个地址来找到数据. 基本数据类型和堆中对象的引用保存在栈中,引用类型保存在堆中. 2 ...
- 编译MangosZero
最近研究了一下魔兽世界模拟器MangosZero,花了两天时间终于编译成功!现在把编译的过程做个完整的记录,以便让想要学习编译的同学们少走弯路! 服务器端运行界面: 客户端运行界面: 一:下载源程序 ...
- C语言中关于三目运算符的注意事项
C语言中常见的条件运算符?:在运算符优先级中排行13.部分时候可以代替if--else语句,使代码更加简洁.但是更容易隐含一些不易觉察的错误. 最近接了一个项目,本来通信协议部分很简单,自己的STM3 ...
- 前端随手优化不完全篇-SEO篇
一代码优化概述 关于代码优化的知识是纯理论的知识,学习的很枯燥.在学到CSS时,不免遇到CSS+div进行代码优化的知 识,因此在网上看了一些关于这方面的知识,简单的整合一下,梳理自己所了解的代码优化 ...
- C++ struct 初始化的问题
struct student { int age; string name; int id; }; 初始化: student st1={10, "li ming", 01}; 修改 ...
- js解决苹果移动端300ms延迟的问题
做移动端页面开发的可能会了解到,ios系统click事件会有卡顿的现象,这个问题的根源是苹果本身自带的safari有双击放大页面的功能,再次双击会返回到原始尺寸,所以在第一次点击的系统会延迟300ms ...
- OpenGL 的空间变换(上):矩阵在空间几何中的应用
在使用 OpenGL 的应用程序中,当我们指定了模型的顶点后,顶点依次会变换到不同的 OpenGL 空间中,最后才会被显示到屏幕上.在变换的过程中,通过使用矩阵,我们更高效地来完成这些变换工作. 本篇 ...
- windows和linux双系统修改启动项
在windows系统的基础上再装linux系统的时候,电脑启动就会出现linux的启动引导项,默认的是进入linux.要使电脑默认进入windows只需要修改linux系统的启动引导文件(grub.c ...
- PhpMyAdmin导入数据库大小限制?
问题描述: 在phpMyAdmin中导入数据库时,出现问题: 1. 如果按照扩展名.sql导入,提示如下: 没有接收到要导入的数据.可能是文件名没有提交,也可能是文件大小超出 PHP 限制. 2. 如 ...