SpringBoot学习(九) ------访问静态web资源

SpringBoot可以通过3种方式来获取静态资源

方式一:访问所有webjars/**,访问静态资源的路径为META-INF/resources/webjars,可以在此路径中查找静态资源。

举个例子:

新建一个项目工程

并在pom.xml文件中引入webjars包,

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.zk.myspringboot_011</groupId>
	<artifactId>myspringboot_011</artifactId>
	<packaging>jar</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>myspringboot_011 Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-configuration-processor</artifactId>
			<optional>true</optional>
		</dependency>
		<!-- 继承父包 -->
		<dependency>
			<groupId>org.webjars</groupId>
			<artifactId>jquery</artifactId>
			<version>3.3.1-1</version>
		</dependency>
	</dependencies>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.4.3.RELEASE</version>
	</parent>
	<build>
		<finalName>myspringboot_011</finalName>
	</build>
</project>

 核心代码:

<dependency>
	<groupId>org.webjars</groupId>
	<artifactId>jquery</artifactId>
	<version>3.3.1-1</version>
</dependency>

可以参考一下这个引入静态资源的网站https://www.webjars.org/

 然后我们通过浏览器访问一下web静态资源,路径为http://localhost:8080/webjars/jquery/3.3.1-1/jquery.js

为什么可以访问webjars目录下的所有静态资源,我们可以通过查看org.springframework.boot.autoconfigure.web包下面的WebMvcAutoConfiguration.class类的源代码分析其原因:

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
		        if (!this.resourceProperties.isAddMappings()) {
				logger.debug("Default resource handling disabled");
				return;
			}
			Integer cachePeriod = this.resourceProperties.getCachePeriod();
			if (!registry.hasMappingForPattern("/webjars/**")) {
				customizeResourceHandlerRegistration(
						registry.addResourceHandler("/webjars/**")
								.addResourceLocations(
										"classpath:/META-INF/resources/webjars/")
						.setCachePeriod(cachePeriod));
			}
			String staticPathPattern = this.mvcProperties.getStaticPathPattern();
			if (!registry.hasMappingForPattern(staticPathPattern)) {
				customizeResourceHandlerRegistration(
						registry.addResourceHandler(staticPathPattern)
								.addResourceLocations(
										this.resourceProperties.getStaticLocations())
						.setCachePeriod(cachePeriod));
			}
}

这里直接给staticPathPattern赋值,然后将该值赋给了资源访问路径方法。所以能够通过/webjars/**对静态资源进行访问。

方式二:./**访问当前项目的任何资源

 可以通过以下四种路径放置web静态资源,并访问web静态资源

classpath:/META-INF/resources/* 
classpath:/resources/*
classpath:/static/*
classpath:/public/*

 这里四个路径的优先级顺序分别从上到下依次递减。

举个例子:

在项目resource文件夹下建一个static静态文件夹,在image目录下放a.png文件

我们访问这个路径:localhost:8080/image/a.png,可以访问到a.png静态资源

为什么可以访问以上四个路径下的所有静态资源,我们可以通过查看org.springframework.boot.autoconfigure.web包下面的ResourceProperties.class类的源代码分析其原因:

/*
 * Copyright 2012-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.boot.autoconfigure.web;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

/**
 * Properties used to configure resource handling.
 *
 * @author Phillip Webb
 * @author Brian Clozel
 * @author Dave Syer
 * @author Venil Noronha
 * @since 1.1.0
 */
@ConfigurationProperties(prefix = "spring.resources", ignoreUnknownFields = false)
public class ResourceProperties implements ResourceLoaderAware {

	private static final String[] SERVLET_RESOURCE_LOCATIONS = { "/" };

	private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
			"classpath:/META-INF/resources/", "classpath:/resources/",
			"classpath:/static/", "classpath:/public/" };

	private static final String[] RESOURCE_LOCATIONS;

	static {
		RESOURCE_LOCATIONS = new String[CLASSPATH_RESOURCE_LOCATIONS.length
				+ SERVLET_RESOURCE_LOCATIONS.length];
		System.arraycopy(SERVLET_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS, 0,
				SERVLET_RESOURCE_LOCATIONS.length);
		System.arraycopy(CLASSPATH_RESOURCE_LOCATIONS, 0, RESOURCE_LOCATIONS,
				SERVLET_RESOURCE_LOCATIONS.length, CLASSPATH_RESOURCE_LOCATIONS.length);
	}

	/**
	 * Locations of static resources. Defaults to classpath:[/META-INF/resources/,
	 * /resources/, /static/, /public/] plus context:/ (the root of the servlet context).
	 */
	private String[] staticLocations = RESOURCE_LOCATIONS;

	/**
	 * Cache period for the resources served by the resource handler, in seconds.
	 */
	private Integer cachePeriod;

	/**
	 * Enable default resource handling.
	 */
	private boolean addMappings = true;

	private final Chain chain = new Chain();

	private ResourceLoader resourceLoader;

	@Override
	public void setResourceLoader(ResourceLoader resourceLoader) {
		this.resourceLoader = resourceLoader;
	}

	public String[] getStaticLocations() {
		return this.staticLocations;
	}

	public void setStaticLocations(String[] staticLocations) {
		this.staticLocations = staticLocations;
	}

	public Resource getWelcomePage() {
		for (String location : getStaticWelcomePageLocations()) {
			Resource resource = this.resourceLoader.getResource(location);
			try {
				if (resource.exists()) {
					resource.getURL();
					return resource;
				}
			}
			catch (Exception ex) {
				// Ignore
			}
		}
		return null;
	}

	private String[] getStaticWelcomePageLocations() {
		String[] result = new String[this.staticLocations.length];
		for (int i = 0; i < result.length; i++) {
			String location = this.staticLocations[i];
			if (!location.endsWith("/")) {
				location = location + "/";
			}
			result[i] = location + "index.html";
		}
		return result;
	}

	List<Resource> getFaviconLocations() {
		List<Resource> locations = new ArrayList<Resource>(
				this.staticLocations.length + 1);
		if (this.resourceLoader != null) {
			for (String location : this.staticLocations) {
				locations.add(this.resourceLoader.getResource(location));
			}
		}
		locations.add(new ClassPathResource("/"));
		return Collections.unmodifiableList(locations);
	}

	public Integer getCachePeriod() {
		return this.cachePeriod;
	}

	public void setCachePeriod(Integer cachePeriod) {
		this.cachePeriod = cachePeriod;
	}

	public boolean isAddMappings() {
		return this.addMappings;
	}

	public void setAddMappings(boolean addMappings) {
		this.addMappings = addMappings;
	}

	public Chain getChain() {
		return this.chain;
	}

	/**
	 * Configuration for the Spring Resource Handling chain.
	 */
	public static class Chain {

		/**
		 * Enable the Spring Resource Handling chain. Disabled by default unless at least
		 * one strategy has been enabled.
		 */
		private Boolean enabled;

		/**
		 * Enable caching in the Resource chain.
		 */
		private boolean cache = true;

		/**
		 * Enable HTML5 application cache manifest rewriting.
		 */
		private boolean htmlApplicationCache = false;

		/**
		 * Enable resolution of already gzipped resources. Checks for a resource name
		 * variant with the "*.gz" extension.
		 */
		private boolean gzipped = false;

		@NestedConfigurationProperty
		private final Strategy strategy = new Strategy();

		/**
		 * Return whether the resource chain is enabled. Return {@code null} if no
		 * specific settings are present.
		 * @return whether the resource chain is enabled or {@code null} if no specified
		 * settings are present.
		 */
		public Boolean getEnabled() {
			Boolean strategyEnabled = getStrategy().getFixed().isEnabled()
					|| getStrategy().getContent().isEnabled();
			return (strategyEnabled ? Boolean.TRUE : this.enabled);
		}

		public void setEnabled(boolean enabled) {
			this.enabled = enabled;
		}

		public boolean isCache() {
			return this.cache;
		}

		public void setCache(boolean cache) {
			this.cache = cache;
		}

		public Strategy getStrategy() {
			return this.strategy;
		}

		public boolean isHtmlApplicationCache() {
			return this.htmlApplicationCache;
		}

		public void setHtmlApplicationCache(boolean htmlApplicationCache) {
			this.htmlApplicationCache = htmlApplicationCache;
		}

		public boolean isGzipped() {
			return this.gzipped;
		}

		public void setGzipped(boolean gzipped) {
			this.gzipped = gzipped;
		}

	}

	/**
	 * Strategies for extracting and embedding a resource version in its URL path.
	 */
	public static class Strategy {

		@NestedConfigurationProperty
		private final Fixed fixed = new Fixed();

		@NestedConfigurationProperty
		private final Content content = new Content();

		public Fixed getFixed() {
			return this.fixed;
		}

		public Content getContent() {
			return this.content;
		}

	}

	/**
	 * Version Strategy based on content hashing.
	 */
	public static class Content {

		/**
		 * Enable the content Version Strategy.
		 */
		private boolean enabled;

		/**
		 * Comma-separated list of patterns to apply to the Version Strategy.
		 */
		private String[] paths = new String[] { "/**" };

		public boolean isEnabled() {
			return this.enabled;
		}

		public void setEnabled(boolean enabled) {
			this.enabled = enabled;
		}

		public String[] getPaths() {
			return this.paths;
		}

		public void setPaths(String[] paths) {
			this.paths = paths;
		}

	}

	/**
	 * Version Strategy based on a fixed version string.
	 */
	public static class Fixed {

		/**
		 * Enable the fixed Version Strategy.
		 */
		private boolean enabled;

		/**
		 * Comma-separated list of patterns to apply to the Version Strategy.
		 */
		private String[] paths = new String[] { "/**" };

		/**
		 * Version string to use for the Version Strategy.
		 */
		private String version;

		public boolean isEnabled() {
			return this.enabled;
		}

		public void setEnabled(boolean enabled) {
			this.enabled = enabled;
		}

		public String[] getPaths() {
			return this.paths;
		}

		public void setPaths(String[] paths) {
			this.paths = paths;
		}

		public String getVersion() {
			return this.version;
		}

		public void setVersion(String version) {
			this.version = version;
		}

	}

}

  核心代码:

private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
			"classpath:/META-INF/resources/", "classpath:/resources/",
			"classpath:/static/", "classpath:/public/" };

 这里定义了我们的四个访问路径,因此,静态资源可以通过这四个访问路径进行访问。

方式三:可以自定义静态资源进行访问

 新建一个MyWebMvcConfig.java,重写WebMvcConfigurer接口,这里我只重写了addResourceHandlers方法,定义了一个test文件夹。

package com.zk.Springboot;
import java.util.List;

import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.stereotype.Component;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
/**
 * 静态资源映射
 */
@Component
public class MyWebMvcConfig implements WebMvcConfigurer {
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/test/**")
                .addResourceLocations("classpath:/test/");
        }

	@Override
	public void addArgumentResolvers(List<HandlerMethodArgumentResolver> arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void addCorsMappings(CorsRegistry arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void addFormatters(FormatterRegistry arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void addInterceptors(InterceptorRegistry arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void addViewControllers(ViewControllerRegistry arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configureAsyncSupport(AsyncSupportConfigurer arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configureContentNegotiation(ContentNegotiationConfigurer arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configureDefaultServletHandling(DefaultServletHandlerConfigurer arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configureMessageConverters(List<HttpMessageConverter<?>> arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configurePathMatch(PathMatchConfigurer arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void configureViewResolvers(ViewResolverRegistry arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void extendMessageConverters(List<HttpMessageConverter<?>> arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public MessageCodesResolver getMessageCodesResolver() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Validator getValidator() {
		// TODO Auto-generated method stub
		return null;
	}
}

  访问刚才自定义路径http://localhost:8080/test/a.png

 同样能够访问我们的静态资源文件。

 方式四:可以在application.properties设置进行访问

spring.resources.static-locations=classpath:/static,classpath:/public,classpath:/resources,classpath:/META-INF/resources

  

 访问localhost:8080/static/index.html

SpringBoot中引入thymeleaf

首先我们介绍一下什么是thymeleaf

thymeleaf是个XML/XHTML/HTML5模板引擎,可以用于Web与非Web应用。

我们现在需要使用thymeleaf,将thymeleaf引入springboot中。

在pom.xml文件中添加如下代码:

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

加入thymeleaf依赖,引入jar包。

 thymeleaf的默认静态资源路径为classpath:/templates/,必须放置在此路径下,才能够访问到静态thymeleaf资源,否则无法访问。

 分析其原因可以查看源代码,访问spring-boot-autoconfigure-1.4.3.RELEASE.jar 包下的org.springframework.boot.autoconfigure.thymeleaf中的ThymeleafProperties.class文件

@ConfigurationProperties("spring.thymeleaf")
public class ThymeleafProperties {

	private static final Charset DEFAULT_ENCODING = Charset.forName("UTF-8");

	private static final MimeType DEFAULT_CONTENT_TYPE = MimeType.valueOf("text/html");

	public static final String DEFAULT_PREFIX = "classpath:/templates/";

	public static final String DEFAULT_SUFFIX = ".html";

 从该class文件中可以分析到,访问静态资源的路径必须为classpath:/templates/,且静态资源为.html

我们举个例子,

我们建个springboot项目,项目目录如下:

首先在classpath:/templates/构建success.html文件,文件内容如下:

success.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head>
    <meta charset="utf-8" />
    <title>success.html</title>
    <!--<link rel="stylesheet" type="text/css" href="./styles.css">-->
  </head>
  
  <body>
    success,helloworld <br/>
    <!-- 将div中的文本内容设置成自定义值 -->
    <h1 th:text="${hello}" th:id="${hello}" th:class="${hello}"></h1>
    <h1 th:utext="${hello}"></h1>
    <!-- 遍历user -->
    <div th:each="user:${users}">
    <span th:text="${user}"></span>
    </div>
    <table border="1">
        <thead>
            <th>学生id</th>
            <th>学生姓名</th>
            <th>学生年龄</th>
        </thead>
        <tbody>
            <tr th:each="entries:${resultList}">
                <td th:text="${entries['sid']}"></td>
                <td th:text="${entries['sname']}"></td>
                <td th:text="${entries['sage']}"></td>
            </tr>
        </tbody>
    </table>
  </body>
</html>

 如果想使用thymeleaf,则需要引入标签:

<html xmlns:th="http://www.thymeleaf.org">

 在success.html文件中访问了user参数列表和resultList,在HelloController后台封装代码如下:

package com.zk.Springboot;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloController {
	@ResponseBody
	@RequestMapping("/hello")
	public String hello() { 
		return "hello";
	}
	//插入一些数据在页面显示
	@RequestMapping("/success")
	public String successs(Map<String,Object> map) {
		map.put("hello", "你好");
		map.put("users", Arrays.asList("zhang","zhao","qian"));
		return "success";
	}
	
	@Controller
	@RequestMapping("studentMgmt")
	public class StudentController {
	    @RequestMapping("queryStudentInfo")
	    public String queryStudentInfo(Model model) {
	        List<Map<String, Object>> resultList = new ArrayList<Map<String, Object>>();
	        Map<String, Object> student = new HashMap<String, Object>(){{
	            put("sid", "101");
	            put("sname", "张三");
	            put("sage", "20");
	        }};
	        resultList.add(student);
	        student = new HashMap<String, Object>(){{
	            put("sid", "102");
	            put("sname", "李四");
	            put("sage", "30");
	        }};
	        resultList.add(student);
	        model.addAttribute("resultList", resultList);
	        return "success";
	    }
	}
}

 同样设置启动项:

package com.zk.Springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringBootApplicationFirst {
	public static void main(String[]args){
        SpringApplication.run(SpringBootApplicationFirst.class, args);
    }
    public static void run(String...arg0) {
        System.out.println("Hello world from Command Line Runner");
    }
}

 application.properties配置文件内容:

spring.resources.static-locations=classpath:/static,classpath:/public,classpath:/resources,classpath:/META-INF/resources

  我们访问一下thymeleaf静态资源网页,访问效果如下:

 访问成功

 SpringBoot中引入freemark

首先在pom.xml文件中引入freemarker的依赖

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>myspringboot003</groupId>
  <artifactId>myspringboot003</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <parent>
  	<groupId>org.springframework.boot</groupId>
  	<artifactId>spring-boot-starter-parent</artifactId>
  	<version>1.3.3.RELEASE</version>
  </parent>
  <dependencies>
  	<dependency>
  		<groupId>org.springframework.boot</groupId>
  		<artifactId>spring-boot-starter-web</artifactId>
  	</dependency>
  	<dependency>
  		<groupId>org.springframework.boot</groupId>
  		<artifactId>spring-boot-starter-freemarker</artifactId>
  	</dependency>
  </dependencies>
</project>

 接着,写ftl页面文件

this is itmayiedu<br>
${name}
<#list userlist as user>
${user}
</#list>

 写业务controller文件

package com.zk.myspringboot003;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

//标识该接口全部返回json格式
@Controller
public class indexController {
	@RequestMapping("/indexController")
	public String indexController(Map<String,Object> result) {
		result.put("name", "zk");
		List<String> list=new ArrayList<String>();
		list.add("zhangkun");
		list.add("lisi");
		list.add("26");
		result.put("userlist", list);
		return "index";
	}
}

 最后写启动文件

package com.zk.myspringboot003;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@EnableAutoConfiguration
@SpringBootApplication
public class SpringBootApplicationThird {
	public static void main(String[]args){
        SpringApplication.run(SpringBootApplicationThird.class, args);
    }
    public static void run(String...arg0) {
        System.out.println("Hello world from Command Line Runner");
    }
}

  运行结果如下:

 SpringBoot中引入JSP

需要注意的是,在创建MAVEN工程项目的时候需要选择war,而不是我们平时选择的jar包

页面:index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
springboot 你好
</body>
</html>

  Controller类:IndexController.java

package com.zk.myspringboot004;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class IndexController {
	
	@RequestMapping("/index")
	public String index() {
		return "index";
	}
}

 application属性文件:application.properties

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

 依赖文件:pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.myspringboot004</groupId>
  <artifactId>myspringboot004</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>war</packaging>
  
  <parent>
  	<groupId>org.springframework.boot</groupId>
  	<artifactId>spring-boot-starter-parent</artifactId>
  	<version>1.3.3.RELEASE</version>
  </parent>
  <dependencies>
  	<dependency>
  		<groupId>org.springframework.boot</groupId>
  		<artifactId>spring-boot-starter-web</artifactId>
  	</dependency>
  	<dependency>
  		<groupId>org.springframework.boot</groupId>
  		<artifactId>spring-boot-starter-tomcat</artifactId>
  	</dependency>
  	<dependency>
  		<groupId>org.apache.tomcat.embed</groupId>
  		<artifactId>tomcat-embed-jasper</artifactId>
  	</dependency>
  </dependencies>
</project>

  启动程序:SpringBootApplicationTwice.java

package com.zk.myspringboot004;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@EnableAutoConfiguration
@SpringBootApplication
public class SpringBootApplicationTwice {
	public static void main(String[]args){
        SpringApplication.run(SpringBootApplicationTwice.class, args);
    }
    public static void run(String...arg0) {
        System.out.println("Hello world from Command Line Runner");
    }
}

  

原文地址:https://www.cnblogs.com/longlyseul/p/12698183.html