一般實(shí)現(xiàn)
- 定義一個攔截器類
MyInterceptor.java 實(shí)現(xiàn)HandlerInterceptor 接口
import org.json.JSONObject;
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;
import javax.servlet.http.HttpSession;
import java.io.PrintWriter;
@Component
public class MyInterceptor implements HandlerInterceptor {
Logger logger = LoggerFactory.getLogger(MyInterceptor.class);
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// TODO Auto-generated method stub
//獲取session
logger.info("---------------------開始進(jìn)入請求地址攔截----------------------------");
//return true;
HttpSession session = request.getSession(true);
if (session.getAttribute("userId") == null) {
logger.info("------:跳轉(zhuǎn)到login頁面周荐!");
// response.reset();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter out = null;
JSONObject res = new JSONObject();
res.put("state", "0");
res.put("msg", "login in first");
res.put("output","");
out = response.getWriter();
out.append(res.toString());
return false;
} else {
session.setAttribute("userId", session.getAttribute("userId"));
return true;
}
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
logger.info("--------------處理請求完成后視圖渲染之前的處理操作---------------");
}
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
logger.info("---------------視圖渲染之后的操作-------------------------0");
}
}
定義一個WebConfig類,并將
WebConfig.java
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
@Configuration
public class WebConfig implements WebMvcConfigurer{
@Resource
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(myInterceptor).addPathPatterns("/sensitiveword");//.excludePathPatterns("/login.html").excludePathPatterns("/*.min.js.*");
}
}
這樣一個攔截器就實(shí)現(xiàn)了
HandlerInterceptor是一個接口,其中定義了三個default方法
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
public interface HandlerInterceptor {
default boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
return true;
}
default void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
default void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
}
}
WebMvcConfigurer也是一個接口璧疗,定義的方法都是default方法
import java.util.List;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.lang.Nullable;
import org.springframework.validation.MessageCodesResolver;
import org.springframework.validation.Validator;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.HandlerExceptionResolver;
public interface WebMvcConfigurer {
default void configurePathMatch(PathMatchConfigurer configurer) {
}
//內(nèi)容協(xié)商配置
default void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
}
default void configureAsyncSupport(AsyncSupportConfigurer configurer) {
}
default void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
}
//類型轉(zhuǎn)換器和格式化器
default void addFormatters(FormatterRegistry registry) {
}
//添加攔截器
default void addInterceptors(InterceptorRegistry registry) {
}
//添加靜態(tài)資源,重新定義靜態(tài)資源的路徑
default void addResourceHandlers(ResourceHandlerRegistry registry) {
}
//添加跨域支持
default void addCorsMappings(CorsRegistry registry) {
}
default void addViewControllers(ViewControllerRegistry registry) {
}
//配置視圖解析器
default void configureViewResolvers(ViewResolverRegistry registry) {
}
default void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
}
default void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
}
//配置消息轉(zhuǎn)換器
default void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
}
default void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
}
default void configureHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
default void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> resolvers) {
}
@Nullable
default Validator getValidator() {
return null;
}
@Nullable
default MessageCodesResolver getMessageCodesResolver() {
return null;
}
}
Servlet過濾器
- Servlet過濾器提供過濾作用箕昭,能夠在調(diào)用前檢查Request對象,修改Request Header和Request內(nèi)容叶雹,在Servlet調(diào)用完成以后檢查Response對象,修改Response Header和Respones內(nèi)容
- 可以串聯(lián)
- 只有特定的URL才會觸發(fā)攔截器
public interface Filter {
//Servlet過濾器的初始化方法换吧,Servlet容器創(chuàng)建Servlet過濾器實(shí)例后將調(diào)用這個方法折晦。在這個方法中可以讀取web.xml文件中Servlet過濾器的初始化參數(shù)
public void init(FilterConfig filterConfig) throws ServletException;
//完成實(shí)際的過濾操作,當(dāng)客戶請求訪問于過濾器關(guān)聯(lián)的URL時沾瓦,Servlet容器將先調(diào)用過濾器的doFilter方法满着。FilterChain參數(shù)用于訪問后續(xù)過濾器
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
//Servlet容器在銷毀過濾器實(shí)例前調(diào)用該方法,這個方法中可以釋放Servlet過濾器占用的資源
public void destroy();
}
public interface FilterConfig {
//返回web.xml部署文件中定義的該過濾器的名稱
String getFilterName();
//返回調(diào)用者所處的servlet上下文
ServletContext getServletContext();
//返回過濾器初始化參數(shù)值的字符串形式贯莺,當(dāng)參數(shù)不存在時风喇,返回nul1.name是初始化參數(shù)名
String getInitParameter(String var1);
//以Enumeration形式返回過濾器所有初始化參數(shù)值,如果沒有初始化參數(shù)缕探,返回為空
Enumeration<String> getInitParameterNames();
}
Servlet攔截過程
- 攔截器截獲客戶端請求
- 重新封裝ServletResponse响驴,在封裝后的ServletResponse中提供用戶自定義的輸出流
- 將請求后續(xù)傳遞
- Web組件響應(yīng)請求
- 獲取ServletRespones中的輸出流
- 將響應(yīng)內(nèi)容通過用戶自定義的輸出流寫入到緩沖流中
- 修改響應(yīng)內(nèi)容清空緩沖流輸出相應(yīng)內(nèi)容
對比
- filter基于filter接口中的doFilter回調(diào)函數(shù),interceptor則基于Java本身的反射機(jī)制撕蔼;
- filter是依賴于servlet容器的豁鲤,沒有servlet容器就無法回調(diào)doFilter方法,而interceptor與servlet無關(guān)鲸沮;
- filter的過濾范圍比interceptor大琳骡,filter除了過濾請求外通過通配符可以保護(hù)頁面、圖片讼溺、文件等楣号,而interceptor只能過濾請求,只對action起作用怒坯,在action之前開始炫狱,在action完成后結(jié)束(如被攔截,不執(zhí)行action)剔猿;
- filter的過濾一般在加載的時候在init方法聲明视译,而interceptor可以通過在xml聲明是guest請求還是user請求來辨別是否過濾;
- interceptor可以訪問action上下文归敬、值棧里的對象酷含,而filter不能;
- 在action的生命周期中汪茧,攔截器可以被多次調(diào)用椅亚,而過濾器只能在容器初始化時被調(diào)用一次。