Оригинальный адрес блога:блог Пимайка
предисловие
При фактической разработке проекта раньше, хотя фильтры и перехватчики полезны, понимание все еще немного невежественно и не полностью понято, В этой статье будет тщательно проанализирована разница и связь между ними.
фильтр
Фильтр Фильтр, определенный в спецификации сервлета, поддерживается контейнером сервлета, а интерфейс определен вjavax.servlet
В пакете он в основном выполняет предварительную обработку клиентского запроса (HttpServletRequest) и постобработку ответа сервера (HttpServletResponse). Код интерфейса выглядит следующим образом:
package javax.servlet;
import java.io.IOException;
public interface Filter {
void init(FilterConfig var1) throws ServletException;
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
void destroy();
}
Проанализируйте три вышеуказанных метода интерфейса:
- init(FilterConfig): интерфейс инициализации, который вызывается при инициализации пользовательского фильтра, имеет ту же функцию, что и метод инициализации сервлета.
-
doFilter(ServletRequest,ServletResponse,FilterChain): этот метод будет вызываться при поступлении запроса каждого пользователя и перед сервисным методом сервлета (если мы разрабатываем проект сервлета), а FilterChain представляет текущую всю цепочку запросов, вызывая
FilterChain.doFilter
Вы можете продолжать передавать запрос.Если вы хотите перехватить запрос, вы можете не вызывать FilterChain.doFilter, тогда запрос будет возвращен напрямую.Таким образом, фильтр — это шаблон проектирования цепочки ответственности.,существуетspring security
Так же много использования фильтров, есть цепочка фильтров. - destroy: этот метод вызывается при уничтожении объекта Filter.Обратите внимание, что после того, как веб-контейнер вызовет этот метод, контейнер снова вызовет метод doFilter.
Пользовательский фильтр
Пользовательский класс Filter в springboot выглядит следующим образом:
@Component
public class MyFilter implements Filter {
private Logger logger = LoggerFactory.getLogger(MyFilter.class);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
logger.info("filter init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
logger.info("doFilter");
//对request,response进行预处理
//TODO 进行业务逻辑
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
logger.info("filter destroy");
}
}
Метод FilterRegistrationBean
предоставляется в спрингбутFilterRegistrationBean
метод, этот класс предоставляет метод setOrder, который может установить значение порядка для нескольких фильтров. код показывает, как показано ниже:
@Configuration
public class FilterConfig {
/**
* 配置一个Filter注册器
*
* @return
*/
@Bean
public FilterRegistrationBean filterRegistrationBean1() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(filter1());
registrationBean.setName("filter1");
//设置顺序
registrationBean.setOrder(10);
return registrationBean;
}
@Bean
public FilterRegistrationBean filterRegistrationBean2() {
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
registrationBean.setFilter(filter2());
registrationBean.setName("filter2");
//设置顺序
registrationBean.setOrder(3);
return registrationBean;
}
@Bean
public Filter filter1() {
return new MyFilter();
}
@Bean
public Filter filter2() {
return new MyFilter2();
}
}
перехватчик
Перехватчик — это концепция, предложенная Spring.Он действует как фильтр.Он может перехватывать запросы пользователей и обрабатывать их соответствующим образом.Он может осуществлять более тонкий контроль.
В SpringMVC DispatcherServlet захватывает каждый запрос. Прежде чем достичь соответствующего контроллера, запрос может быть обработан перехватчиком. После предварительной обработки в перехватчике запрос наконец достигает контроллера.
Интерфейс перехватчикаorg.springframework.web.servlet.HandlerInterceptor
Интерфейс, код интерфейса следующий:
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 {
}
}
Интерпретация методов интерфейса:
- метод предварительной обработки: Предварительно обработайте запрос, отправленный клиентом. Если метод возвращает true, продолжайте выполнять последующие операции. Если он возвращает false, выполните обработку запроса прерывания, и запрос не будет отправлен в контроллер.
-
метод postHandler: Выполняется после обработки запроса, то есть обрабатывается после вызова метода Controller, конечно, при условии, что предыдущий
preHandle
метод возвращает истину. Конкретно,postHandler
Метод будет вызываться до того, как DispatcherServlet вернет и отобразит представление, а это значит, что мы можем обработать контроллер в этом методе.ModelAndView
объект для работы -
метод afterCompletion: Этот метод выполняется после завершения всего запроса, конечно, посылка все еще
preHandle
Возвращаемое значение метода истинно. Этот метод обычно используется для очистки ресурсов.
пользовательский перехватчик
public class MyInterceptor implements HandlerInterceptor {
private 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...");
}
}
Зарегистрируйте перехватчик и одновременно настройте правила перехватчика.
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(handlerInterceptor())
//配置拦截规则
.addPathPatterns("/**");
}
@Bean
public HandlerInterceptor handlerInterceptor() {
return new MyInterceptor();
}
}
Несколько перехватчиков работают вместе
В springMVC мы можем реализовать несколько перехватчиков и зарегистрировать их по очереди следующим образом:
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(handlerInterceptor())
.addPathPatterns("/**");
registry.addInterceptor(handlerInterceptor2())
.addPathPatterns("/**");
}
Порядок перехватчиков также связан с порядком их регистрации, как минимумpreHandle
Метод такой: На следующем рисунке показан порядок выполнения при совместной работе двух перехватчиков:
На фото выше изМООК
Журнал спула также выводит тот же порядок выполнения:
io-9999-exec-2] c.p.filter.interceptor.MyInterceptor : preHandle....
2018-09-13 12:13:31.292 INFO 9736 --- [nio-9999-exec-2] c.p.filter.interceptor.MyInterceptor2 : preHandle2....
2018-09-13 12:13:31.388 INFO 9736 --- [nio-9999-exec-2] c.p.filter.controller.HelloController : username:pjmike,password:123456
2018-09-13 12:13:31.418 INFO 9736 --- [nio-9999-exec-2] c.p.filter.interceptor.MyInterceptor2 : postHandle2...
2018-09-13 12:13:31.418 INFO 9736 --- [nio-9999-exec-2] c.p.filter.interceptor.MyInterceptor : postHandle...
2018-09-13 12:13:31.418 INFO 9736 --- [nio-9999-exec-2] c.p.filter.interceptor.MyInterceptor2 : afterCompletion2...
2018-09-13 12:13:31.418 INFO 9736 --- [nio-9999-exec-2] c.p.filter.interceptor.MyInterceptor : afterCompletion...
Разница между перехватчиком и фильтром
Из приведенного выше описания перехватчиков и фильтров они очень похожи и могут обрабатывать запросы от клиентов, отличия заключаются в следующем:
-
разная сфера
- Фильтр зависит от контейнера сервлета и может использоваться только в контейнере сервлета, веб-среде.
- Перехватчик зависит от контейнера Spring и может быть вызван в контейнере Spring, независимо от того, в какой среде Spring находится в это время.
-
мелкозернистая разница
- Управление фильтром относительно грубое, и его можно обработать только тогда, когда приходит запрос, а запрос и ответ упакованы.
- Перехватчики обеспечивают более детальное управление и могут быть вызваны до или после обработки запроса контроллером или после того, как визуализированное представление представлено пользователю.
-
Разные уровни сложности прерывания выполнения цепочки
- Перехватчики могут
preHandle
Верните false внутри метода для прерывания - Фильтры более сложны, требуют обработки объектов запроса и ответа, чтобы вызвать прерывания, требуют дополнительных действий, таких как перенаправление пользователя на страницу с ошибкой.
- Перехватчики могут
резюме
Подводя итог, можно сказать, что перехватчики имеют более тонкое управление, чем фильтры. Они зависят от контейнера Spring и могут запускаться до или после запроса. Фильтры в основном зависят от сервлетов. Что могут фильтры, в основном могут перехватчики.