開頭是雞蛋,后面全靠編!!!
========================================================
1.默認靜態資源映射路徑以及優先順序
Spring Boot 默認為我們提供了靜態資源處理,使用 WebMvcAutoConfiguration 中的配置各種屬性。
建議大家使用Spring Boot的默認配置方式,提供的靜態資源映射如下:
-
classpath:/META-INF/resources
-
classpath:/resources
-
classpath:/static
-
classpath:/public
制作【四個同名】的圖片,分別在圖片上標注對應要放在的【靜態資源文件夾】下
一定要重啟,讓項目重新加載目錄。然后再進行訪問
訪問地址:http://localhost:8080/123.png
然后把這個目錄下的圖片刪除,依次驗證,完成后得出結論:
上面這幾個都是靜態資源的映射路徑,優先級順序為:META-INF/resources > resources > static > public
除此之外,這幾個映射路徑下可以放置任何的靜態資源都可以被瀏覽器訪問到。
查看完整的配置文件:http://www.cnblogs.com/sxdcgaq8080/p/7724506.html
可以看到
spring.mvc.static-path-pattern=/** 靜態資源的映射路徑模式就是localhost:8080/下面,那比如訪問靜態資源路徑下的圖片就是localhost:8080/123.png
如果更改為
spring.mvc.static-path-pattern=/sxd/** 那訪問的時候就需要訪問localhost:8080/sxd/123.png
spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/
規定 靜態資源映射路徑就是根目錄下的這幾個,如果想要配置更多,請再以,逗號分隔跟在后面寫就好了
2.繼承WebMvcConfigurerAdapter類,在保留spring boot的配置情況下,添加自定義的額外配置
實現自定義的額外配置的前提,是自定義一個配置類,並使用注解@Configuration
package com.sxd.util; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class MyConfig extends WebMvcConfigurerAdapter { }
2.1通過重寫 WebMvcConfigurerAdapter 類的addResourceHandlers()方法,實現添加自定義的靜態資源映射地址
實現方式如下:

package com.sxd.util; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class MyConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/**").addResourceLocations("classpath:/sxd/"); super.addResourceHandlers(registry); } }
registry.addResourceHandler("/**")代表根訪問路徑,也就是localhost:8080/
addResourceLocations("classpath:/sxd/");代表規定classpath下的/sxd/為靜態資源的映射地址
組合到一起就是localhost:8080/123.png就能訪問到 resources文件夾下的sxd下的文件
這個圖片就是放在項目中,新建的sxd目錄下
然后檢測一下是否自定義的配置可以成功,同時可以檢測到 自定義的靜態資源映射地址和默認的映射地址哪個的優先級更高
訪問之后發現,訪問到的是自定義的映射文件地址下的圖片。
那我們修改一下上面的代碼:

package com.sxd.util; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class MyConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/sxd/**").addResourceLocations("classpath:/sxd/"); super.addResourceHandlers(registry); } }
訪問地址:http://localhost:8080/123.png
訪問地址:http://localhost:8080/sxd/123.png
可以看出,即使是添加了自定義的靜態資源映射地址,原本默認的地址依舊可以起作用。
同樣的,修改【addResourceLocations("file:E:/壁紙/");】可以指定本地磁盤目錄為靜態資源訪問路徑
本地磁盤目錄如下:

package com.sxd.util; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class MyConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/sxd/**").addResourceLocations("file:E:/壁紙/"); super.addResourceHandlers(registry); } }
然后重啟訪問:
最后,再次申明一點:
addResourceHandler("/**") 代表根訪問路徑,也就是localhost:8080/,就是對外暴露的地址
addResourceLocations("classpath:/sxd/"); 代表規定classpath下的/sxd/為靜態資源的映射地址,就是文件存放的目錄
==============================================================================================================
2.2 重寫addViewControllers()方法,實現頁面跳轉的簡便化
前面有spring boot項目訪問jsp頁面:http://www.cnblogs.com/sxdcgaq8080/p/7712874.html
要訪問頁面,還得創建一個controller,然后controller中還得寫一個頁面跳轉的方法,才能訪問跳轉成功。
好現在創建一個hello2頁面
現在

package com.sxd.util; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class MyConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/helloS").setViewName("hello2"); super.addViewControllers(registry); } }
同時咱們原來的controller中原來的訪問方式依舊是可以訪問到的。

package com.sxd.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class ViewController { @RequestMapping("/hello") public String hello(){ return "hello"; } }
現在把controller中的訪問地址和自定義配置中的這個訪問地址設置為一樣的,
controller:
@Controller public class ViewController { @RequestMapping("/hello") public String hello(){ return "hello"; } }
配置類:
@Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/hello").setViewName("hello2"); super.addViewControllers(registry); }
然后重啟,訪問:
contrller和自定義配置類的頁面跳轉相比較,controller中優先有效。
最后,如果想添加多個頁面跳轉,怎么辦 ?
看下面代碼:
@Configuration public class MyConfig extends WebMvcConfigurerAdapter { @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/hello2").setViewName("hello2"); registry.addViewController("/hello3").setViewName("hello3"); super.addViewControllers(registry); } }
重啟,訪問
如此,甚好!!!!
===================================================================================================================
3.實現HandlerInterceptor 接口,重寫addInterceptors方法實現自定義攔截器
好了,現在要實現自定義攔截器,在此之前我們需要做一些工作:
整個項目目錄如下:
pom.xml文件如下:

<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.sxd</groupId> <artifactId>orderdiscount</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>orderdiscount</name> <description>orderdiscount for Spring Boot</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.8.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <!--web 支持--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--jsp頁面使用jstl標簽--> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <!--用於編譯jsp--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> <!--<scope>provided</scope>--> </dependency> <!--spring boot熱部署插件--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <!--開啟熱部署--> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <fork>true</fork><!--這個必須加上--> </configuration> </plugin> </plugins> </build> </project>
application.properties 配置文件:
spring.mvc.view.prefix = /WEB-INF/views/
spring.mvc.view.suffix = .jsp
User實體:
啟動類:

package com.sxd; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class OrderdiscountApplication { public static void main(String[] args) { SpringApplication.run(OrderdiscountApplication.class, args); } }
登錄頁面跳轉控制器--MainController跳轉登錄:
【訪問localhost:8080/toLogin】就去找了根路徑下的login.jsp頁面,也就是classpath:/WEB-INF/views/login.jsp

package com.sxd.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class MainController { @RequestMapping("/toLogin") public String hello(){ return "login"; } }
登錄時驗證用戶信息控制器--ViewController驗證控制:
【如果用戶名和密碼都不為null,返回1,代表登錄成功,並且放入session;否則返回2】

package com.sxd.controller; import com.sxd.entity.User; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Controller public class ViewController { @RequestMapping("/login") @ResponseBody public String hello(HttpServletRequest request, HttpServletResponse response, User user){ System.out.println(user); if(!"".equals(user.getUsername()) && !"".equals(user.getPassword())){ request.getSession().setAttribute("user",user); return "1"; }else{ return "2"; } } }
登錄頁面login.jsp:

<%-- Created by IntelliJ IDEA. User: SXD Date: 2017/11/15 Time: 13:51 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <!DOCTYPE html> <html lang="zh-CN"> <head> <title>登錄頁面</title> <link href="/bootstrap-3.3.7/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container"> <h1 class="text-center">測試登錄頁面</h1> <form class="form-horizontal loginForm"> <div class="form-group-lg"> <label class="col-lg-2 control-label">用戶名</label> <div class="col-lg-10"> <div class="input-group"> <span class="input-group-addon"><span class="glyphicon glyphicon-user"></span></span> <input class="form-control" name="username" type="text" placeholder="輸入用戶名"> </div> </div> </div> <div class="form-group-lg "> <label class="col-lg-2 control-label">密碼</label> <div class="col-lg-10"> <div class="input-group"> <span class="input-group-addon"><span class="glyphicon glyphicon-lock"></span></span> <input class="form-control" name="password" type="password" placeholder="輸入密碼"> </div> </div> </div> <div class="form-group-lg"> <div class="col-lg-4 col-lg-offset-4"> <button class="btn btn-lg btn-primary btn-block" name="userLogin"><span class="glyphicon glyphicon-off"></span>登錄</button> </div> </div> </form> </div> <script src="/js/jquery-3.2.1.min.js"></script> <script src="/js/login.js"></script> </body> </html>
登陸成功頁面hello.jsp

<%-- Created by IntelliJ IDEA. User: SXD Date: 2017/11/14 Time: 14:59 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>歡迎頁面</title> </head> <body> 登陸成功的歡迎頁面!! </body> </html>
login.js

$(document).ready(function(){ /** * 登錄 */ $("button[name='userLogin']").click(function(){ var user = $(".loginForm").serialize(); $.post("/login?"+user,function(data){ if(data == "1"){ location.href = "/toHello"; }else{ alert("登錄失敗"); } }); }); });
和題目描述一致,要實現攔截器功能,需要下面兩個步驟:
1》》創建自己的攔截器類實現HandlerInterceptor接口,並重寫對應的攔截方法
2》》重寫WebMvcConfigurerAdapter中的addInterceptors方法,將自定義的攔截器類添加進來,並且規定攔截哪些,放過哪些地址
創建攔截器 MyInterceptpr.java
【關於重寫HandlerInterceptor的三個方法說明:請在文末查看 補充1】
【需要實現HandlerInterceptor接口,重寫preHandle()方法,判斷session中是否有用戶信息,若有則返回true並繼續執行接下來的程序,否則返回false並重定向到登錄頁面】

package com.sxd.interceptor; import com.sxd.entity.User; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class MyInterceptpr implements HandlerInterceptor{ /** * 預處理方法,handler執行之前調用 * @param httpServletRequest * @param httpServletResponse * @param o * @return true/false true即可執行之后的方法 否則 中斷 * @throws Exception */ @Override public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception { User user = (User) httpServletRequest.getSession().getAttribute("user"); boolean flag = false; if(user != null){ flag = true; }else{ flag = false; httpServletResponse.sendRedirect("/toLogin"); } return flag; } /** *handler執行之后調用 * @param httpServletRequest * @param httpServletResponse * @param o * @param modelAndView * @throws Exception */ @Override public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception { } /** *本次request完成后調用 * @param httpServletRequest * @param httpServletResponse * @param o * @param e * @throws Exception */ @Override public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception { } }
創建攔截器之后,需要將自定義的攔截器添加到自定義配置類MyConfig.java中:

package com.sxd.util; import com.sxd.interceptor.MyInterceptpr; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class MyConfig extends WebMvcConfigurerAdapter { /** * 添加自定義攔截器 * @param registry */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptpr()).addPathPatterns("/**").excludePathPatterns("/toLogin","/login","/js/**","/bootstrap-3.3.7/**"); super.addInterceptors(registry); } /** * 添加自定義頁面跳轉 * @param registry */ @Override public void addViewControllers(ViewControllerRegistry registry) { registry.addViewController("/toHello").setViewName("hello"); super.addViewControllers(registry); } }
.addPathPatterns("/**")要攔截的路徑
.excludePathPatterns("/toLogin","/login","/js/**","/bootstrap-3.3.7/**")要放過的路徑
/js/* 代表js下的子一級目錄
/js/** 代表js下的所有子級
這樣訪問的時候,如果未登錄就會跳轉到login.html頁面,而訪問http://localhost:8080/toLogin 和http://localhost:8080/login 不會被攔截。
=========================================================================================================================================
注意就是:
1.js和css的目錄都放置在webapp下,與/WEB-INF/同級而不是再其里面
2.資源如果放在靜態資源的映射文件下,是可以直接引用到的。。。
如下,123.png放在static目錄下
在頁面上引用一下:

<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>歡迎頁面</title> <link rel="stylesheet" href="/bootstrap-3.3.7/css/bootstrap.min.css"> </head> <body> <div class="container"> <div class="row"> <h1 class="text-center"> 登陸成功頁面!!! </h1> </div> <div class="row text-center"> <img class="img-thumbnai" src="/123.png"> </div> </div> </body> </html>
效果如下:
=========================================================================================================================================
更多配置可以查看WebMvcConfigurerAdapter的類的API。因其是WebMvcConfigurer接口的實現,所以WebMvcConfigurer的API方法也可以用來配置MVC。
只是實現這個接口的話,要實現所有的方法,這樣還是很不方便的唉。
所以還是推薦使用繼承WebMvcConfigurerAdapter類來處理。
=========================================================================================================================================
=========================================================================================================================================
補充1:
HandlerInterceptor接口主要定義了三個方法:
1. boolean preHandle (HttpServletRequest request, HttpServletResponse response, Object handle)方法:該方法將在請求處理之前進行調用,只有該方法返回true,才會繼續執行后續的Interceptor和Controller,當返回值為true 時就會繼續調用下一個Interceptor的preHandle 方法,如果已經是最后一個Interceptor的時候就會是調用當前請求的Controller方法;
2.void postHandle (HttpServletRequest request, HttpServletResponse response, Object handle, ModelAndView modelAndView)方法:該方法將在請求處理之后,DispatcherServlet進行視圖返回渲染之前進行調用,可以在這個方法中對Controller 處理之后的ModelAndView 對象進行操作。
3.void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handle, Exception ex)方法:該方法也是需要當前對應的Interceptor的preHandle方法的返回值為true時才會執行,該方法將在整個請求結束之后,也就是在DispatcherServlet 渲染了對應的視圖之后執行。用於進行資源清理。
=========================================================================================================================================
=========================================================================================================================================
補充2:
關於HandlerInterceptor接口主要定義了三個方法的使用場景------spring boot 獲取到攔截方法的返回值 進行處理
代碼示例: