共计 7857 个字符,预计需要花费 20 分钟才能阅读完成。
github:https://github.com/Ccww-lx/Sp… 模块:spring-boot-starter-base-web
Web
开发是开发中至关重要的一部分,Web
开发的核心内容主要包括内嵌 Servlet
容器和 Spring MVC
。更重要的是,Spring Boot
` 为 web 开发提供了快捷便利的方式进行开发,使用依赖 jar:
spring-boot-starter-web, 提供了嵌入式服务器
Tomcat 以及
Spring MVC 的依赖,且自动配置
web 相关配置,可查看
org.springframework.boot.autoconfigure.web`。
Web
相关的核心功能:
-
Thymeleaf
模板引擎 -
Web
相关配置 -
Tomcat
配置 -
Favicon
配置
1. 模板配置
1.1 原理以及源码分析
Spring Boot
提供了大量模板引擎,包含括 FreeMarker
、Groovy
、Thymeleaf
、Velocity 和 Mustache
,Spring Boot
中推荐
使用 Thymeleaf
作为模板引擎,因为 Thymeleaf
提供了完美的 Spring MVC
的支持。
在 Spring Boot
的org.springframework.boot.autoconfigure.thymeleaf
包下实现自动配置,如下所示:
ThymeleafAutoConfiguration
源码:
@Configuration
@EnableConfigurationProperties(ThymeleafProperties.class)
@ConditionalOnClass({TemplateMode.class, SpringTemplateEngine.class})
@AutoConfigureAfter({WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class})
public class ThymeleafAutoConfiguration {
// 配置 TemplateResolver
@Configuration
@ConditionalOnMissingBean(name = "defaultTemplateResolver")
static class DefaultTemplateResolverConfiguration {...}
// 配置 TemplateEngine
@Configuration
protected static class ThymeleafDefaultConfiguration {...}
// 配置 SpringWebFluxTemplateEngine
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true)
static class ThymeleafWebMvcConfiguration {...}
// 配置 thymeleafViewResolver
@Configuration
@ConditionalOnWebApplication(type = Type.REACTIVE)
@ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true)
static class ThymeleafWebFluxConfiguration {...}
...
}
ThymeleafAutoConfiguration
自动加载 Web
所需的 TemplateResolver
、TemplateEngine
、SpringWebFluxTemplateEngine
以及 thymeleafViewResolver
,并通过ThymeleafProperties
进行 Thymeleaf
属性配置。详细细节查看官方源码。
ThymeleafProperties
源码:
// 读取 application.properties 配置文件的属性
@ConfigurationProperties(prefix = "spring.thymeleaf")
public class ThymeleafProperties {
private static final Charset DEFAULT_ENCODING = StandardCharsets.UTF_8;
public static final String DEFAULT_PREFIX = "classpath:/templates/";
public static final String DEFAULT_SUFFIX = ".html";
/**
*Web 模板文件前缀路径属性,Spring boot 默认路径为 classpath:/templates/
*/
private String prefix = DEFAULT_PREFIX;
/**
* Web 模板文件后缀属性,默认为 html
*/
private String suffix = DEFAULT_SUFFIX;
/**
* Web 模板模式属性,默认为 HTML
*/
private String mode = "HTML";
/**
* Web 模板文件编码属性,默认为 UTF_8
*/
private Charset encoding = DEFAULT_ENCODING;
....
}
可以从 ThymeleafProperties
中看出,Thymeleaf
的默认设置,以及可以通过前缀为 spring.thymeleaf
属性修改 Thymeleaf
默认配置。
1.2 示例
1). 根据默认 Thymeleaf
配置,在 src/main/resources/
下,创建 static
文件夹存放脚本样式静态文件以及 templates
文件夹存放后缀为 html 的页面,如下所示:
2)index.html 页面
<!DOCTYPE html>
<!-- 导入 xmlns:th=http://www.thymeleaf.org 命名空间 -->
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<title> 首面详细 </title>
</head>
<body>
<div class="user" align="center" width="400px" height="400px">
message:<span th:text="${user.message}"/><br/>
用户名:<span th:text="${user.username}"/><br/>
密码:<span th:text="${user.password}"/>
</div>
</body>
</html>
3).controller
配置:
@Controller
public class LoginController {
@Autowired
private LoginService loginService;
/**
* 将首页设置为登陆页面 login.html
* @return
*/
@RequestMapping("/")
public String startIndex() {return "login";}
/**
* 登陆验证
* @param username
* @param password
* @param model
* @return
*/
@RequestMapping("/login")
public String login(@RequestParam("username") String username, @RequestParam("password") String password, Model model) {UserDTO userDTO = loginService.login(username, password);
model.addAttribute("user", userDTO);
return "index";
}
}
2. web
相关配置
根据 WebMvcAutoConfiguration
以及 WebMvcProperties
理解 Spring Boot
提供的自动配置原理。
2.1 ViewResolver
以及静态资源
Spring boot
自动配置ViewResolver
:
-
ContentNegotiatingViewResolver
(最高优先级Ordered.HIGHEST_PRECEDENCE
) BeanNameViewResolver
InternalResourceViewResolver
静态资源 :
addResourceHandlers
方法默认定义了/static
、/public
、/resources
和/METAINF/resources
文件夹下的静态文件直接映射为/**
2.2 Formatter 和 Converter 类型转换器
addFormatters
方法会自动加载 Converter
、GenericConverter
以及 Formatter
的实现类、并注册到 Spring MVC 中,因此自定义类型转换器只需继承其三个接口即可。
自定义Formatter
:
/**
* 将格式为 ccww:ccww88 转为 UserDTO
*
* @Auther: ccww
* @Date: 2019/10/4 16:25
* @Description:
*/
public class StringToUserConverter implements Converter<String, UserDTO> {
@Nullable
public UserDTO convert(String s) {UserDTO userDTO = new UserDTO();
if (StringUtils.isEmpty(s))
return userDTO;
String[] item = s.split(":");
userDTO.setUsername(item[0]);
userDTO.setPassword(item[1]);
return userDTO;
}
}
2.3 HttpMessageConverters
(HTTP request
(请求)和 response
(响应) 的转换器)
configureMessageConverters
方法自动配置 HttpMessageConverters:
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {this.messageConvertersProvider.ifAvailable((customConverters) -> converters
.addAll(customConverters.getConverters()));
}
通过加载由 HttpMessageConvertersAutoConfiguration
定义的 HttpMessageConverters
,会自动注册一系列HttpMessage Converter
类,比如 Spring MVC
默认:
ByteArrayHttpMessageConverter
StringHttpMessageConverter
ResourceHttpMessageConverter
SourceHttpMessageConverter
AllEncompassingFormHttpMessageConverter
自定义 HttpMessageConverters
,只需要在自定义的HttpMessageConverters
的Bean
注册自定义 HttpMessageConverter
即可。
如下:
注册自定义的HttpMessageConverter
:
@Configuration
public class CustomHttpMessageConverterConfig {
@Bean
public HttpMessageConverters converter(){HttpMessageConverter<?> userJsonHttpMessageConverter=new UserJsonHttpMessageConverter();
return new HttpMessageConverters(userJsonHttpMessageConverter);
}
}
自定义HttpMessageConverter
:
public class UserJsonHttpMessageConverter extends AbstractHttpMessageConverter<UserDTO> {private static Charset DEFUALT_ENCODE=Charset.forName("UTF-8");
public UserJsonHttpMessageConverter(){super(new MediaType("application", "xxx-ccww", DEFUALT_ENCODE));
}
protected boolean supports(Class aClass) {return UserDTO.class == aClass;}
protected UserDTO readInternal(Class aClass, HttpInputMessage httpInputMessage) throws IOException, HttpMessageNotReadableException {String message = StreamUtils.copyToString(httpInputMessage.getBody(), DEFUALT_ENCODE);
String[] messages = message.split("-");
UserDTO userDTO = new UserDTO();
userDTO.setUsername(messages[0]);
userDTO.setMessage(messages[1]);
return userDTO;
}
protected void writeInternal(UserDTO userDTO, HttpOutputMessage httpOutputMessage) throws IOException, HttpMessageNotWritableException {String out = "ccww:" + userDTO.getUsername() + "-" + userDTO.getMessage();
httpOutputMessage.getBody().write(out.getBytes());
}
}
同理,可以将 Servlet、Filter 以及 Listener 相对于的注册即可。
2.4 MVC 相关配置
自定义的 MVC 配置类上加 @EnableWebMvc
将废弃到 Spring boot
默认配置,完全由自己去控制 MVC
配置,但通常 是 Springboot
默认配置 + 所需的额外 MVC
配置,只需要配置类继承 WebMvcConfigurerAdapter
即可
2.5 Tomcat
配置
可以使用两种方式进行 Tomcat
配置属性
- 在
application.properties
配置属性即可,Tomcat
是以 ”server.tomcat
“ 为前缀的特有配置属性,通用的是以 ”server
“ 作为前缀; - 通过实现
WebServerFactoryCustomizer
接口自定义属性配置类即可,同理其他服务器实现对应的接口即可。
application.properties
配置属性:
# 通用 Servlet 容器配置
server.port=8888
#tomcat 容器配置
#配置 Tomcat 编码,默认为 UTF-8
server.tomcat.uri-encoding = UTF-8
# Tomcat 是否开启压缩,默认为关闭 off
server.tomcat.compression=off
实现 WebServerFactoryCustomizer
接口自定义:
/**
* 配置 tomcat 属性
* @Auther: ccww
* @Date: 2019/10/5 23:22
* @Description:
*/
@Component
public class CustomTomcatServletContainer implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {public void customize(ConfigurableServletWebServerFactory configurableServletWebServerFactory) {((TomcatServletWebServerFactory)configurableServletWebServerFactory).addConnectorCustomizers(new TomcatConnectorCustomizer() {public void customize(Connector connector) {Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
protocol.setMaxConnections(200);
protocol.setMaxThreads(200);
protocol.setSelectorTimeout(3000);
protocol.setSessionTimeout(3000);
protocol.setConnectionTimeout(3000);
protocol.setPort(8888);
}
});
}
}
替换 spring boot
默认Servle
t 容器tomcat
,直接在依赖中排除,并导入相应的Servlet
容器依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starterweb</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-startertomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starterjetty</artifactId>
</dependency
2.6 自定义Favicon
自定义 Favicon
只需要则只需将自己的 favicon.ico
(文件名不能变动)文件放置在类路径根目录、类路径META-INF/resources/
下、类路径 resources/
下、类路径 static/
下或类路径 public/
下。
最后可关注公众号:【ccww 笔记】一起学习, 每天会分享干货,还有学习视频领取!