乐趣区

SpringBoot2xSpringBoot-Web开发中ThymeleafWebTomcat以及Favicon

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配置:

@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 方法会自动加载 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

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

  1. application.properties 配置属性即可,Tomcat是以 ”server.tomcat“ 为前缀的特有配置属性,通用的是以 ”server“ 作为前缀;
  2. 通过实现 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 笔记】一起学习, 每天会分享干货,还有学习视频领取!

退出移动版