Spring Boot与Web开发(下)

本文详细介绍了SpringBoot如何配置和使用嵌入式Servlet容器,如Tomcat、Jetty和Undertow。内容包括如何修改默认的Servlet容器配置、注册servlet组件、切换不同Servlet容器以及自动配置原理。此外,还探讨了如何在外部Servlet容器中启动SpringBoot应用,以及SpringBoot作为单体Web应用的使用场景,如整合模板引擎FreeMarker。
摘要由CSDN通过智能技术生成

目录

4.SpringBoot的嵌入式Servlet容器

1.嵌入式Servlet容器配置修改

2.注册servlet三大组件

3.切换其他嵌入式Servlet容器

4.嵌入式Servlet容器自动配置原理

5.使用外部Servlet容器

6.外部Servlet容器启动SpringBoot应用原理

5.SpringBoot作为单体Web应用的使用


4.SpringBoot的嵌入式Servlet容器

Spring 默认的Servlet容器是:Tomcat, 当前SpringBoot 2.3.6 的版本是对应 tomcat9

https://note.youdao.com/yws/public/resource/a1475b8cffccdffcd309dd2a11832a35/xmlnote/A94ACAD9490445C8A838A57715B14515/80D8C467B30641CD87B31574C86C997B/11380

1.嵌入式Servlet容器配置修改

  • 1.通过全局配置文件修改
    • 如果带了具体的服务器名称则是单独对该服务器进行设置,比如 server.tomcat.xxx 就是专门针对tomcat的配置
    • 可以通过server.xxx 来进行web服务配置, 没有带服务器名称的则是通用配置
server.port=8080
server.servlet.context-path=/tomcat
  • 2.通过WebServerFactoryCustomizer的Bean修改
    • 修改server.xxx 配置的相关内容
    • 会跟配置文件形成互补

@Component
public class CustomizationBean implements WebServerFactoryCustomizer<ConfigurableServletWebServerFactory> {

    @Override
    public void customize(ConfigurableServletWebServerFactory factory) {
        factory.setPort(8088);
        factory.setContextPath("/customTomcat");
    }

}

2.注册servlet三大组件

  • servlet listener filter

servlet3.0规范提供的注解方式注册

@WebServlet
@WebListener
@WebFilter

        1.声明servlet 及映射

@WebServlet(name="HelloServlet",urlPatterns = "/HelloServlet")
/*@WebListener
@WebFilter*/
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        PrintWriter writer = resp.getWriter();
        writer.println("hello servlet!");

    }
}

        2.加上@ServletComponentScan才会扫描那3个注解

@SpringBootApplication
@ServletComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

SpringBoot提供的注册

使用ServletRegistrationBeanFilterRegistrationBean以及ServletListenerRegistrationBean

@Configuration
public class MyWebMvcConfigurer  {

    @Bean
    public ServletRegistrationBean myServlet(){
        // 声明一个servlet注册器Bean
        ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean();
        // 设置相应的servlet
        servletRegistrationBean.setServlet(new BeanServlet());
        // 设置名字
        servletRegistrationBean.setName("BeanServlet");
        // 添加映射规则
        servletRegistrationBean.addUrlMappings("/BeanServlet");
        return servletRegistrationBean;

    }
}

3.切换其他嵌入式Servlet容器

  • Spring Boot包含对嵌入式TomcatJettyUndertow服务器的支持
    • tomcat(默认)
    • Jetty(socket)
    • Undertow(响应式)
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <!--1.排除tomcat-->
    <exclusions>
        <exclusion>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <groupId>org.springframework.boot</groupId>
        </exclusion>
    </exclusions>
</dependency>

<!--2.依赖jetty
<dependency>
    <artifactId>spring-boot-starter-jetty</artifactId>
    <groupId>org.springframework.boot</groupId>
</dependency>-->

<!--2.依赖undertow
<dependency>
    <artifactId>spring-boot-starter-undertow</artifactId>
    <groupId>org.springframework.boot</groupId>
</dependency>-->

4.嵌入式Servlet容器自动配置原理

  • ServletWebServerFactoryAutoConfiguration servlet容器自动配置类
@Configuration(proxyBeanMethods = false)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
// 只要依赖任意一个servlet容器都会存在该来ServletRequest
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
// 启用servet.xxx的所有的配置信息绑定到ServerProperties
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
		ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
		ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
		ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {

1.为什么可以根据配置的依赖自动使用对应的servlet容器?

        通过@Import 导入Embeddedxxxx

@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
		ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
		ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
		ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })

每个Embeddedxxxx 中都配置了相应的@ConditionalOnClass,会根据当前servlet容器start依赖判断classpath是否存在对应的类, 如果存在就使用对应的servlet容器。 比如EmbeddedTomcat:

https://note.youdao.com/yws/public/resource/a1475b8cffccdffcd309dd2a11832a35/xmlnote/A94ACAD9490445C8A838A57715B14515/92C2105FA7004E2C861F5C7D7DD3A09E/11551

2.怎么根据配置文件中server.xxx 以及 WebServerFactoryCustomizer 去设置servlet容器属性?

  • ServletWebServerFactoryCustomizer 也实现了WebServerFactoryCustomizer ,说明它也是定制servlet容器的
  • Servlet容器配置文件通用定制器
	@Bean
	public ServletWebServerFactoryCustomizer servletWebServerFactoryCustomizer(ServerProperties serverProperties) {
		return new ServletWebServerFactoryCustomizer(serverProperties);
	}

https://note.youdao.com/yws/public/resource/a1475b8cffccdffcd309dd2a11832a35/xmlnote/A94ACAD9490445C8A838A57715B14515/6D8AAAE1106E4C088402F37A0EF65C94/11555

        根据配置文件中server.xxx 来进行定制servlet容器

ServletWebServerFactoryCustomizer类中的customize方法

	@Override
	public void customize(ConfigurableServletWebServerFactory factory) {
		PropertyMapper map = PropertyMapper.get().alwaysApplyingWhenNonNull();
 // if(serverProperties.getPort()!=null){
    //      factory.setPort(serverProperties.getPort())
   //}
		map.from(this.serverProperties::getPort).to(factory::setPort);
		map.from(this.serverProperties::getAddress).to(factory::setAddress);
		map.from(this.serverProperties.getServlet()::getContextPath).to(factory::setContextPath);
		map.from(this.serverProperties.getServlet()::getApplicationDisplayName).to(factory::setDisplayName);
		map.from(this.serverProperties.getServlet()::isRegisterDefaultServlet).to(factory::setRegisterDefaultServlet);
		map.from(this.serverProperties.getServlet()::getSession).to(factory::setSession);
		map.from(this.serverProperties::getSsl).to(factory::setSsl);
		map.from(this.serverProperties.getServlet()::getJsp).to(factory::setJsp);
		map.from(this.serverProperties::getCompression).to(factory::setCompression);
		map.from(this.serverProperties::getHttp2).to(factory::setHttp2);
		map.from(this.serverProperties::getServerHeader).to(factory::setServerHeader);
		map.from(this.serverProperties.getServlet()::getContextParameters).to(factory::setInitParameters);
		map.from(this.serverProperties.getShutdown()).to(factory::setShutdown);
	}
  • TomcatServletWebServerFactoryCustomizer Tomcat配置文件定制器
    • 根据配置文件中servet.tomcat.xxxx 定制servlet容器
	@Bean
	@ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")
	public TomcatServletWebServerFactoryCustomizer tomcatServletWebServerFactoryCustomizer(
			ServerProperties serverProperties) {
		return new TomcatServletWebServerFactoryCustomizer(serverProperties);
	}

 TomcatServletWebServerFactoryCustomizer 类中的customize方法

	@Override
	public void customize(TomcatServletWebServerFactory factory) {
		ServerProperties.Tomcat tomcatProperties = this.serverProperties.getTomcat();
		if (!ObjectUtils.isEmpty(tomcatProperties.getAdditionalTldSkipPatterns())) {
			factory.getTldSkipPatterns().addAll(tomcatProperties.getAdditionalTldSkipPatterns());
		}
		if (tomcatProperties.getRedirectContextRoot() != null) {
			customizeRedirectContextRoot(factory, tomcatProperties.getRedirectContextRoot());
		}
		customizeUseRelativeRedirects(factory, tomcatProperties.isUseRelativeRedirects());
		factory.setDisableMBeanRegistry(!tomcatProperties.getMbeanregistry().isEnabled());
	}

怎么让所有的WebServerFactoryCustomizer Bean一一调用的

        BeanPostProcessorsRegistrar实现了ImportBeanDefinitionRegistrar 会提供一个方法,并且提供BeanDefinitionRegistar 让我们去注册bean

public static class BeanPostProcessorsRegistrar implements ImportBeanDefinitionRegistrar, BeanFactoryAware {

		private ConfigurableListableBeanFactory beanFactory;

		@Override
		public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
			if (beanFactory instanceof ConfigurableListableBeanFactory) {
				this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
			}
		}

		@Override
		public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
				BeanDefinitionRegistry registry) {
			if (this.beanFactory == null) {
				return;
			}
			registerSyntheticBeanIfMissing(registry, "webServerFactoryCustomizerBeanPostProcessor",
					WebServerFactoryCustomizerBeanPostProcessor.class);
			registerSyntheticBeanIfMissing(registry, "errorPageRegistrarBeanPostProcessor",
					ErrorPageRegistrarBeanPostProcessor.class);
		}

		private void registerSyntheticBeanIfMissing(BeanDefinitionRegistry registry, String name, Class<?> beanClass) {
			if (ObjectUtils.isEmpty(this.beanFactory.getBeanNamesForType(beanClass, true, false))) {
				RootBeanDefinition beanDefinition = new RootBeanDefinition(beanClass);
				beanDefinition.setSynthetic(true);
				registry.registerBeanDefinition(name, beanDefinition);
			}
		}

	}

注册了:WebServerFactoryCustomizerBeanPostProcessor

 实现了BeanPostProcessor接口,并实现了两个方法在bean初始化前后调用

//初始化前
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 判断当前创建的bean是不是WebServerFactory
        if (bean instanceof WebServerFactory) {
            this.postProcessBeforeInitialization((WebServerFactory)bean);
        }

        return bean;
    }
//初始化后
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
        ((Callbacks)LambdaSafe.callbacks(WebServerFactoryCustomizer.class, this.getCustomizers(), webServerFactory, new Object[0]).withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)).invoke((customizer) -> {
            customizer.customize(webServerFactory);
        });
    }

当对应Embeddedxxxx 启用时, 就会在里面配置一个WebServerFactory 类型的一个Bean, 负责创建对应的容器和启动

 TomcatServletWebServerFactory 是WebServerFactory类型的一个Bean

https://note.youdao.com/yws/public/resource/a1475b8cffccdffcd309dd2a11832a35/xmlnote/A94ACAD9490445C8A838A57715B14515/A5A651689EAE4D7C920FB524C939592F/11583

 我们具体看一下初始化之后调用的方法

private void postProcessBeforeInitialization(WebServerFactory webServerFactory) {
    // 调用getCustomizers()
   LambdaSafe.callbacks(WebServerFactoryCustomizer.class, getCustomizers(), webServerFactory)
         .withLogger(WebServerFactoryCustomizerBeanPostProcessor.class)
         
         .invoke((customizer) -> customizer.customize(webServerFactory));
}
  • 1.调用getCustomizers()
private Collection<WebServerFactoryCustomizer<?>> getCustomizers() {
        if (this.customizers == null) {
            this.customizers = new ArrayList(this.getWebServerFactoryCustomizerBeans());
            this.customizers.sort(AnnotationAwareOrderComparator.INSTANCE);
            this.customizers = Collections.unmodifiableList(this.customizers);
        }

        return this.customizers;
    }
  • 2.getWebServerFactoryCustomizerBeans() 就获取了所有实现了WebServerFactoryCustomizer接口的Bean
    • 获取 自定义的,和ServletWebServerFactoryCustomizer、TomcatServletWebServerFactoryCustomizer


    private Collection<WebServerFactoryCustomizer<?>> getWebServerFactoryCustomizerBeans() {
        //从spring容器中拿到类型为WebServerFactoryCustomizer的bean
        //包括自动配置类中的,也包括我们自己定制化的
        return this.beanFactory.getBeansOfType(WebServerFactoryCustomizer.class, false, false).values();
    }
  • 3.在invoke方法中循环调用所有实现了WebServerFactoryCustomizer接口的Bean的customize方法进行一一定制

3.嵌入式servlet容器是怎么启动的

TomcatServletWebServerFactory

  • 自动配置中根据不同的依赖, 启动对应一个Embeddedxxxx, 然后配置一个对应的servlet容器工厂类, 比如tomcat:TomcatServletWebServerFactory
  • 在springboot应用启动的时候 , 就会调用容器refresh方法, onRefresh , 调用getWebServer, 创建servlet及启动(spring源码)
    public WebServer getWebServer(ServletContextInitializer... initializers) {
        if (this.disableMBeanRegistry) {
            Registry.disableRegistry();
        }

        Tomcat tomcat = new Tomcat();
        File baseDir = this.baseDirectory != null ? this.baseDirectory : this.createTempDir("tomcat");
        tomcat.setBaseDir(baseDir.getAbsolutePath());
        Connector connector = new Connector(this.protocol);
        connector.setThrowOnFailure(true);
        tomcat.getService().addConnector(connector);
        this.customizeConnector(connector);
        tomcat.setConnector(connector);
        tomcat.getHost().setAutoDeploy(false);
        this.configureEngine(tomcat.getEngine());
        Iterator var5 = this.additionalTomcatConnectors.iterator();

        while(var5.hasNext()) {
            Connector additionalConnector = (Connector)var5.next();
            tomcat.getService().addConnector(additionalConnector);
        }

        this.prepareContext(tomcat.getHost(), initializers);
        return this.getTomcatWebServer(tomcat);
    }

 getTomcatWebServer方法

    protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
        return new TomcatWebServer(tomcat, this.getPort() >= 0, this.getShutdown());
    }

TomcatWebServer构造方法会调用this.initialize(),initialize方法中调用this.tomcat.start();启动tomcat

    public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) {
        this.monitor = new Object();
        this.serviceConnectors = new HashMap();
        Assert.notNull(tomcat, "Tomcat Server must not be null");
        this.tomcat = tomcat;
        this.autoStart = autoStart;
        this.gracefulShutdown = shutdown == Shutdown.GRACEFUL ? new GracefulShutdown(tomcat) : null;
        this.initialize();
    }

    private void initialize() throws WebServerException {
        logger.info("Tomcat initialized with port(s): " + this.getPortsDescription(false));
        synchronized(this.monitor) {
            try {
                this.addInstanceIdToEngineName();
                Context context = this.findContext();
                context.addLifecycleListener((event) -> {
                    if (context.equals(event.getSource()) && "start".equals(event.getType())) {
                        this.removeServiceConnectors();
                    }

                });
                this.tomcat.start();
                this.rethrowDeferredStartupExceptions();

                try {
                    ContextBindings.bindClassLoader(context, context.getNamingToken(), this.getClass().getClassLoader());
                } catch (NamingException var5) {
                }

                this.startDaemonAwaitThread();
            } catch (Exception var6) {
                this.stopSilently();
                this.destroySilently();
                throw new WebServerException("Unable to start embedded Tomcat", var6);
            }

        }
    }

5.使用外部Servlet容器

  • 外部servlet容器
    • 服务器、本机 安装tomcat 环境变量...
    • 部署: war---运维--->tomcat webapp startup.sh 启动
    • 开发: 将开发绑定本地tomcat
    • 开发 、 运维 服务器配置 war
  • 内嵌servlet容器:
    • 部署: jar---> 运维---java -jar 启动

使用:

1. 下载tomcat服务

2.设置当前maven项目的打包方式

<!--打包方式  默认是jar-->
<packaging>war</packaging>

3.让tomcat相关的依赖不参与打包部署 ,因为外置tomcat服务器已经有这些jar包

<!--让它不参与打包部署-->
<dependency>
    <artifactId>spring-boot-starter-tomcat</artifactId>
    <groupId>org.springframework.boot</groupId>
    <scope>provided</scope>
</dependency>

4. 为了让它支持springboot需要加上: 才能启动springboot应用

// 当tomcat启动时就会调用configure方法, 从而在springboot启动类的基础启动springboot
// 什么时候调用?
public class TomcatStartSpringBoot extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(Application.class);
    }
}

 5. 在idea中运行

https://note.youdao.com/yws/public/resource/a1475b8cffccdffcd309dd2a11832a35/xmlnote/A94ACAD9490445C8A838A57715B14515/F6A6311F70D7458D89B43A23C7190E57/11642

https://note.youdao.com/yws/public/resource/a1475b8cffccdffcd309dd2a11832a35/xmlnote/A94ACAD9490445C8A838A57715B14515/043710911BB245FCB639494C215F9075/11644

6.外部Servlet容器启动SpringBoot应用原理

tomcat---> web.xml--filter servlet listener 3.0+

tomcat不会主动去启动springboot应用 ,, 所以tomcat启动的时候肯定调用了SpringBootServletInitializer的SpringApplicationBuilder , 就会启动springboot

public class TomcatStartSpringBoot extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder (SpringApplicationBuilder builder) {
        return builder.sources(Application.class);
    }
}

servlet3.0 规范官方文档: 8.2.4

https://note.youdao.com/yws/public/resource/a1475b8cffccdffcd309dd2a11832a35/xmlnote/A94ACAD9490445C8A838A57715B14515/11E12E3047ED472899122032855DB429/11696

大概: 当servlet容器启动时候 就会去META-INF/services 文件夹中找到javax.servlet.ServletContainerInitializer, 这个文件里面肯定绑定一个ServletContainerInitializer. 当servlet容器启动时候就会去该文件中找到ServletContainerInitializer的实现类,从而创建它的实例调用onstartUp (SPI规范,数据库驱动也用到了)

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
  • @HandlesTypes(WebApplicationInitializer.class).
    • @HandlesTypes传入的类为ServletContainerInitializer感兴趣的
    • 容器会自动在classpath中找到 WebApplicationInitializer 会传入到onStartup方法的webAppInitializerClasses参数中
    • Set> webAppInitializerClasses 这里面也包括之前自己定义的TomcatStartSpringBoot

 SpringServletContainerInitializer 的onStartup方法

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

		List<WebApplicationInitializer> initializers = Collections.emptyList();

		if (webAppInitializerClasses != null) {
			initializers = new ArrayList<>(webAppInitializerClasses.size());
			for (Class<?> waiClass : webAppInitializerClasses) {
				 // 如果不是接口 不是抽象 跟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);
		for (WebApplicationInitializer initializer : initializers) {
			initializer.onStartup(servletContext);
		}
	}

https://note.youdao.com/yws/public/resource/a1475b8cffccdffcd309dd2a11832a35/xmlnote/A94ACAD9490445C8A838A57715B14515/FD19118A9D9941C392567DA840315B10/11731

 SpringBootServletInitializer的onstartup方法

    public void onStartup(ServletContext servletContext) throws ServletException {
        this.logger = LogFactory.getLog(this.getClass());
        WebApplicationContext rootApplicationContext = this.createRootApplicationContext(servletContext);
        if (rootApplicationContext != null) {
            servletContext.addListener(new SpringBootServletInitializer.SpringBootContextLoaderListener(rootApplicationContext, servletContext));
        } else {
            this.logger.debug("No ContextLoaderListener registered, as createRootApplicationContext() did not return an application context");
        }

    }

 首先调用createRootApplicationContext方法

    protected WebApplicationContext createRootApplicationContext(ServletContext servletContext) {
        SpringApplicationBuilder builder = this.createSpringApplicationBuilder();
        builder.main(this.getClass());
        ApplicationContext parent = this.getExistingRootWebApplicationContext(servletContext);
        if (parent != null) {
            this.logger.info("Root context already created (using as parent).");
            servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, (Object)null);
            builder.initializers(new ApplicationContextInitializer[]{new ParentContextApplicationContextInitializer(parent)});
        }

        builder.initializers(new ApplicationContextInitializer[]{new ServletContextApplicationContextInitializer(servletContext)});
        builder.contextClass(AnnotationConfigServletWebServerApplicationContext.class);
        builder = this.configure(builder);
        builder.listeners(new ApplicationListener[]{new SpringBootServletInitializer.WebEnvironmentPropertySourceInitializer(servletContext)});
        SpringApplication application = builder.build();
        if (application.getAllSources().isEmpty() && MergedAnnotations.from(this.getClass(), SearchStrategy.TYPE_HIERARCHY).isPresent(Configuration.class)) {
            application.addPrimarySources(Collections.singleton(this.getClass()));
        }

        Assert.state(!application.getAllSources().isEmpty(), "No SpringApplication sources have been defined. Either override the configure method or add an @Configuration annotation");
        if (this.registerErrorPageFilter) {
            application.addPrimarySources(Collections.singleton(ErrorPageFilterConfiguration.class));
        }

        application.setRegisterShutdownHook(false);
        return this.run(application);
    }

 在createRootApplicationContext方法中builder = this.configure(builder);

而我们自己定义的TomcatStartSpringBoot重写了configure方法,就会来到我们自己定义的继承的SpringBootServletInitializer的configure方法,将Springboot启动类传入到builder.source

public class TomcatStartSpringBoot extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
        return builder.sources(Application.class);
    }
}

// 调用SpringApplication application = builder.build(); 就会根据传入的Springboot启动类来构建一个SpringApplication

    public SpringApplication build(String... args) {
        this.configureAsChildIfNecessary(args);
        this.application.addPrimarySources(this.sources);
        return this.application;
    }

// 调用 return run(application); 就会帮我启动springboot应用

    protected WebApplicationContext run(SpringApplication application) {
        return (WebApplicationContext)application.run(new String[0]);
    }

它就相当于我们的

public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

https://note.youdao.com/yws/public/resource/a1475b8cffccdffcd309dd2a11832a35/xmlnote/A94ACAD9490445C8A838A57715B14515/0FFC526EF4C2494FA8B40EE6E065D960/11751

其实这2个实现类就是帮我创建ContextLoaderListener 和DispatcherServlet 

listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--全局参数:spring配置文件-->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring-core.xml</param-value>
</context-param>


<!--前端调度器servlet-->
<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--设置配置文件的路径-->
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring-mvc.xml</param-value>
    </init-param>
    <!--设置启动即加载-->
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

https://note.youdao.com/yws/public/resource/a1475b8cffccdffcd309dd2a11832a35/xmlnote/A94ACAD9490445C8A838A57715B14515/07D5D92C840B45E9873186BE55EBB0D1/11755

5.SpringBoot作为单体Web应用的使用

如果需要动态展示Springmvc的数据到页面上需要使用模板引擎技术:

SpringBoot提供以下模板引擎技术的支持:

以Freemarker为例

        1.添加freemarker的依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        2.设置freemakrer的全局配置

#如果在生产环境可以设置true
spring.freemarker.cache=false

spring.freemarker.charset=UTF-8

spring.freemarker.suffix=.html

        3.添加freemarker的页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<#list usernames as username>
<h1>${username}</h1>
</#list>
</body>
</html>

        4.对应的控制器

@Controller
@RequestMapping("user")
public class UserController {

    @RequestMapping("index")
    public  String index(Model model){
        model.addAttribute("username","fztx");
        return "index";
    }

    @RequestMapping("list")
    public  String list(Model model){
        List<String> list= Arrays.asList("fztx","zhangsan","lisi");
        model.addAttribute("usernames",list);
        return "list";
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值