一、Servlet、Filter(過濾器)、?Listener(監(jiān)聽器)、Interceptor(攔截器)
Javaweb三大組件:servlet、Filter(過濾器)、?Listener(監(jiān)聽器)
SpringBoot特有組件:Interceptor(攔截器)
過濾器、攔截器、監(jiān)聽器、AOP(后續(xù)文章介紹)、全局異常處理器(后續(xù)文章介紹)是搭建系統(tǒng)框架時(shí),經(jīng)常用到的部分,全局異常處理器的作用很明顯,就是處理接口執(zhí)行過程中的異常,而過濾器、攔截器和AOP的作用就很豐富了,日志記錄、性能監(jiān)控、安全認(rèn)證等等可以向上抽取的功能組件,均可以用他們來實(shí)現(xiàn)。
傳統(tǒng)基于Servlet容器的程序中,我們可以使用過濾器和監(jiān)聽器,在Java 框架中還可以使用攔截器,而面向切面編程AOP更是作為Spring框架中的核心思想被大家所關(guān)注
Filter和Listener:依賴Servlet容器,基于函數(shù)回調(diào)實(shí)現(xiàn)??梢詳r截所有請(qǐng)求,覆蓋范圍更廣,但無法獲取ioc容器中的bean。
Interceptor和aop:依賴spring框架,基于java反射和動(dòng)態(tài)代理實(shí)現(xiàn)。只能攔截controller的請(qǐng)求,可以獲取ioc容器中的bean,這點(diǎn)很重要,在攔截器里注入一個(gè)service,可以調(diào)用業(yè)務(wù)邏輯。。?
從 Filter -> Interceptor -> aop ,攔截的功能越來越細(xì)致、強(qiáng)大,尤其是Interceptor和aop可以更好的結(jié)合spring框架的上下文進(jìn)行開發(fā)。但是攔截順序也是越來越靠后,請(qǐng)求是先進(jìn)入Servlet容器的,越早的過濾和攔截對(duì)系統(tǒng)性能的消耗越少。具體選用哪種方法,就需要開發(fā)人員根據(jù)實(shí)際業(yè)務(wù)情況綜合考慮了。
二、過濾器
1、過濾器作用
Filter過濾器是Servlet容器層面的,在實(shí)現(xiàn)上基于函數(shù)回調(diào),可以對(duì)幾乎所有請(qǐng)求進(jìn)行過濾
過濾器是對(duì)數(shù)據(jù)進(jìn)行過濾,預(yù)處理過程,當(dāng)我們訪問網(wǎng)站時(shí),有時(shí)候會(huì)發(fā)布一些敏感信息,發(fā)完以后有的會(huì)用*替代,還有就是登陸權(quán)限控制等,一個(gè)資源,沒有經(jīng)過授權(quán),肯定是不能讓用戶隨便訪問的,這個(gè)時(shí)候,也可以用到過濾器,主要是對(duì)用戶的一些請(qǐng)求進(jìn)行一些預(yù)處理,并在服務(wù)器響應(yīng)后再進(jìn)行預(yù)處理,返回給用戶。
過濾器的功能還有很多,例如實(shí)現(xiàn)URL級(jí)別的權(quán)限控制、壓縮響應(yīng)信息、編碼格式等等。對(duì)web服務(wù)器管理所有的web資源,例如jsp,靜態(tài)圖片 過濾敏感詞匯,某些信息用*隱藏。
使用方式有以下三種
2、過濾器執(zhí)行流程
3、過濾器攔截路徑
4、過濾鏈
一個(gè)javaweb系統(tǒng)中,可以配置多個(gè)過濾器、這多個(gè)過濾器就形成了一個(gè)過濾鏈,當(dāng)然可以控制每個(gè)過濾器順序,見過濾器三種實(shí)現(xiàn)方式
5、過濾器三種實(shí)現(xiàn)方式
第一種方式:利用Servlet3.0的WebFilter注解配置
@WebFilter是Servlet3.0新增加的注解,在servlet3.0之前,我們需要在web.xml文件中進(jìn)行過濾器的配置,而現(xiàn)在可以通過此注解進(jìn)行配置,當(dāng)項(xiàng)目啟動(dòng)時(shí),會(huì)自動(dòng)掃描自動(dòng)注冊
通過 @WebFilter 注解來標(biāo)記一個(gè)過濾器,這種方式相信大家很容易想到。這是將 Servlet 中的那一套東西直接拿到 Spring Boot 上用。
具體做法就是通過 @WebFilter 注解來標(biāo)記一個(gè) Filter,如下:
//一個(gè)是filter的名字,一個(gè)是url為什么時(shí)用此過濾器,其他的看源碼,Filter,必須要有名字,所有的過濾器執(zhí)行順序是根據(jù)Filter的名字字母順序來執(zhí)行的
@WebFilter(filterName = "filter1",urlPatterns = {"/hello/*"})
public class TimeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("=======初始化過濾器=========");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
long start = System.currentTimeMillis();
filterChain.doFilter(request, response);
System.out.println("filter 耗時(shí):" + (System.currentTimeMillis() - start));
}
@Override
public void destroy() {
System.out.println("=======銷毀過濾器=========");
}
}
這個(gè)注解要生效,還需要我們在項(xiàng)目啟動(dòng)類上配置 @ServletComponentScan 注解,
@ServletComponentScan 注解雖然名字帶了 Servlet,但是實(shí)際上它不僅僅可以掃描項(xiàng)目中的 Servlet 容器,也可以掃描 Filter 和 Listener。
這是我們在 Spring Boot 中使用過濾器的第一種方式,在實(shí)際項(xiàng)目中,這種方式使用較少,因?yàn)檫@種方式有一個(gè)很大的弊端就是無法指定 Filter 的優(yōu)先級(jí),如果存在多個(gè) Filter 時(shí),無法通過 @Order 指定優(yōu)先級(jí)。
@SpringBootApplication
@ServletComponentScan
public class SysoaApplication {
public static void main(String[] args) {
SpringApplication.run(SysoaApplication.class, args);
}
}
第二種方式:利用SpringBoot的配置類來添加過濾器
這種方式最簡單,直接實(shí)現(xiàn)Filter接口,并使用@Component注解標(biāo)注為組件自動(dòng)注入bean,
Filter接口有 init、doFilter、destroy 三個(gè)方法,但 init、destroy 是有默認(rèn)方法實(shí)現(xiàn),可以不重寫。
@Component
public class TimeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("=======初始化過濾器=========");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
long start = System.currentTimeMillis();
filterChain.doFilter(request, response);
System.out.println("filter 耗時(shí):" + (System.currentTimeMillis() - start));
}
@Override
public void destroy() {
System.out.println("=======銷毀過濾器=========");
}
}
但是缺點(diǎn)是沒辦法設(shè)置過濾的路徑,默認(rèn)是 /* 過濾所有(當(dāng)然代碼中可以加入相關(guān)判斷)。?
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String requestUri = request.getRequestURI().replaceFirst(contextPath, "");
String[] urlList = {"/login","/loginPage","logOut"};
for (String uriItem : urlList){
if(requestUri.contains(uriItem)){
filterChain.doFilter(request,response);
return;
}
}
//判斷session中是否存在用戶,這里還可以做其他業(yè)務(wù)邏輯 比如ip黑名單等 用戶是否被禁,禁止多人在線等
if (request.getSession().getAttribute(SystemConstants.USER) == null) {
//沒有登錄跳轉(zhuǎn)到登錄頁面
response.sendRedirect(contextPath+SystemConstants.LOGIN_PAGE_URL);
return;
}
filterChain.doFilter(request, response);
}
這種方式看起來很方便,一個(gè)注解將 Filter 納入到 Spring 容器中即可。而且這種方式還有一個(gè)優(yōu)勢,就是如果存在多個(gè) Filter,可以通過 @Order 注解指定多個(gè) Filter 的優(yōu)先級(jí),像下面這樣:
@Component
@Order(-1)
public class MyFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("-----doFilter-----");
chain.doFilter(request, response);
}
}
第三種方式:Configuration+FilterRegistrationBean
還是將 Filter 封裝成一個(gè) Bean,但這個(gè) Bean 是 FilterRegistrationBean,通過 FilterRegistrationBean 我們既可以配置 Filter 的優(yōu)先級(jí),也可以配置 Filter 的攔截規(guī)則。
public class AFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("=======初始化過濾器A=========");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
long start = System.currentTimeMillis();
filterChain.doFilter(request, response);
System.out.println("filter 耗時(shí):" + (System.currentTimeMillis() - start));
}
@Override
public void destroy() {
System.out.println("=======銷毀過濾器=========");
}
}
?然后使用SpringBoot提供的FilterRegistrationBean來對(duì)Filter進(jìn)行配置
@Configuration
public class FilterConfig {
/*過濾器注解bean: FilterRegistrationBean, 注冊過濾器, 添加過濾器*/
@Bean
public FilterRegistrationBean<AFilter> createFilterRegistrationBean() {
//1.創(chuàng)建FilterRegistrationBean這個(gè)對(duì)象, 一個(gè)過濾器注冊器,注冊一個(gè)過濾器
FilterRegistrationBean<AFilter> filterRegistrationBean = new FilterRegistrationBean<>();
//注冊一個(gè)過濾器
filterRegistrationBean.setFilter(new AFilter());
//過濾器的配置, 設(shè)置攔截的url
filterRegistrationBean.addUrlPatterns("/*");
//給過濾器起名字
filterRegistrationBean.setName("AFilter");
//設(shè)置過濾器的執(zhí)行順序
filterRegistrationBean.setOrder(1);
return filterRegistrationBean;
}
當(dāng)然也可以配置多個(gè)并且控制順序
@Configuration
public class FilterConfig {
@Bean
FilterRegistrationBean<AFilter> myFilterFilterRegistrationBean() {
FilterRegistrationBean<AFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new AFilter());
bean.setOrder(-1);
bean.setUrlPatterns(Arrays.asList("/*"));
return bean;
}
@Bean
FilterRegistrationBean<BFilter> myFilterFilterRegistrationBean2() {
FilterRegistrationBean<BFilter> bean = new FilterRegistrationBean<>();
bean.setFilter(new BFilter());
bean.setOrder(-2);
bean.setUrlPatterns(Arrays.asList("/hello"));
return bean;
}
}
?
FilterRegistrationBean 擴(kuò)展
Spring Boot 為了方便大家向 Servlet 容器中注冊 Servlet、Filter 以及 Listener,提供了一個(gè) Bean 注冊的抽象類 RegistrationBean,如下:
public abstract class RegistrationBean implements ServletContextInitializer, Ordered {
private int order = Ordered.LOWEST_PRECEDENCE;
private boolean enabled = true;
@Override
public final void onStartup(ServletContext servletContext) throws ServletException {
String description = getDescription();
if (!isEnabled()) {
logger.info(StringUtils.capitalize(description) + " was not registered (disabled)");
return;
}
register(description, servletContext);
}
protected abstract String getDescription();
protected abstract void register(String description, ServletContext servletContext);
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isEnabled() {
return this.enabled;
}
public void setOrder(int order) {
this.order = order;
}
@Override
public int getOrder() {
return this.order;
}
}
?
RegistrationBean 實(shí)現(xiàn)了 ServletContextInitializer 接口,在 Servlet 啟動(dòng)時(shí),RegistrationBean#onStartup 方法會(huì)被調(diào)用,進(jìn)而完成 Filter、Servlet 以及 Listener 的注冊。
? ? enabled 屬性可以理解為一個(gè)開關(guān),設(shè)置為 false 相當(dāng)于關(guān)閉組件注冊。
RegistrationBean 有眾多的實(shí)現(xiàn)類,我們之前使用的 FilterRegistrationBean 只是其中之一:
實(shí)現(xiàn)類的作用一目了然:
? ? ServletListenerRegistrationBean 用來注冊監(jiān)聽器。
? ? ServletRegistrationBean 用來注冊 Servlet。
? ? DispatcherServletRegistrationBean 用來注冊 DispatcherServlet。
? ? FilterRegistrationBean 用來注冊過濾器。
? ? DelegatingFilterProxyRegistrationBean 則用來注冊 DelegatingFilterProxy,DelegatingFilterProxy 在 Spring Security、Spring Session、Shiro 等整合時(shí)非常有用。
?
6、過濾器實(shí)際項(xiàng)目場景使用舉例
使用filter實(shí)現(xiàn)登錄校驗(yàn)
三、監(jiān)聽器
Listener監(jiān)聽器也是Servlet層面的,可以用于監(jiān)聽Web應(yīng)用中某些對(duì)象、信息的創(chuàng)建、銷毀和修改等動(dòng)作發(fā)生,然后做出相應(yīng)的響應(yīng)處理。可以在這些事件發(fā)生前和發(fā)生后進(jìn)行處理。
用途:
1、用于統(tǒng)計(jì)在線人數(shù)和在線用戶,
2、系統(tǒng)啟動(dòng)時(shí)加載初始化信息,
3、統(tǒng)計(jì)網(wǎng)站訪問量,
4、記錄用戶訪問路徑
根據(jù)監(jiān)聽對(duì)象,將監(jiān)聽器分為3類:
第一類:ServletContext:對(duì)應(yīng)application,實(shí)現(xiàn)接口ServletContextListener。在整個(gè)Web服務(wù)中只有一個(gè),在Web服務(wù)關(guān)閉時(shí)銷毀??捎糜谧鰯?shù)據(jù)緩存,例如結(jié)合redis,在Web服務(wù)創(chuàng)建時(shí)從數(shù)據(jù)庫拉取數(shù)據(jù)到緩存服務(wù)器。
第二類:HttpSession:對(duì)應(yīng)session會(huì)話,實(shí)現(xiàn)接口HttpSessionListener。在會(huì)話起始時(shí)創(chuàng)建,一端關(guān)閉會(huì)話后銷毀。可用作獲取在線用戶數(shù)量。
第三類:ServletRequest:對(duì)應(yīng)request,實(shí)現(xiàn)接口ServletRequestListener。request對(duì)象是客戶發(fā)送請(qǐng)求時(shí)創(chuàng)建的,用于封裝請(qǐng)求數(shù)據(jù),請(qǐng)求處理完畢后銷毀。可用作封裝用戶信息。
在寫Listener的類時(shí),有兩種方式。
第一種是只加@Component;
第二種是 @WebListener 和 @ServletComponentScan 配合使用。
不過實(shí)現(xiàn)接口則根據(jù)監(jiān)聽對(duì)象區(qū)分,如:ServletContextListener、HttpSessionListener和ServletRequestListener。
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
@WebListener()
public class MyListener implements HttpSessionListener{
public static int online = 0;
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("創(chuàng)建session,在線用戶數(shù):" + (++online));
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("銷毀session,在線用戶數(shù):" + (--online));
online--;
}
}
啟動(dòng)類
@SpringBootApplication
@ServletComponentScan("com.demo.listener") //需要掃描包
public class SpringBoot1Application {
public static void main(String[] args) {
SpringApplication.run(SpringBoot1Application.class, args);
}
}
?
這里我們再補(bǔ)充一下常用的監(jiān)聽器接口:
1.ServletContextListener -- 監(jiān)聽servletContext對(duì)象的創(chuàng)建以及銷毀
? ? 1.1 ? ?contextInitialized(ServletContextEvent arg0) ? -- 創(chuàng)建時(shí)執(zhí)行
? ? 1.2 ? ?contextDestroyed(ServletContextEvent arg0) ?-- 銷毀時(shí)執(zhí)行
2.HttpSessionListener ?-- 監(jiān)聽session對(duì)象的創(chuàng)建以及銷毀
? ? 2.2 ? sessionCreated(HttpSessionEvent se) ? -- 創(chuàng)建時(shí)執(zhí)行
? ? 2.2 ? sessionDestroyed(HttpSessionEvent se) -- 銷毀時(shí)執(zhí)行
3.ServletRequestListener -- 監(jiān)聽request對(duì)象的創(chuàng)建以及銷毀
? ? 3.1 ? ?requestInitialized(ServletRequestEvent sre) -- 創(chuàng)建時(shí)執(zhí)行
? ? 3.2 ? ?requestDestroyed(ServletRequestEvent sre) -- 銷毀時(shí)執(zhí)行
4.ServletContextAttributeListener ?-- 監(jiān)聽servletContext對(duì)象中屬性的改變
? ? 4.1 ? ?attributeAdded(ServletContextAttributeEvent event) -- 添加屬性時(shí)執(zhí)行
? ? 4.2 ? ?attributeReplaced(ServletContextAttributeEvent event) -- 修改屬性時(shí)執(zhí)行
? ? 4.3 ? ?attributeRemoved(ServletContextAttributeEvent event) -- 刪除屬性時(shí)執(zhí)行
5.HttpSessionAttributeListener ?--監(jiān)聽session對(duì)象中屬性的改變
? ? 5.1 ? ?attributeAdded(HttpSessionBindingEvent event) -- 添加屬性時(shí)執(zhí)行
? ? 5.2 ? ?attributeReplaced(HttpSessionBindingEvent event) -- 修改屬性時(shí)執(zhí)行
? ? 5.3 ? ?attributeRemoved(HttpSessionBindingEvent event) -- 刪除屬性時(shí)執(zhí)行
6.ServletRequestAttributeListener ?--監(jiān)聽request對(duì)象中屬性的改變
? ? 6.1 ? ?attributeAdded(ServletRequestAttributeEvent srae) -- 添加屬性時(shí)執(zhí)行
? ? 6.2 ? ?attributeReplaced(ServletRequestAttributeEvent srae) -- 修改屬性時(shí)執(zhí)行
? ? 6.3 ? ?attributeRemoved(ServletRequestAttributeEvent srae) -- 刪除屬性時(shí)執(zhí)行
?
四、攔截器
1、攔截器作用
過濾器是攔截所有請(qǐng)求,而攔截器是攔截在進(jìn)入到前端控制器之后的請(qǐng)求,
Interceptor和Filter、Listener有本質(zhì)上的不同,F(xiàn)ilter、Listener都是依賴于Servlet容器,而Interceptor則是依賴于Spring框架,是aop的一種表現(xiàn),當(dāng)某個(gè)方法或字段被訪問時(shí)進(jìn)行攔截,在之前 和 在之后 加入某些操作
用途:權(quán)限驗(yàn)證,判斷用戶是否登錄,或者再做某一操作時(shí)要確定滿足某一定的條件,基于Java的動(dòng)態(tài)代理實(shí)現(xiàn)的。
2、攔截器執(zhí)行流程
3、攔截器攔截路徑
?攔截器可以根據(jù)需求配置不同的攔截路徑
?
4、攔截器的使用
首先通過實(shí)現(xiàn) HandlerInterceptor接口聲明攔截器的類,實(shí)現(xiàn)preHandle、postHandle和afterCompletion方法。然后通過配置類WebMvcConfigurer接口,實(shí)現(xiàn)addInterceptors方法配置攔截器
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;
@Component
public class InterceptorTest implements HandlerInterceptor {
/**
* 在請(qǐng)求處理之前進(jìn)行調(diào)用(Controller方法調(diào)用之前)
* 預(yù)處理回調(diào)方法,實(shí)現(xiàn)處理器的預(yù)處理
* 返回值:true表示繼續(xù)流程;false表示流程中斷,不會(huì)繼續(xù)調(diào)用其他的攔截器或處理器
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("開始攔截.........");
String name = MyCookie.getCookieByKey(request,response,"name");
String password = MyCookie.getCookieByKey(request,response,"password");
//如果session中沒有user,表示沒登陸
if (password == null|| name == null){
//這個(gè)方法返回false表示忽略當(dāng)前請(qǐng)求,如果一個(gè)用戶調(diào)用了需要登陸才能使用的接口,如果他沒有登陸這里會(huì)直接忽略掉
//當(dāng)然你可以利用response給用戶返回一些提示信息,告訴他沒登陸
request.getRequestDispatcher("/interceptor/to_login").forward(request, response);
return false;
}else {
return true;//放行
}
}
/**
* 請(qǐng)求處理之后進(jìn)行調(diào)用,但是在視圖被渲染之前(Controller方法調(diào)用之后)
* 后處理回調(diào)方法,實(shí)現(xiàn)處理器(controller)的后處理,但在渲染視圖之前
* 此時(shí)我們可以通過modelAndView對(duì)模型數(shù)據(jù)進(jìn)行處理或?qū)σ晥D進(jìn)行處理
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
System.out.println("return前");
}
/**
* 在整個(gè)請(qǐng)求結(jié)束之后被調(diào)用,也就是在DispatcherServlet 渲染了對(duì)應(yīng)的視圖之后執(zhí)行(主要是用于進(jìn)行資源清理工作)
* 整個(gè)請(qǐng)求處理完畢回調(diào)方法,即在視圖渲染完畢時(shí)回調(diào),
* 如性能監(jiān)控中我們可以在此記錄結(jié)束時(shí)間并輸出消耗時(shí)間,
* 還可以進(jìn)行一些資源清理,類似于try-catch-finally中的finally,
* 但僅調(diào)用處理器執(zhí)行鏈中
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
System.out.println("操作完之后,可以用于資源清理");
}
}
然后將這個(gè)組件加入到boot中,在boot1版本中 通過繼承WebmvcConfigureAdapter實(shí)現(xiàn)一個(gè)web配置,例如我們配置上面的攔截器
@Configuration //聲明這是一個(gè)配置
public class LoginInterceptorConfig extends WebMvcConfigurerAdapter {
@Resource
private LoginInterceptor loginInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor).addPathPatterns("/admin/**").excludePathPatterns("/admin").excludePathPatterns("/admin/login");
}
}
?或者直接使用匿名類的方式
import org.springframework.context.annotation.Configuration;
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;
/**
* 自定義一個(gè)登陸攔截器
*/
@Configuration //聲明這是一個(gè)配置
public class LoginInterceptor extends WebMvcConfigurerAdapter {
/*
用來添加攔截器的方法
InterceptorRegistry registry攔截器注冊
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
//使用匿名內(nèi)部類創(chuàng)建要給攔截器
HandlerInterceptor loginInterceptor = new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
//判斷session中是否存在用戶
if (request.getSession().getAttribute("user") == null) {
response.sendRedirect("/admin");
return false;
}
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
}
};
registry.addInterceptor(loginInterceptor).addPathPatterns("/admin/**").excludePathPatterns("/admin").excludePathPatterns("/admin/login");
}
}
?對(duì)于Sprinboot2版本,第一步還是定義一個(gè)攔截器組件。
第二不再是通過繼承WebmvcConfigureAdapter實(shí)現(xiàn)一個(gè)web配置,而是實(shí)現(xiàn)接口WebMvcConfigurer增加一個(gè)配置
@Configuration
public class WebConfig implements WebMvcConfigurer {
//引入我們的攔截器組件
@Resource
private LoginInterceptor loginInterceptor;
//實(shí)現(xiàn)攔截器配置方法
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor).addPathPatterns("/admin/**").excludePathPatterns("/admin").excludePathPatterns("/admin/login");
}
}
踩坑5--springboot2.xl登陸攔截器中排除靜態(tài)資源的幾種情況整理 - 百度文庫 (baidu.com)?
5、攔截器使用場景舉例
Filter與Interceptor區(qū)別
1.接口范圍不同:過濾器需要實(shí)現(xiàn)Filter接口,而攔截器需要實(shí)現(xiàn)HandlerInterceptor接口。文章來源:http://www.zghlxwxcb.cn/news/detail-770497.html
2.攔截范圍不同:過濾器Filter會(huì)攔截所有的資源,而Interceptor只會(huì)攔截Spring環(huán)境中的資源文章來源地址http://www.zghlxwxcb.cn/news/detail-770497.html
到了這里,關(guān)于Springboot中使用攔截器、過濾器、監(jiān)聽器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!