Durante o desenvolvimento do projeto da web springboot, geralmente precisamos solicitar o processamento de interceptação do conteúdo da solicitação e resposta, como registro de solicitação, verificação de UA, verificação de permissão do usuário, filtragem de conteúdo ilegal e outras funções. Nesse momento, filtros e interceptores são enviados. usar.
Este artigo explica como o springboot usa filtros e interceptores e a diferença entre os dois.
Navegação neste artigo
filtro
Os filtros de servlet podem interceptar solicitações e respostas dinamicamente para transformar ou usar as informações contidas na solicitação ou resposta. O filtro é uma classe Java que implementa a interface javax.servlet.Filter. A interface javax.servlet.Filter define três métodos:
public interface Filter {
default void init(FilterConfig filterConfig) throws ServletException {
}
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
default void destroy() {
}
}
Número de série | Método e Descrição |
---|---|
1 | O método doFilter conclui a operação de filtragem real.Quando o cliente solicita um URL que corresponda à configuração do filtro, o contêiner Servlet primeiro chama o método doFilter do filtro. Os usuários do FilterChain acessam os filtros subsequentes. |
2 | Quando o aplicativo da web init é iniciado, o servidor da web irá criar um objeto de instância de Filter, chamar seu método init, ler a configuração web.xml, completar a função de inicialização do objeto e preparar para a interceptação de solicitações subsequentes do usuário (objeto de filtro Ele será criado apenas uma vez, e o método init será executado apenas uma vez). Os desenvolvedores podem obter o objeto FilterConfig que representa as informações de configuração do filtro atual por meio dos parâmetros do método init. |
3 | O contêiner destroy Servlet chama esse método antes de destruir a instância do filtro, na qual os recursos ocupados pelo filtro do servlet são liberados. |
SpringBoot usa filtros
Define um filtro simples
@Slf4j
public class LogFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest)servletRequest;
log.info(req.getRequestURI());
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
Use FilterRegistrationBean para registrar filtros
@Configuration
public class LogFilterConfiguration {
@Bean
public FilterRegistrationBean registrationBean(){
FilterRegistrationBean registrationBean=new FilterRegistrationBean();
registrationBean.setFilter(new LogFilter());
//匹配的过滤器
registrationBean.addUrlPatterns("/*");
//过滤器名称
registrationBean.setName("logFilter");
//过滤器顺序
registrationBean.setOrder(1);
return registrationBean;
}
}
Use anotações Servlet3.0 para definir filtros
@WebFilter(urlPatterns = "/*",filterName = "authFiler")
@Slf4j
public class AuthFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
log.info("进行权限校验.........");
chain.doFilter(servletRequest,servletResponse);
}
}
A diferença entre os dois métodos:
- A anotação WebFilter não especifica o atributo da ordem de execução. A ordem de execução depende do nome do Filtro, que é classificado em ordem alfabética reversa de acordo com o nome da classe do Filtro (observe que não é o nome do filtro configurado)
- A prioridade do filtro especificado por @WebFilter é maior do que o filtro configurado por FilterRegistrationBean
- O método FilterRegistrationBean pode injetar beans no contêiner IOC SpringBoot
Interceptor
SpringBoot interceptor Interceptor similar Oriented Programming na seção e informar , através de nosso proxy dinâmico para um service()
método de adição de melhorias na função de notificação . Por exemplo, antes de o método ser executado no processo de inicialização , realizado após o método de execução de pós-processamento . Interceptor idéias e AOP
semelhantes, a diferença é o interceptor apenas Controller
no HTTP
pedido de interceptação.
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 {
}
}
Número de série | Método e Descrição |
---|---|
1 | O método preHandle é executado antes que o controlador receba a solicitação para processar a solicitação. O valor de retorno é booleano. Quando o valor de retorno é verdadeiro, os métodos postHandle () e afterCompletion () são executados; se retornar falso, a execução é interrompida. |
2 | postHandle é executado após o controlador processar a solicitação e antes de ModelAndView processá-la, e o resultado da resposta pode ser modificado. |
3 | afterCompletion é executado após DispatchServlet processar essa solicitação, ou seja, após ModelAndView ser gerado. |
Defina um interceptor simples
@Slf4j
public class LogHandler implements HandlerInterceptor {
private NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<>("StopWatch-StartTime");
public LogHandler() {
super();
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
long beginTime = System.currentTimeMillis();//1、开始时间
startTimeThreadLocal.set(beginTime);//线程绑定变量(该数据只有当前请求的线程可见)
return true;//继续流程
}
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
long endTime = System.currentTimeMillis();
long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量(开始时间)
long consumeTime = endTime - beginTime;
//3、消耗的时间
log.info(String.format("%s consume %d millis", request.getRequestURI(), consumeTime));
}
}
Registre o interceptor
@Configuration
public class HandlerConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogHandler());
}
}
A diferença entre filtro e interceptor
Número de série | A diferença |
---|---|
1 | O filtro é uma especificação de servlet, o escopo de uso são programas da web, os interceptores não estão limitados a programas da web, mas também podem ser usados em aplicativos e programas Swing |
2 | O filtro é definido na especificação do servlet e suportado pelo contêiner do servlet. O interceptor está no contêiner Spring e é apoiado pela estrutura Spring |
3 | O interceptor é um componente do Spring, que pode usar objetos no Spring, como objetos de serviço, fontes de dados, gerenciamento de transações e injeção no contêiner por meio de IOC, mas os filtros não podem |
4 | O filtro funciona antes e depois do servlet, e o interceptor pode se aprofundar no método antes e depois que a exceção é lançada. |
5 | Interceptadores são geralmente preferidos em projetos springboot |
Mil milhas começam com um único passo. Este é o décimo segundo artigo da série de tutoriais SpringBoot. Todos os códigos-fonte do projeto podem ser baixados em meu GitHub .