Фильтры, вероятно, знакомы многим, особенно тем, кто начинал изучать Java-серверную часть с Servlet. Но что же можно сделать с помощью фильтров? Фильтры主要用于过滤用户请求,允许我们在请求到达目标资源之前或之后进行预处理和后处理。例如,可以实现基于 URL 的权限控制、过滤非法请求等。Фильтры являются конкретной реализацией программирования с использованием аспектов (AOP), которое представляет собой определенный подход к программированию.
Кроме того, фильтры зависят от контейнера Servlet, интерфейс Filter
находится в пакете Servlet и является частью спецификации Servlet. Поэтому часто его называют "усовершенствованным Servlet".
Если вам нужно создать собственный фильтр, это очень просто: вам нужно реализовать интерфейс javax.servlet.Filter
и переопределить три метода внутри него!
Filter.java
public interface Filter {
// Операции, выполняемые после инициализации фильтра
default void init(FilterConfig filterConfig) throws ServletException {
}
// Фильтрация запроса
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
// Операции, выполняемые после завершения работы фильтра, обычно используются для освобождения ресурсов
default void destroy() {
}
}
В интерфейсе Filter
есть метод doFilter
, который реализует фильтрацию запросов. Вот основные шаги:1. Пользователь отправляет запрос на веб-сервер, запрос сначала попадает в фильтр;
2. Фильтр обрабатывает запрос, например, фильтрует параметры запроса, изменяет содержимое ответа, которое возвращается клиенту, проверяет, имеет ли пользователь доступ к определенному ресурсу и т.д.
3. Ответ на запрос пользователя завершается.
4. Выполняются дополнительные операции, которые вы хотите выполнить.
Вот два способа.
Собственные фильтры должны реализовать интерфейс javax.servlet.Filter
и переопределить три метода, определенные в интерфейсе.
MyFilter.java
/**
* @author shuang.kou
*/
@Component
public class MyFilter implements Filter {
private static final Logger logger = LoggerFactory.getLogger(MyFilter.class);
@Override
public void init(FilterConfig filterConfig) {
logger.info("Инициализация фильтра: {}", filterConfig.getFilterName());
}
В конфигурации регистрируем собственный фильтр.
@Configuration
public class MyFilterConfig {
@Autowired
MyFilter myFilter;
@Bean
public FilterRegistrationBean<MyFilter> thirdFilter() {
FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(myFilter);
filterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/api/*")));
return filterRegistrationBean;
}
}
@WebFilter
к собственному фильтру и конфигурируем его через параметры этой аннотации.
@WebFilter(filterName = "MyFilterWithAnnotation", urlPatterns = "/api/*")
public class MyFilterWithAnnotation implements Filter {
......
}
Для того чтобы Spring мог найти этот фильтр, необходимо добавить аннотацию @ServletComponentScan
к стартовому классу.
Что если мы добавим еще один фильтр?
MyFilter2.java
@Component
public class MyFilter2 implements Filter {
private static final Logger logger = LoggerFactory.getLogger(MyFilter2.class);
@Override
public void init(FilterConfig filterConfig) {
logger.info("Инициализация фильтра 2");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// Предварительная обработка запроса
logger.info("Фильтр начал предварительную обработку запроса 2:");
HttpServletRequest request = (HttpServletRequest) servletRequest;
String requestUri = request.getRequestURI();
System.out.println("Запрошенный интерфейс 2: " + requestUri);
long startTime = System.currentTimeMillis();
// Реализация функции фильтрации через метод doFilter
filterChain.doFilter(servletRequest, servletResponse);
// После выполнения метода doFilter запрос пользователя уже возвращен
long endTime = System.currentTimeMillis();
System.out.println("Запрос пользователя обработан, затраченное время 2: " + (endTime - startTime));
}
@Override
public void destroy() {
logger.info("Уничтожение фильтра 2");
}
}
Регистрация пользовательского фильтра в конфигурации, используя метод setOrder
класса FilterRegistrationBean
для определения порядка выполнения фильтра.
@Configuration
public class MyFilterConfig {
@Autowired
MyFilter myFilter;
@Autowired
MyFilter2 myFilter2;
@Bean
public FilterRegistrationBean<MyFilter> setUpMyFilter() {
FilterRegistrationBean<MyFilter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setOrder(2);
filterRegistrationBean.setFilter(myFilter);
filterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/api/*")));
return filterRegistrationBean;
}
@Bean
public FilterRegistrationBean<MyFilter2> setUpMyFilter2() {
FilterRegistrationBean<MyFilter2> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setOrder(1);
filterRegistrationBean.setFilter(myFilter2);
filterRegistrationBean.setUrlPatterns(new ArrayList<>(Arrays.asList("/api/*")));
return filterRegistrationBean;
}
}
Создание пользовательского контроллера для проверки фильтра
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api")
public class MyController {
@GetMapping("/hello")
public String getHello() throws InterruptedException {
Thread.sleep(1000);
return "Hello";
}
}
Результаты тестирования:
2019-10-22 22:32:15.569 INFO 1771 --- [ main] g.j.springbootfilter.filter.MyFilter2 : Инициализация фильтра 2
2019-10-22 22:32:15.569 INFO 1771 --- [ main] g.j.springbootfilter.filter.MyFilter : Инициализация фильтра
2019-10-22 22:32:55.199 INFO 1771 --- [nio-8080-exec-1] g.j.springbootfilter.filter.MyFilter2 : Фильтр начал предварительную обработку запроса 2:
Интерфейс запроса 2: /api/hello
2019-10-22 22:32:55.199 INFO 1771 --- [nio-8080-exec-1] g.j.springbootfilter.filter.MyFilter : Фильтр начал предварительную обработку запроса:
Интерфейс запроса: /api/hello
Запрос пользователя обработан, затраченное время: 1037 мс
Запрос пользователя обработан, затраченное время 2: 1037 мс
```Код доступен по адресу: https://github.com/Snailclimb/springboot-guide/tree/master/source-code/basis/springboot-filter-interceptor
```
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )