[SpringBoot 2.x] - Thymeleaf, Web, Tomcat and Favicon in SpringBoot Web Development

Keywords: Java Spring Thymeleaf Tomcat encoding

github: https://github.com/Ccww-lx/Sp...
Module: spring-boot-starter-base-web

Web development is a very important part of development. The core content of Web development mainly includes embedded Servlet container and Spring MVC. More importantly, Spring Boot `provides a quick and convenient way for web development. It uses dependency jar: spring-boot-starter-web to provide dependencies of embedded server Tomcat and Spring MVC, and automatically configures web-related configurations. You can see org. spring framework. boot. autoconfigure. web`.

Core Web-related functions:

  • Thymeleaf Template Engine
  • Web-related configuration
  • Tomcat configuration
  • Favicon configuration

1. Template configuration

1.1 principle and source code analysis

_Spring Boot provides a large number of template engines, including FreeMarker, Groovy, Thymeleaf, Velocity and Mustache, recommended in Spring Boot
Thymeleaf is used as a template engine because Thymeleaf provides perfect Spring MVC support.

__implements automatic configuration under Spring Boot's package of org.spring framework.boot.autoconfigure.thymeleaf, as follows:

ThymeleafAutoConfiguration source code:

@Configuration
@EnableConfigurationProperties(ThymeleafProperties.class)
@ConditionalOnClass({ TemplateMode.class, SpringTemplateEngine.class })
@AutoConfigureAfter({ WebMvcAutoConfiguration.class, WebFluxAutoConfiguration.class })
public class ThymeleafAutoConfiguration {

        // Configure Template Resolver
    @Configuration
    @ConditionalOnMissingBean(name = "defaultTemplateResolver")
    static class DefaultTemplateResolverConfiguration {
            ...
    }
    
        // Configure Template Engine
    @Configuration
    protected static class ThymeleafDefaultConfiguration {
            ...
    }
        // Configure Spring Web Flux Template Engine
    @Configuration
    @ConditionalOnWebApplication(type = Type.SERVLET)
    @ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true)
    static class ThymeleafWebMvcConfiguration {
           ...
    }
    
        // Configure thymeleafViewResolver
    @Configuration
    @ConditionalOnWebApplication(type = Type.REACTIVE)
    @ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true)
    static class ThymeleafWebFluxConfiguration {
           ...
    }
    ...
}

Thymeleaf AutoConfiguration automatically loads Template Resolver, Template Engine, Spring Web Flux Template Engine and thymeleafViewResolver required by the Web, and configures Thymeleaf properties through Thymeleaf Properties. Check the official source code for details.

ThymeleafProperties source code:


//Read the properties of the application.properties configuration file
@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 Template file prefix path property, Spring boot default path is classpath:/templates/
     */
    private String prefix = DEFAULT_PREFIX;

    /**
     * Web Template file suffix property, default html
     */
    private String suffix = DEFAULT_SUFFIX;

    /**
     * Web Template schema attribute, default HTML
     */
    private String mode = "HTML";

    /**
     *  Web Template file encoding property, defaults to UTF_8
     */
    private Charset encoding = DEFAULT_ENCODING;

        ....
}

As you can see from Thymeleaf Properties, Thymeleaf's default settings and Thymeleaf's default configuration can be modified by prefixing the spring.thymeleaf property.

1.2 example

1. According to the default Thymeleaf configuration, under src/main/resources/, create static folders to store script-style static files and templates folders to store pages suffixed with html, as follows:

2)index.html page

<!DOCTYPE html>
<!-- Import xmlns:  th=http://www.thymeleaf.org namespace - >
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
 <head>
     <meta charset="UTF-8">
    <title>First detail</title>
 </head>
  <body>
    <div class="user" align="center"  width="400px" height="400px">
        message: <span th:text="${user.message}"/><br/>
       //Username: <span: text="${user.username}"/> <br/>
         //Password: <span: text="${user.password}"/>
    </div>
 </body>
</html>

3) Controller configuration:

@Controller
public class LoginController {
    @Autowired
    private LoginService loginService;
    
    /**
     * Set the home page to login.html
     * @return
     */
    @RequestMapping("/")
    public String startIndex() {
        return "login";
    }

    /**
     *  Landing verification
     * @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-related configuration

Understand the automatic configuration principle provided by Spring Boot based on WebMvcAutoConfiguration and WebMvcProperties.

2.1 ViewResolver and static resources

Spring boot automatically configures ViewResolver:

  • Content Negotiating ViewResolver (highest priority Ordered.HIGHEST_PRECEDENCE)
  • BeanNameViewResolver
  • InternalResourceViewResolver

Static resources:
_addResourceHandlers method defines by default the static files under / static, / public, / resources and / METAINF/resources folders mapped directly to /**

2.2 Formatter and Converter type converters

The_addFormatters method automatically loads Converter, GenericConverter and Formatter implementation classes and registers them in Spring MVC, so the custom type converter only needs to inherit its three interfaces.

Custom Formatter:


/**
 * Convert the format to ccww: ccww88 to 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 and response converters)

The configureMessageConverters method automatically configures HttpMessageConverters:

public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            this.messageConvertersProvider.ifAvailable((customConverters) -> converters
                    .addAll(customConverters.getConverters()));
        }

By loading HttpMessageConverters defined by HttpMessageConverters AutoConfiguration, a series of HttpMessage Converter classes are automatically registered, such as Spring MVC default:

  • ByteArrayHttpMessageConverter
  • StringHttpMessageConverter
  • ResourceHttpMessageConverter
  • SourceHttpMessageConverter
  • AllEncompassingFormHttpMessageConverter

To customize HttpMessageConverters, you just need to register the customized HttpMessageConverters in the Bean of the customized HttpMessageConverters.
As follows:

Register a custom HTTP MessageConverter:

@Configuration
public class CustomHttpMessageConverterConfig {
    @Bean
    public HttpMessageConverters converter(){
        HttpMessageConverter<?> userJsonHttpMessageConverter=new UserJsonHttpMessageConverter();
        return new HttpMessageConverters(userJsonHttpMessageConverter);
    }
}

Customize 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());
    }
}

Similarly, you can register Servlet s, Filter s, and Listener s relative to each other.

2.4 MVC related configuration

_. Adding @EnableWebMvc to a custom MVC configuration class will discard the default configuration of Spring boot and control the MVC configuration entirely by itself, but usually Spring boot default configuration + the additional MVC configuration required, just need the configuration class to inherit WebMvc Configurer Adapter.

2.5 Tomcat configuration

There are two ways to configure Tomcat properties

  1. In application.properties, Tomcat is a special configuration attribute prefixed with "server.tomcat", and in general, it is prefixed with "server".
  2. By implementing the Web Server FactoryCustomizer interface to customize the attribute configuration class, the corresponding interface can be implemented by other servers.

application.properties configuration properties:

#General Servlet container configuration
server.port=8888

#tomcat container configuration
#Configure Tomcat encoding, defaults to UTF-8
server.tomcat.uri-encoding = UTF-8
# Whether Tomcat turns on compression or not, the default is to turn off
server.tomcat.compression=off

Implement Web Server FactoryCustomizer interface customization:

/**
 * Configure tomcat attributes
 * @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);
            }
        });
    }
}

Replace spring boot default Servlet container tomcat, exclude directly from dependencies, and import the corresponding Servlet container dependencies:

<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 Custom Favicon

_Custom Favicon only needs to place its own favicon.ico file in the root directory of the class path, META-INF/resources/under the class path, resources/under the class path, static/under the class path or public/under the class path.



Finally, we can pay attention to the public address: [ccww notes] learn together, share dry goods every day, and learn video to collect!

Posted by virva on Sat, 05 Oct 2019 20:47:38 -0700