SpringBoot series of integrated jsp template engine

SpringBoot series of integrated jsp template engine
@

1. Introduction template engine

Reference template engine Baidu Encyclopedia explained:

Template engine (here especially for Web development template engine) is to make the user interface and business data (content) resulting from the separation, it can generate a document in a specific format, for a website template engine will generate a standard HTML document.

There are a few areas in JavaEE more commonly used template engine, namely Jsp, Velocity, Freemarker, Thymeleaf, but for the front page for rendering efficiency, jsp but it is still the fastest, Velocity followed. Thymeleaf While rendering efficiency is not very fast, but the grammar is more compact, lighter than the Velocity Thymeleaf grammar, but rendered less efficient than Velocity

2, prepare the environment

ok, Springboot is a javaee framework, the use of very simple, but also create a default project labeled jar package, starting jar package can be run directly embedded Servlet container such as Tomcat, etc., but Springboot to be integrated template engine, it is jsp not supported by default, but it does not mean that can not be used, first of all Springboot project run by default jar, and our previous projects mostly war jsp packet mode, the jar is packaged webapp project there will be no default, and so these files so we want to create jsp project, you can create a package in the form of project time into war

ok, conduct experiments jsp, the environment to prepare:

  • version:
    • Maven3.9 +
    • SpringBoot2.2.1
  • HERE:
    • IntelliJ IDEA

Creating Springboot Initializer project, a packaging choose war mode
Here Insert Picture Description

Create a good project, there is no default webapp file, so we can manually add or do so in the idea:

Here Insert Picture Description
New web.xml, remember to change the default path down
Here Insert Picture Description
after created, we can look at what is automatically generated project features:

  • The first is one more ServletInitializer class that is doing? Back then speak in detail
    Here Insert Picture Description
  • Pom文件,翻了一下,发现spring-boot-starter-tomcat的作用范围被改成provided的,这个是什么意思?需要补充一下maven的基础知识,maven中三种classpath 编译,测试,运行
    • 1.compile:默认范围,编译测试运行都有效
    • 2.provided:在编译和测试时有效
    • 3.runtime:在测试和运行时有效
    • 4.test:只在测试时有效
    • 5.system:在编译和测试时有效,与本机系统关联,可移植性差
      修改scope为provided,也就是在运行时不起效,也就是打成war包时候,就不引入对应的Tomcat jar包,不使用嵌入式的Tomcat容器,使用外部的Tomcat容器
      Here Insert Picture Description

      3、外部Servlet容器

      Springboot项目创建之后,其实就可以直接创建jsp应用了,然后从其自动生成的配置可以看出我们在创建war包时,是可以使用外部的Tomcat容器的,所以,我们引入一下外部Tomcat
      Here Insert Picture Description

Here Insert Picture Description
部署时候,直接使用暴露的war即可,Application context可以写上也可以不管
Here Insert Picture Description
直接创建一个jsp页面
Here Insert Picture Description
进行页面跳转,写个Controller类:

@Controller
public class HelloController {

    @RequestMapping(value = {"/success"})
    public String toSuccess(){
        return "success";
    }
}

注意:还要向以前那样定义一下mvc的一下配置:

spring.mvc.view.prefix=/WEB-INF/
spring.mvc.view.suffix=.jsp

ok,我之前博客SpringBoot源码学习系列之嵌入式Servlet容器已经比较详细地介绍了Springboot嵌入式Servlet容器的知识,所以本博客有必要对比一下嵌入式的Servlet容器和本博客介绍的外部Servlet容器的区别

  • 外部Servlet容器:maven打包是war形式,先启动Servlet容器,在创建ioc容器
  • 嵌入式Servlet容器:maven打包是jar形式,启动时候先创建ioc容器,再启动嵌入式的Servlet容器,比如Tomcat、undertow等等

4、源码原理简介

Silicon Valley video yet introduced the Servlet specification, turn down the document, find the section as shown, this section describes the creation of the project when the war package automatically creates ServletInitializer classes, introduces runtime shared libraries and plug-ins, which introduced ServletContainerInitializer, that is, Servlet initialize a class using the container, start time will find the corresponding class in the META-INF / services via the configuration file, by @HandlesTypes annotation start time will be needed to introduce the class

。
Global search to find the corresponding configuration in the Spring-web project
Here Insert Picture Description

@HandlesTypes(WebApplicationInitializer.class)//SpringServletContainerInitializer 容器类启动时候会一起创建WebApplicationInitializer类
public class SpringServletContainerInitializer implements ServletContainerInitializer {

    @Override
    public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
            throws ServletException {

        List<WebApplicationInitializer> initializers = new LinkedList<>();

        if (webAppInitializerClasses != null) {
            for (Class<?> waiClass : webAppInitializerClasses) {
                // Be defensive: Some servlet containers provide us with invalid classes,
                // no matter what @HandlesTypes says...
                //检验WebApplicationInitializer不是一个接口、抽象类就进行实例
                if (!waiClass.isInterface() && !Modifier.isAbstract(waiClass.getModifiers()) &&
                        WebApplicationInitializer.class.isAssignableFrom(waiClass)) {
                    try {
                        initializers.add((WebApplicationInitializer)
                                ReflectionUtils.accessibleConstructor(waiClass).newInstance());
                    }
                    catch (Throwable ex) {
                        throw new ServletException("Failed to instantiate WebApplicationInitializer class", ex);
                    }
                }
            }
        }

        if (initializers.isEmpty()) {
            servletContext.log("No Spring WebApplicationInitializer types detected on classpath");
            return;
        }

        servletContext.log(initializers.size() + " Spring WebApplicationInitializers detected on classpath");
        AnnotationAwareOrderComparator.sort(initializers);
        //遍历获取到的WebApplicationInitializer 类,调用其对应的onStartup方法
        for (WebApplicationInitializer initializer : initializers) {
            initializer.onStartup(servletContext);
        }
    }

}

WebApplicationInitializer is actually an interface class, it opened its implementation class, you can see SpringBootServletInitializer class
Here Insert Picture Description
SpringBootServletInitializer class implements WebApplicationInitializer interface, will be created in the Servlet container startup time while performing onStartup method, as shown, to find the key points:

Here Insert Picture Description
createRootApplicationContext method is created according to the container, look at the source:

protected WebApplicationContext createRootApplicationContext(ServletContext servletContext) {
        //创建SpringApplication的构建器
        SpringApplicationBuilder builder = createSpringApplicationBuilder();
        builder.main(getClass());//设置main方法
        ApplicationContext parent = getExistingRootWebApplicationContext(servletContext);
        if (parent != null) {
            this.logger.info("Root context already created (using as parent).");
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, null);
            //构建器初始化
            builder.initializers(new ParentContextApplicationContextInitializer(parent));
        }
        builder.initializers(new ServletContextApplicationContextInitializer(servletContext));
        builder.contextClass(AnnotationConfigServletWebServerApplicationContext.class);
        //关键点,调用configure方法
        builder = configure(builder);
        builder.listeners(new WebEnvironmentPropertySourceInitializer(servletContext));
        SpringApplication application = builder.build();
        if (application.getAllSources().isEmpty()
                && MergedAnnotations.from(getClass(), SearchStrategy.TYPE_HIERARCHY).isPresent(Configuration.class)) {
            application.addPrimarySources(Collections.singleton(getClass()));
        }
        Assert.state(!application.getAllSources().isEmpty(),
                "No SpringApplication sources have been defined. Either override the "
                        + "configure method or add an @Configuration annotation");
        // Ensure error pages are registered
        if (this.registerErrorPageFilter) {
            application.addPrimarySources(Collections.singleton(ErrorPageFilterConfiguration.class));
        }
        //启动Application类
        return run(application);
    }

Find the key point configure method from this source, it continues with this method, the base class method is very simple, just return the constructor
Here Insert Picture Description
so, in the idea in the ctrl + alt + B to open its realization, as seen key point, this is not ServletInitializer class is automatically created? And rewrite the configure method, and the Springboot Application class to the constructor class, so now here to understand why Servlet container when it will start to create a trigger ioc container Springboot
Here Insert Picture Description

Download code examples: GitHub download link

Guess you like

Origin www.cnblogs.com/mzq123/p/12006845.html