spring boot設(shè)置過濾器、監(jiān)聽器及攔截器的方法
前言
其實(shí)這篇文章算不上是springboot的東西,我們?cè)趕pring普通項(xiàng)目中也是可以直接使用的
設(shè)置過濾器:
以前在普通項(xiàng)目中我們要在web.xml中進(jìn)行filter的配置,但是只從servlet 3.0后,我們就可以在直接在項(xiàng)目中進(jìn)行filter的設(shè)置,因?yàn)樗峁┝艘粋€(gè)注解@WebFilter(在javax.servlet.annotation包下),使用這個(gè)注解我們就可以進(jìn)行filter的設(shè)置了,同時(shí)也解決了我們使用springboot項(xiàng)目沒有web.xml的尷尬,使用方法如下所示
@WebFilter(urlPatterns="/*",filterName="corsFilter", asyncSupported = true)
public class CorsFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse)servletResponse;
HttpServletRequest request = (HttpServletRequest)servletRequest;
chain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
其實(shí)在WebFilter注解中有一些屬性我們需要進(jìn)行設(shè)置, 比如value、urlPatterns,這兩個(gè)屬性其實(shí)都是一樣的作用,都是為了設(shè)置攔截路徑,asyncSupported這個(gè)屬性是設(shè)置配置的filter是否支持異步響應(yīng),默認(rèn)是不支持的,如果我們的項(xiàng)目需要進(jìn)行請(qǐng)求的異步響應(yīng),請(qǐng)求經(jīng)過了filter,那么這個(gè)filter的asyncSupported屬性必須設(shè)置為true不然請(qǐng)求的時(shí)候會(huì)報(bào)異常。
設(shè)置攔截器:
編寫一個(gè)配置類,繼承org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter或者org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport并重寫addInterceptors(InterceptorRegistry registry)方法,其實(shí)父類的addInterceptors(InterceptorRegistry registry)方法就是個(gè)空方法。使用方法如下:
@Configuration
public class MvcConfig extends WebMvcConfigurationSupport {
@Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration registration = registry.addInterceptor(new HandlerInterceptor() {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
});
// 配置攔截路徑
registration.addPathPatterns("/**");
// 配置不進(jìn)行攔截的路徑
registration.excludePathPatterns("/static/**");
}
}
配置監(jiān)聽器:
一般我們常用的就是request級(jí)別的javax.servlet.ServletRequestListener和session級(jí)別的javax.servlet.http.HttpSessionListener,下面以ServletRequestListener為例,編寫一個(gè)類實(shí)現(xiàn)ServletRequestListener接口并實(shí)現(xiàn)requestInitialized(ServletRequestEvent event)方法和requestDestroyed(ServletRequestEvent event)方法,在實(shí)現(xiàn)類上加上@WebListener(javax.servlet.annotation包下),如下所示
@WebListener
public class RequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("請(qǐng)求結(jié)束");
}
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("請(qǐng)求開始");
}
}
這樣每一個(gè)請(qǐng)求都會(huì)被監(jiān)聽到,在請(qǐng)求處理前equestInitialized(ServletRequestEvent event)方法,在請(qǐng)求結(jié)束后調(diào)用requestDestroyed(ServletRequestEvent event)方法,其實(shí)在spring中有一個(gè)非常好的例子,就是org.springframework.web.context.request.RequestContextListener類
public class RequestContextListener implements ServletRequestListener {
private static final String REQUEST_ATTRIBUTES_ATTRIBUTE =
RequestContextListener.class.getName() + ".REQUEST_ATTRIBUTES";
@Override
public void requestInitialized(ServletRequestEvent requestEvent) {
if (!(requestEvent.getServletRequest() instanceof HttpServletRequest)) {
throw new IllegalArgumentException(
"Request is not an HttpServletRequest: " + requestEvent.getServletRequest());
}
HttpServletRequest request = (HttpServletRequest) requestEvent.getServletRequest();
ServletRequestAttributes attributes = new ServletRequestAttributes(request);
request.setAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE, attributes);
LocaleContextHolder.setLocale(request.getLocale());
RequestContextHolder.setRequestAttributes(attributes);
}
@Override
public void requestDestroyed(ServletRequestEvent requestEvent) {
ServletRequestAttributes attributes = null;
Object reqAttr = requestEvent.getServletRequest().getAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE);
if (reqAttr instanceof ServletRequestAttributes) {
attributes = (ServletRequestAttributes) reqAttr;
}
RequestAttributes threadAttributes = RequestContextHolder.getRequestAttributes();
if (threadAttributes != null) {
// We're assumably within the original request thread...
LocaleContextHolder.resetLocaleContext();
RequestContextHolder.resetRequestAttributes();
if (attributes == null && threadAttributes instanceof ServletRequestAttributes) {
attributes = (ServletRequestAttributes) threadAttributes;
}
}
if (attributes != null) {
attributes.requestCompleted();
}
}
}
在這個(gè)類中,spring將每一個(gè)請(qǐng)求開始前都將請(qǐng)求進(jìn)行了一次封裝并設(shè)置了一個(gè)threadLocal,這樣我們?cè)谡?qǐng)求處理的任何地方都可以通過這個(gè)threadLocal獲取到請(qǐng)求對(duì)象,好處當(dāng)然是有的啦,比如我們?cè)趕ervice層需要用到request的時(shí)候,可以不需要調(diào)用者傳request對(duì)象給我們,我們可以通過一個(gè)工具類就可以獲取,豈不美哉。
擴(kuò)充:在springboot的啟動(dòng)類中我們可以添加一些ApplicationListener監(jiān)聽器,例如:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(DemoApplication.class);
application.addListeners(new ApplicationListener<ApplicationEvent>() {
@Override
public void onApplicationEvent(ApplicationEvent event) {
System.err.println(event.toString());
}
});
application.run(args);
}
}
ApplicationEvent是一個(gè)抽象類,她的子類有很多比如ServletRequestHandledEvent(發(fā)生請(qǐng)求事件的時(shí)候觸發(fā))、ApplicationStartedEvent(應(yīng)用開始前觸發(fā),做一些啟動(dòng)準(zhǔn)備工作)、ContextRefreshedEvent(容器初始化結(jié)束后觸發(fā)),其他還有很多,這里不再多說,但是這些ApplicationListener只能在springboot項(xiàng)目以main方法啟動(dòng)的時(shí)候才會(huì)生效,也就是說項(xiàng)目要打jar包時(shí)才適用,如果打war包,放在Tomcat等web容器中是沒有效果的。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Java實(shí)戰(zhàn)項(xiàng)目 圖書管理系統(tǒng)
這篇文章主要介紹了使用java SSM jsp mysql maven設(shè)計(jì)實(shí)現(xiàn)的精品圖書管理系統(tǒng),是一個(gè)很好的實(shí)例,對(duì)大家的學(xué)習(xí)和工作具有借鑒意義,建議收藏一下2021-09-09
Struts2中validate數(shù)據(jù)校驗(yàn)的兩種方法詳解附Struts2常用校驗(yàn)器
這篇文章主要介紹了Struts2中validate數(shù)據(jù)校驗(yàn)的兩種方法及Struts2常用校驗(yàn)器,本文介紹的非常詳細(xì),具有參考借鑒價(jià)值,感興趣的朋友一起看看吧2016-09-09
java多線程Synchronized實(shí)現(xiàn)可見性原理解析
這篇文章主要介紹了java多線程Synchronized實(shí)現(xiàn)可見性原理,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12
Java?8?Stream?處理數(shù)據(jù)方法匯總
這篇文章主要介紹了Java?8?Stream處理數(shù)據(jù),Stream是Java?8?新引入的一個(gè)包它讓我們能用聲明式的方式處理數(shù)據(jù),Stream流式處理相較于傳統(tǒng)方法簡(jiǎn)潔高效,也便于進(jìn)行并發(fā)編程,更多相關(guān)內(nèi)容需要的小伙伴可以參考下面文章內(nèi)容2022-06-06
Java中ByteBuddy動(dòng)態(tài)字節(jié)碼操作庫的使用技術(shù)指南
ByteBuddy?是一個(gè)功能強(qiáng)大的?Java?字節(jié)碼操作庫,可以幫助開發(fā)者在運(yùn)行時(shí)動(dòng)態(tài)生成和修改類,而無需直接接觸復(fù)雜的?ASM?API,本文給大家介紹了Java?ByteBuddy動(dòng)態(tài)字節(jié)碼操作庫的使用技術(shù)指南,需要的朋友可以參考下2025-04-04
java使用JDBC連接數(shù)據(jù)庫的五種方式(IDEA版)
這篇文章主要介紹了java使用JDBC連接數(shù)據(jù)庫的五種方式(IDEA版),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04
基于Java 數(shù)組內(nèi)存分配的相關(guān)問題
本篇文章是對(duì)Java中數(shù)組內(nèi)存分配進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05

