文 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路径与控制器参数相匹配:

如果要进一步配置路径匹配的方式,可以提供自己的PathMatcherUrlPathHelper实现,但这些在最极端和自定义的情况下都是必需的,一般情况下不推荐使用。

二. 配置自定义静态路径映射

在前面的内容中,我们讲解了如何调整请求的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.classServer.classLoader.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.Serverorg.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)的更多相关文章

  1. Spring Boot学习大全(入门)

    Spring Boot学习(入门) 1.了解Spring boot Spring boot的官网(https://spring.io),我们需要的一些jar包,配置文件都可以在下载.添置书签后,我自己 ...

  2. Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客

    ==他的博客应该不错,没有细看 Spring Boot学习记录(二)--thymeleaf模板 - CSDN博客 http://blog.csdn.net/u012706811/article/det ...

  3. Spring boot学习1 构建微服务:Spring boot 入门篇

    Spring boot学习1 构建微服务:Spring boot 入门篇 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框 ...

  4. spring boot 学习资料

    spring boot 学习资料: 学习资料 网址 Spring Boot Cookbook-极客学院 http://wiki.jikexueyuan.com/project/spring-boot- ...

  5. Spring Boot学习笔记2——基本使用之最佳实践[z]

    前言 在上一篇文章Spring Boot 学习笔记1——初体验之3分钟启动你的Web应用已经对Spring Boot的基本体系与基本使用进行了学习,本文主要目的是更加进一步的来说明对于Spring B ...

  6. spring boot 学习(十四)SpringBoot+Redis+SpringSession缓存之实战

    SpringBoot + Redis +SpringSession 缓存之实战 前言 前几天,从师兄那儿了解到EhCache是进程内的缓存框架,虽然它已经提供了集群环境下的缓存同步策略,这种同步仍然需 ...

  7. 转载:spring boot学习

    Spring Boot学习 Spring Boot是为了简化Spring应用的创建.运行.调试.部署等而出现的,使用它可以做到专注于Spring应用的开发,而无需过多关注XML的配置. 简单来说,它提 ...

  8. Spring Boot学习路线

    Spring Boot 学习路线,本文计划根据作者近几年的工作.学习经验,来分析和制定一个学习使用 Spring Boot技术的步骤路线图. SpringBoot是伴随着Spring4.0诞生的: S ...

  9. 我的Spring Boot学习记录(二):Tomcat Server以及Spring MVC的上下文问题

    Spring Boot版本: 2.0.0.RELEASE 这里需要引入依赖 spring-boot-starter-web 这里有可能有个人的误解,请抱着怀疑态度看. 建议: 感觉自己也会被绕晕,所以 ...

  10. 15 个优秀开源的 Spring Boot 学习项目,一网打尽!

    Spring Boot 算是目前 Java 领域最火的技术栈了,松哥年初出版的 <Spring Boot + Vue 全栈开发实战>迄今为止已经加印了 8 次,Spring Boot 的受 ...

随机推荐

  1. asp.net core 编译mvc,routing,security源代码进行本地调试

    因为各种原因,需要查看asp.net core mvc的源代码来理解运行机制等等,虽说源代码查看已经能很好的理解了.但是能够直接调试还是最直观的.所有就有了本次尝试. 因调试设置源代码调试太辍笔,所以 ...

  2. vue实现简单表格组件

    本来想这一周做一个关于vuex的总结的,但是由于朋友反应说还不知道如何用vue去写一个组件,所以在此写写一篇文章来说明下如何去写vue页面或者组件.vue的核心思想就是组件,什么是组件呢?按照我的理解 ...

  3. 【算法】RMQ LCA 讲课杂记

    4月4日,应学弟要求去了次学校给小同学们讲了一堂课,其实讲的挺内容挺杂的,但是目的是引出LCA算法. 现在整理一下当天讲课的主要内容: 开始并没有直接引出LCA问题,而是讲了RMQ(Range Min ...

  4. 学习java分为几个阶段,分别是什么?

    多年前我自学的时候是很茫然,上网问问题,总是一堆外行的人说很难啊,你需要这样需要那样,不然就是,一堆人说一些空话,多看多写,买好书,我很无语,除了这些就没有自己的一些想法吗? 首先很多人认为学JAVA ...

  5. 函数, lambda表达式

    函数 函数:简单的理解,就是一次执行很多行代码 函数的返回值 函数的参数,和变量没区别 例: def hello(): print "hello world" hello() he ...

  6. Python生产环境部署(fastcgi,uwsgi)

    Python部署web开发程序的几种方法 fastcgi ,通过flup模块来支持,在nginx里对应的配置指令是 fastcgi_pass http,nginx使用proxy_pass转发,这个要求 ...

  7. [移动端] IOS下border-image不起作用的解决办法

    上周五突然接到现场的一个需求,做一个移动端的劳模展示页面.现场美工把原型图发了过来.这个样子的: 说实在的很想吐槽一下我们美工的审美哈,不过这不是重点. 因为边框是需要特殊花纹的所以打算用border ...

  8. Stimulsoft报表操作笔记(一):统计

    一.引言 报表大家应该都知道是什么,简单来说就是用表格.图表等格式来动态显示数据.现在web系统中很多需要使用到报表统计.打印功能等,将所需用到的数据绑定到指定的位置,然后分类汇总,这样查看起来更清晰 ...

  9. mysql for windows(服务器)上的配置安装--实例

    mysql for windows(服务器)上的配置安装 **** 下载 官网网址:https://www.mysql.com/downloads/ 选择左上角Community 再选择MySQL C ...

  10. Java的CLASSPATH

    在JDK安装好后,要设置两个变量Path和Classpath,Path是操作系统要求的,这里不谈了,而classpath是Java虚拟机要求的这里做一个详细的解释. 一.classpath的作用 == ...