SpringBoot 自定義filter 和 interceptor,自定義靜態檔案存放位置
上篇分享我們已經有了一個最基礎具有登陸驗證功能 的SpringBoot web專案,本篇對照之前SpringMVC 的xml配置,闡述SpringBoot 中的filter 和 interceptor。
一、web.xml中的filter 和 SpringBoot filter 比較。
<filter>
<filter-name>encodingFilter</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter -class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true </param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>encodingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在SpringBoot 中我們定義一個filter:
package cn.pw.pf.web.filter;
import org.springframework.core.annotation.Order;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* 自定義Filter
* Login Filter
* @Description:
* @Author:libin
* @Date: Created in 16:40 2017/11/13
*/
@WebFilter(filterName = "myFilter",urlPatterns = "/*")
@Order(1)
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("filter======> 我是過濾器!");
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
@WebFilter 是自定義Filter的關鍵註解,屬性filterName 相當於web.xml中的 <filter-name>
;屬性urlPatterns 相當於web.xml中的<url-pattern>
。
@Order(1)在定義多個Filter時,用於決定執行順序的,數字越小,越先執行。
說明:本篇以web.xml的CharacterEncodingFilter為例,但在SpringBoot中CharacterEncodingFilter有更簡單的配置,在application.xml中做如下配置便可 :
spring:
http:
encoding:
charset: UTF-8
enabled: true
force: true
言歸正傳,我們啟動專案測試一下過濾器是否 生效:
在瀏覽器分別開啟 http://localhost:8680/hello 和 http://localhost:8680/login ,觀察控制檯輸出,如果不出意外,控制檯連續輸出了 “filter======> 我是過濾器!”,看來我們的過濾器生效了,我們還可以將urlPatterns 設定 為 /hello ,這樣只有訪問 http://localhost:8680/hello 時,控制檯才會輸出 “filter======> 我是過濾器!”。
二、spring-mvc.xml中的 interceptor 和SpringBoot interceptor 比較
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/static/**" />
<bean class="cn.pw.pf.web.filter.MyInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
上面的配置不用解釋,先在filter包下編寫一個MyInterceptor類。
package cn.pw.pf.web.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 自定義攔截器
* @Description:
* @Author:libin
* @Date: Created in 17:46 2017/11/13
*/
@Component
public class MyInterceptor implements HandlerInterceptor {
Logger logger = LoggerFactory.getLogger(MyInterceptor.class);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
logger.info("執行preHandle==============》");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
logger.info("執行postHandle==============》");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
logger.info("執行afterCompletion==============》");
}
}
下面我們看在SpringBoot中如何讓自定義的攔截器MyInterceptor 生效
package cn.pw.pf.web.filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 配置自定義攔截器
* @Description:
* @Author:libin
* @Date: Created in 17:41 2017/11/13
*/
@Configuration
public class MyWebConfig extends WebMvcConfigurerAdapter{
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor).addPathPatterns("/*").excludePathPatterns("/hello/**");
super.addInterceptors(registry);
}
}
閱讀上面的程式碼,我們不難發現,主要在重寫WebMvcConfigurerAdapter的addInterceptors方法上,addPathPatterns添加了要攔截的路徑,excludePathPatterns添加了排除的路徑。
我們重啟專案,測試一下,訪問 http://localhost:8680/login ,也可以在login介面點選登入。
測試結果,我們分析任何一次訪問都經過了filter和interceptor。
filter======> 我是過濾器!
cn.pw.pf.web.filter.MyInterceptor : 執行preHandle==============》
cn.pw.pf.web.filter.MyInterceptor : 執行postHandle==============》
cn.pw.pf.web.filter.MyInterceptor : 執行afterCompletion==============》
filter======> 我是過濾器!
我們排除掉的”/hello/**”,攔截器不再攔截它,測試順利通過!
有同學就問了,你為什麼不按spring-mvc.xml中一樣 ,排除 static 資源。原因很簡單,SpringBoot預設不攔截所有的靜態資源,如果不信,可以 直接訪問 http://localhost:8680/css/common.css 試試。
說明:SpringBoot把類路徑下的/static,/public,/resources和META-INF/resources檔案下的靜態檔案對映為了 “/”,可以直接訪問,我們也可以根據下面的方法自定義靜態檔案的存放位置。
三、自定義靜態檔案存放 位置,只需在MyWebConfig 中,重寫addResourceHandlers方法。
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/img/**").addResourceLocations("classpath:/img/");
super.addResourceHandlers(registry);
}
這樣,我們就定義了一個和static平級的資料夾img用來存放圖片,隨便丟一張 圖片no.jpg進去,然後帶上路徑訪問:
http://localhost:8680/img/no.jpg
OK,今天的分享就到此結束了,SpringBoot的基礎使用就分享這麼多,很簡單。
到今天網際網路迸發的時代,微服務已是大勢所趨,只有在 SpringCloud 微服務架構下,使用SpringBoot才是開發人員值得研究的方向。如果有人想深入瞭解SpringBoot ,我推薦《java EE 開發的顛覆者 Spring Boot 實戰》這本書。但是,初學的讀者一定要注意,這本書是在SpringBoot 1.3版本的基礎上講解的,想實踐書中的例子,一定要用對版本,要不會很苦惱。
後面的分享,我將開啟新的篇章,結合SpringCloud 、Eureka、等,逐步由簡入深,來完成一個基於微服務框架的簡單demo,幫助初學者快速上手。