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提供了大量模板引擎, 包含括FreeMarkerGroovyThymeleafVelocity和MustacheSpring Boot中推荐
使用Thymeleaf作为模板引擎, 因为Thymeleaf提供了完美的Spring MVC的支持。

  在Spring Bootorg.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所需的TemplateResolverTemplateEngineSpringWebFluxTemplateEngine以及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配置:

@Controllerpublic 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 方法会自动加载ConverterGenericConverter以及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,只需要在自定义的HttpMessageConvertersBean注册自定义HttpMessageConverter即可。
如下:

注册自定义的HttpMessageConverter

@Configurationpublic 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配置属性

  1. application.properties配置属性即可,Tomcat是以"server.tomcat"为前缀的特有配置属性,通用的是以"server"作为前缀;
  2. 通过实现WebServerFactoryCustomizer接口自定义属性配置类即可,同理其他服务器实现对应的接口即可。

application.properties配置属性:

#通用Servlet容器配置server.port=8888#tomcat容器配置#配置Tomcat编码, 默认为UTF-8server.tomcat.uri-encoding = UTF-8# Tomcat是否开启压缩, 默认为关闭offserver.tomcat.compression=off

实现WebServerFactoryCustomizer接口自定义:

/** * 配置tomcat属性 * @Auther: ccww * @Date: 2019/10/5 23:22 * @Description:  */@Componentpublic 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 默认Servlet容器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笔记】 一起学习,每天会分享干货,还有学习视频领取!