直接映射到静态页面

当访问某个地址的时候,都会优先检查是否有静态页面,如果没有,才去controller里面查找。

例如,访问 localhost:8080/test.html 时,它就会先查找如下4个位置

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

注意:不在这4个位置,即使在 resources 目录下,默认也是无法直接访问的

spring boot重定向设置cookie springboot 重定向至静态页面_静态资源

因此,当不配置任何 controller 时,5-6.html 是访问不了的,但1-4.html 却可以正常访问。

Spring指定路径映射到静态页面

如果想改变静态页面的访问路径,可以将静态资源通过流直接返回给前端。

例如,规定路径中包含有 /test/ 的地址,即访问资源目录下的 test 文件夹下的路径,如果没有文件名,设置默认访问 index.html。创建一个 StaticResourceController.java

@Controller
public class StaticResourceController {
	private static final String PATH_TEST = "test/";

	@RequestMapping(PATH_TEST + "**")
	public void getHtml(HttpServletRequest request, HttpServletResponse response) {
		String uri = request.getRequestURI();
		String[] arr = uri.split(PATH_TEST);
		String resourceName = "index.html";
		if (arr.length > 1) {
			resourceName = arr[1];
		}
//		String path1 = StaticResourceController.class.getResource(null).getPath();
		String path2 = StaticResourceController.class.getResource("").getPath();
		String path3 = StaticResourceController.class.getResource(".").getPath();
		String path4 = StaticResourceController.class.getResource("/").getPath();
//		System.out.println("path1 = " + path1);
		System.out.println("path2 = " + path2);
		System.out.println("path3 = " + path3);
		System.out.println("path4 = " + path4);
		
		String url = StaticResourceController.class.getResource("/").getPath() + PATH_TEST + resourceName;
		FileReader reader = null;
		BufferedReader br = null;
		try {
			File file = new File(url);
			if (file.exists()) {
				reader = new FileReader(file);
				br = new BufferedReader(reader);
				StringBuilder sb = new StringBuilder();
				for (String line = br.readLine(); line != null; line = br.readLine()) {
					sb.append(line);
				}
				response.getOutputStream().write(sb.toString().getBytes());
				response.flushBuffer();
			} else {
				//如果返回错误信息为中文,则一定药设置编码,否则显示问号
				response.setCharacterEncoding("utf8");
				response.sendError(404, "页面未找到");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if(br != null) br.close();
				if(reader != null) reader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}

对于 getResource() 方法

  • 参数不能为空,会报空指针异常
  • 参数为空串,等价于点号,指的是当前类的路径
  • 参数为斜杠(/),指的是根目录

可以看到,编译之后会把 resources 目录下的文件和 类的根路径放置在同级的位置

spring boot重定向设置cookie springboot 重定向至静态页面_静态页面_02

至于 resources 目录的文件名,可以通过 pom.xml 中的设置进行改变

<resources>
    <resource>
        <directory>src/main/resources</directory>
    </resource>
</resources>

Spring Boot 指定路径映射到静态页面

无论是通过代码,还是通过配置文件,设置之后,都会覆盖默认的那 4个路径(classpath:/META-INF/resources/,classpath:/public/,classpath:/resources/,classpath:/ static/),导致无法访问

通过代码

WebMvcConfigurerAdapter 已经被废弃了,查看源码可知,由于Java8 的新特性,可以在接口前面加一个 default 关键词,来为接口创建一个默认的实现,这样实现该接口的类就不用实现全部接口了。

因此,这里直接实现 WebMvcConfigurer 即可

/**
 * An implementation of {@link WebMvcConfigurer} with empty methods allowing
 * subclasses to override only the methods they're interested in.
 *
 * @author Rossen Stoyanchev
 * @since 3.1
 * @deprecated as of 5.0 {@link WebMvcConfigurer} has default methods (made
 * possible by a Java 8 baseline) and can be implemented directly without the
 * need for this adapter
 */
@Deprecated
public abstract class WebMvcConfigurerAdapter implements WebMvcConfigurer { …… }

Spring Boot 通过注解@Configuration 来实现 IOC(控制反转)和 DI(依赖注入),将管理权交给 Spring 容器。

@Configuration
public class ResourceConf implements WebMvcConfigurer {
	
	/**
	* 静态资源处理器
	*/
	@Override
	public void addResourceHandlers(ResourceHandlerRegistry registry) {
		//路径前缀,可填写多个值
		registry.addResourceHandler("test/**")
		//映射到的资源路径(路径后的斜杠不能省略,否则无法访问)
				.addResourceLocations("classpath:/test/", "classpath:/templates/");
		}
	
//	/** 解决跨域问题 **/
//	public void addCorsMappings(CorsRegistry registry) {}
//	/** 添加拦截器 **/
//	public void addInterceptors(InterceptorRegistry registry) {}
//	/** 这里配置视图解析器 **/
//	public void configureViewResolvers(ViewResolverRegistry registry) {}
//	/** 配置内容裁决的一些选项 **/
//	public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {}
//	/** 视图跳转控制器 **/
//	public void addViewControllers(ViewControllerRegistry registry) {}
//	/** 静态资源处理 **/
//	public void addResourceHandlers(ResourceHandlerRegistry registry) {}
//	/** 默认静态资源处理器 **/
//	public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {}
}

通过配置文件

properties 和 yml,仅需要设置一个即可。这里只是做个示范

如果两个都设置,则仅 properties 生效。

application.properties

spring.mvc.static-path-pattern = /test/**
spring.resources.static-locations = classpath:/test/, classpath:/templates/

application.yml

spring:
  mvc:
    static-path-pattern: /test/**
  resources:
    static-locations: classpath:/test2/, classpath:/templates/

static-path-pattern:表示访问模式,默认为 /** ,如果有多个可以通过逗号分隔
static-locations:静态资源目录,如果有多个可以通过逗号分隔,默认的静态路径为 classpath:/META-INF/resources/, classpath:/resources/, classpath:/static/, classpath:/public/

当多个静态资源目录下,有名字相同的文件时,会按照设置的顺序进行排查,返回第一个找到的。