![translation](https://cdn.durumis.com/common/trans.png)
Esta é uma postagem traduzida por IA.
Selecionar idioma
Texto resumido pela IA durumis
- O filtro fornece funcionalidade para o processamento de tarefas adicionais em todas as solicitações correspondentes ao padrão de URL antes e depois que a solicitação é passada para o servlet de despachador. É uma especificação padrão J2EE que funciona no contêiner web, enquanto o interceptor é uma tecnologia fornecida pelo Spring que permite que você consulte ou processe solicitações e respostas antes e depois que o servlet de despachador chama o controlador, funcionando no contexto do Spring.
- O Argument Resolver pode ajudar indiretamente a criar o objeto desejado a partir dos valores recebidos na solicitação quando uma solicitação é recebida pelo controlador.
- Filter e Interceptor diferem em se funcionam no contêiner Spring ou no contêiner web, se processam solicitações com base no servlet de despachador ou no controlador, e o Argument Resolver funciona após o interceptor e retorna um objeto específico.
O que é um filtro (Filter)?
Um filtro é uma funcionalidade de especificação padrão do J2EE que permite que trabalhos adicionais sejam tratados para todas as solicitações que correspondem a um padrão de URL, antes e depois que a solicitação seja passada para o servlet de despachador (Dispatcher Servlet). Em outras palavras, o filtro é gerenciado por um contêiner da Web como o Tomcat, em vez do contêiner do Spring, então ele processa a solicitação antes que ela chegue ao servlet de despachador.
Implementação do Filtro (Filter)
Para adicionar um filtro, você precisa implementar a interface Filter do javax.servlet. Essa interface tem três métodos:
- Método init
- Este é o método para inicializar o objeto de filtro e adicioná-lo ao serviço. O contêiner da Web chama o método init uma vez para inicializar o objeto de filtro. Depois disso, todas as solicitações serão processadas por meio do método doFilter().
- Método doFilter
- Este método é executado pelo contêiner da Web antes que todas as solicitações HTTP que correspondem ao padrão de URL sejam enviadas para o servlet de despachador, e é executado pelo contêiner da Web antes que o servlet de despachador envie uma resposta HTTP para o cliente.
O parâmetro do método doFilter() é o FilterChain. O método doFilter() do FilterChain é usado para passar a solicitação para o próximo destino. Adicionando o processo necessário antes e depois de chain.doFilter(), você pode realizar o processamento desejado.
- Este método é executado pelo contêiner da Web antes que todas as solicitações HTTP que correspondem ao padrão de URL sejam enviadas para o servlet de despachador, e é executado pelo contêiner da Web antes que o servlet de despachador envie uma resposta HTTP para o cliente.
- Método destory
- Este método é para remover o objeto de filtro do serviço e retornar os recursos que ele está usando. Ele é chamado uma vez pelo contêiner da Web. Depois disso, ele não será mais processado por doFilter().
Código de exemplo - Especificação do servlet
@WebFilter("/*")
public class dolphagoFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
//Pré-processamento aqui
request.setCharacterEncoding("UTF-8");
System.out.println("Antes do doFilter()....");
filterChain.doFilter(request, response);
//Pós-processamento aqui
System.out.println("Depois do doFilter()....");
}
@Override
public void destroy() { }
Código de exemplo - @Component
@Order(1)
@Component
public class CustomFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException { }
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
chain.doFilter(request, response);
}
@Override
public void destroy() { }
- @Component: você pode registrar o filtro como um bean do Spring.
- @Order: você pode definir a ordem se houver vários filtros.
- Se você registrar o filtro que corresponde à especificação do servlet como um bean do Spring desta forma, você poderá usar outros beans que correspondem à especificação do Spring.
Código de exemplo - @Configuration
@Configuration
public class CustomRegistrationBean {
@Bean
public FilterRegistrationBean customFilterBean() {
FilterRegistrationBean registration = new FilterRegistrationBean<>();
registration.setFilter(new CustomFilter());
registration.setOrder(1);
registration.addUrlPatterns("/api/*");
return registration;
}
Se você deseja que o filtro seja executado apenas para um determinado URI, você pode registrar o filtro como um bean do Spring usando FilterRegistrationBean.
Uso do Filtro (Filter)
Ele é principalmente responsável pela validação e processamento dos próprios parâmetros de solicitação.
- Trabalho comum relacionado à segurança
- Como o filtro é executado no contêiner da Web, você pode executar uma verificação de segurança (como proteção contra XSS e CSRF) para bloquear solicitações inválidas. Como a solicitação não é enviada para o contêiner do Spring, você pode melhorar ainda mais a segurança.
- Log para todas as solicitações
- Compressão de imagens/dados e codificação de strings
- O filtro implementou recursos usados em toda a aplicação da Web, como compressão de imagens ou dados e codificação de strings.
- Personalização do ServletRequest
- HttpServletRequest só pode ler o conteúdo do corpo uma vez. Portanto, o filtro ou o Interceptor não pode ler o corpo. Você pode criar um ServletRequest personalizado para registrar o corpo.
Interceptor
O que é um Interceptor?
Um Interceptor, diferente de um filtro (Filter), que é uma especificação padrão do J2EE, é uma tecnologia fornecida pelo Spring que permite que você consulte ou processe solicitações e respostas antes e depois que o servlet de despachador chamar o controlador. Em outras palavras, o Interceptor é executado no contexto do Spring, diferente de um filtro que é executado no contêiner da Web.
O servlet de despachador solicita que o mapeamento de manipulador encontre o controlador apropriado. Como resultado, ele retorna uma cadeia de execução (HandlerExecutionChain). Então, se esta cadeia de execução tiver um ou mais interceptores registrados, ele passará por cada interceptor em sequência antes de executar o controlador. Se não houver interceptores, ele executará o controlador diretamente.
Implementação do Interceptor
Para adicionar um Interceptor, você precisa implementar a interface org.springframework.web.servlet.HandlerInterceptor. Essa interface tem três métodos:
- Método preHandle
- O método preHandle é executado antes que o controlador seja chamado. Portanto, você pode usá-lo para realizar trabalhos de pré-processamento que precisam ser executados antes do controlador, como processar informações de solicitação ou adicionar informações adicionais.
- O terceiro parâmetro do método preHandle, o parâmetro handler, é um objeto que abstrai as informações do método anotado com @RequestMapping.
- O tipo de retorno do método preHandle é boolean. Se o valor retornado for true, ele prosseguirá para a próxima etapa. Se for false, o trabalho será interrompido e o trabalho subsequente (próximo interceptor ou controlador) não será executado.
- Método postHandle
- O método postHandle é executado depois que o controlador é chamado. Portanto, você pode usá-lo para realizar trabalhos de pós-processamento que precisam ser executados depois do controlador.
- Método afterCompletion
- O método afterCompletion é executado depois que todas as tarefas são concluídas, incluindo a geração do resultado final de todas as visualizações.
Código de exemplo
@Component
public class CustomInterceptor implements 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 {
}
}
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new CustomInterceptor());
registry.addInterceptor(new LoggingInterceptor());
}
- Registre o interceptor criado como um bean.
- Registre o interceptor criado no método addInterceptors() da interface WebMvcConfigurer.
- Os interceptores são executados na ordem em que são registrados no InterceptorRegistry.
Uso do Interceptor
Ele é principalmente responsável pelo tratamento da consistência das informações de solicitação usando a lógica do serviço.
- Trabalho comum como autenticação/autorização
- Por exemplo, você pode verificar trabalhos relacionados ao cliente, como autenticação ou autorização, antes que eles sejam passados para o controlador.
- Log para chamadas de API
- Você pode registrar as informações do cliente usando os objetos HttpServletRequest e HttpServletResponse passados.
- Processamento de dados passados para o Controller
- Você pode processar os objetos HttpServletRequest e HttpServletResponse passados e passá-los para o controlador.
- Imitando AOP
- Você pode obter informações adicionais, como a assinatura do método que será executado do HandlerMethod, o terceiro parâmetro do método preHandle(), e determinar se a lógica será executada ou não.
Filtro (Filter) vs Interceptor
- O filtro é executado no contexto da Web e o Interceptor é executado no contexto do Spring, portanto, os tempos de execução são diferentes.
- O filtro pode lidar com antes e depois do servlet de despachador, enquanto o Interceptor pode lidar com antes e depois do controlador.
- O filtro é adequado para trabalhos que precisam ser tratados globalmente, independentemente do Spring, ou para validar os próprios parâmetros de entrada, ou para usar o ServletRequest em vez de HttpServletRequest.
- O Interceptor é apropriado para trabalhar globalmente relacionado à solicitação do cliente que entra no Spring, ou para quando você precisa misturar lógica de serviço.
- O Interceptor pode lidar com exceções usando @ControllerAdvice e @ExceptionHandler, mas o filtro não pode fazê-lo.
- O filtro geralmente envolve o método doFilter() com uma declaração try-catch para lidar diretamente com as exceções que ocorrem naquele momento.
Argument Resolver
O que é Argument Resolver?
Argument Resolver é uma funcionalidade que pode indiretamente criar o objeto desejado a partir dos valores que entram na solicitação quando uma solicitação entra no controlador.
Uso do Argument Resolver
Por exemplo, suponha que uma solicitação tenha chegado com um token JWT. Precisamos validar se o token é válido e, em seguida, extrair o ID armazenado no token e criá-lo como um objeto de usuário logado.
Nesse caso, se você não usar Argument Resolver, terá que implementar o processo de validação do token e de conversão para um objeto de usuário logado em todos os controladores. Isso causará código duplicado em controladores que exigem verificação de usuário e aumentará a responsabilidade do controlador. Argument Resolver pode resolver esse problema.
Implementação do Argument Resolver
Você pode usar o Argument Resolver implementando HandlerMethodArgumentResolver. Essa interface especifica que os dois métodos a seguir devem ser implementados.
boolean supportsParameter(MethodParameter parameter);
@Nullable
- Método supportsParameter
- Adicione uma determinada anotação ao parâmetro para o qual deseja que o Argument Resolver seja executado. O método supportsParameter() verifica se o parâmetro do método solicitado tem a anotação desejada, e retorna true se tiver.
- Método resolveArgument
- Se você receber true em supportsParameter(), ou seja, se houver um método com uma determinada anotação, este método vincula o parâmetro à forma desejada e retorna informações.
A implementação do controlador quando você usa Argument Resolver é a seguinte.
@GetMapping("/me")
public ResponseEntity findMemberOfMine(@AuthenticationPrincipal LoginMember loginMember) {
MemberResponse memberResponse = memberService.findMember(loginMember.getId());
return ResponseEntity.ok().body(memberResponse);
Diferença entre Argument Resolver e Interceptor
- O Argument Resolver é executado depois do Interceptor e, quando uma solicitação entra no controlador, ele retorna o objeto desejado a partir dos valores que entram na solicitação.
- Por outro lado, o Interceptor intercepta a solicitação antes que o controlador seja realmente executado e não pode retornar um determinado objeto. Só existe um tipo de retorno booleano ou void.
Fontes
- https://mangkyu.tistory.com/173
- https://junhyunny.github.io/spring-boot/filter-interceptor-and-aop/
- https://supawer0728.github.io/2018/04/04/spring-filter-interceptor/
- https://tecoble.techcourse.co.kr/post/2021-05-24-spring-interceptor/
- https://baeldung-cn.com/spring-mvc-handlerinterceptor-vs-filter
- https://www.baeldung.com/spring-boot-add-filter
Perguntas e respostas esperadas para entrevista
O que é um filtro?
Um filtro é uma funcionalidade que permite que trabalhos adicionais sejam tratados para todas as solicitações que correspondem a um padrão de URL, antes e depois que a solicitação seja passada para o servlet de despachador. Ele é executado no nível do contêiner do servlet.
Quando devo usar um filtro?
Os filtros podem ser usados para tratar trabalhos que precisam ser tratados globalmente, independentemente do Spring, ou para validar os próprios parâmetros de solicitação.
Alguns exemplos incluem trabalhos comuns relacionados à segurança, logs para todas as solicitações, compressão de imagens/dados e codificação de strings, e trabalhos de personalização do ServletRequest.
O que é um Interceptor?
Um Interceptor é uma funcionalidade que permite que você consulte ou processe solicitações e respostas antes e depois que o servlet de despachador chamar o controlador. Em outras palavras, ele é executado no nível do contêiner do Spring.
Quando devo usar um Interceptor?
Os interceptores podem ser usados para tratar trabalhos que precisam ser tratados globalmente relacionados à solicitação do cliente, ou quando você precisa misturar lógica de serviço.
Alguns exemplos incluem trabalhos comuns como autenticação/autorização, logs para chamadas de API, e trabalhos de processamento de dados passados para o controlador.
Qual a diferença entre um filtro e um interceptor?
Um filtro é executado no nível do contêiner do servlet, enquanto um Interceptor é executado no nível do contêiner do Spring.
Os filtros podem lidar com antes e depois do servlet de despachador, enquanto os Interceptores podem lidar com antes e depois do controlador.
Portanto, os filtros são adequados para trabalhos que precisam ser tratados globalmente, independentemente do Spring, enquanto os Interceptores são adequados para trabalhar globalmente relacionado à solicitação do cliente.
O que é Argument Resolver?
Argument Resolver é uma funcionalidade que pode indiretamente criar o objeto desejado a partir dos valores que entram na solicitação quando uma solicitação entra no controlador.
Quando devo usar Argument Resolver?
Você pode usá-lo quando uma solicitação chega com um token JWT, você precisa validar se o token é válido e, em seguida, extrair o ID armazenado no token e criá-lo como um objeto de usuário logado.
Qual a diferença entre um Interceptor e Argument Resolver?
Argument Resolver é executado depois do Interceptor e, quando uma solicitação entra no controlador, ele retorna o objeto desejado a partir dos valores que entram na solicitação. Por outro lado, o Interceptor não pode retornar um objeto como esse, e o Argument Resolver é executado depois que o Interceptor é executado.