Làm cách nào để thêm một lớp bộ lọc trong Spring Boot?


229

Tôi tự hỏi, nếu có bất kỳ chú thích nào cho một Filterlớp (cho các ứng dụng web) trong Spring Boot? Có lẽ @Filter?

Tôi muốn thêm một bộ lọc tùy chỉnh trong dự án của tôi.

Hướng dẫn tham khảo Spring Boot đã đề cập FilterRegistrationBean, nhưng tôi không chắc chắn cách sử dụng nó.


Lưu ý rằng Bộ lọc được thêm bằng @WebFilter không hoạt động như bộ lọc thực trong thông số Servlet. Nó sẽ là một loại đậu mùa xuân được gọi sau rất nhiều loại đậu mùa xuân khác và không giống như các bộ lọc thực sự trước bất kỳ mã servlet nào.
lrxw

bạn có thể cho tôi biết bạn yêu cầu chính xác. Nếu bạn muốn các lớp bộ lọc cho
ElementScan

Câu trả lời:


159

Nếu bạn muốn thiết lập bộ lọc của bên thứ ba, bạn có thể sử dụng FilterRegistrationBean. Ví dụ: tương đương với web.xml

<filter>
     <filter-name>SomeFilter</filter-name>
        <filter-class>com.somecompany.SomeFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>SomeFilter</filter-name>
    <url-pattern>/url/*</url-pattern>
    <init-param>
       <param-name>paramName</param-name>
       <param-value>paramValue</param-value>
    </init-param>
</filter-mapping>

Đây sẽ là hai hạt đậu trong @Configurationtập tin của bạn

@Bean
public FilterRegistrationBean someFilterRegistration() {

    FilterRegistrationBean registration = new FilterRegistrationBean();
    registration.setFilter(someFilter());
    registration.addUrlPatterns("/url/*");
    registration.addInitParameter("paramName", "paramValue");
    registration.setName("someFilter");
    registration.setOrder(1);
    return registration;
} 

public Filter someFilter() {
    return new SomeFilter();
}

Ở trên đã được thử nghiệm với spring-boot 1.2.3


1
Nếu tôi muốn thêm nhiều bộ lọc thì sao? @Opal
Verystrongjoe

8
Chỉ cần thêm một @Bean công cộng FilterRegistrationBean thêmFilterRegistration ()
Haim Raman

Làm thế nào để biết thứ tự các bộ lọc được áp dụng?
BeepDog

7
FilterRegistrationBean.setOrder
Haim Raman

Bạn không cần lọc đậu khi bạn gọi phương thức someFilter()trực tiếp.
WST

117

Dưới đây là một ví dụ về một phương pháp bao gồm bộ lọc tùy chỉnh trong ứng dụng Spring Boot MVC. Hãy chắc chắn bao gồm các gói trong quét thành phần:

package com.dearheart.gtsc.filters;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

@Component
public class XClacksOverhead implements Filter {

  public static final String X_CLACKS_OVERHEAD = "X-Clacks-Overhead";

  @Override
  public void doFilter(ServletRequest req, ServletResponse res,
      FilterChain chain) throws IOException, ServletException {

    HttpServletResponse response = (HttpServletResponse) res;
    response.setHeader(X_CLACKS_OVERHEAD, "GNU Terry Pratchett");
    chain.doFilter(req, res);
  }

  @Override
  public void destroy() {}

  @Override
  public void init(FilterConfig arg0) throws ServletException {}

}

4
Bộ lọc nên được đăng ký ở đâu đó?
gstackoverflow

1
Khi tôi thử cách tiếp cận đó, Bộ lọc được tạo như là bean và thậm chí được thêm vào lớp khác nhưng phương thức init () không chạy . Có lẽ, init () chỉ hoạt động trong đăng ký 'bình thường' không phải bởi container mùa xuân. Tôi nghĩ rằng, người ta có thể sử dụng PostConstruct thay vì init () nhưng tôi đã không thử điều đó vì tôi đã từ chối khai báo Bộ lọc là Spring bean.
Baurzhan

Điều gì về thứ tự bộ lọc sử dụng phương pháp này?
Pavel Vlasov

Làm cách nào chúng tôi có thể nhận được cơ thể RS từ ServletResponse?
user2602807

1
Một điều quan trọng cần lưu ý là tên của bean của bạn (dựa trên tên lớp của bạn) không nên giống với bean Spring. Ví dụ, bạn có thể bị cám dỗ để tạo một MetricsFilter, nhưng bean này sẽ bị lu mờ bởi bean chấp hành Spring cùng tên. Đã học được điều này một cách khó khăn ...
kinbiko

78

Không có chú thích đặc biệt nào để biểu thị bộ lọc servlet. Bạn chỉ cần khai báo một @Beanloại Filter(hoặc FilterRegistrationBean). Một ví dụ (thêm tiêu đề tùy chỉnh cho tất cả các phản hồi) nằm trong EndpointWebMvcAutoConfiguration của Boot ;

Nếu bạn chỉ khai báo Filternó sẽ được áp dụng cho tất cả các yêu cầu. Nếu bạn cũng thêm một, FilterRegistrationBeanbạn có thể chỉ định thêm các mô hình dịch vụ và url riêng lẻ để áp dụng.

Ghi chú:

Kể từ Spring Boot 1.4, FilterRegistrationBeankhông bị phản đối và chỉ đơn giản là chuyển các gói từ org.springframework.boot.context.embedded.FilterRegistrationBeansangorg.springframework.boot.web.servlet.FilterRegistrationBean


Bạn có phiền khi cho tôi biết làm thế nào để đưa mục tương ứng vào build.gradle không? Tôi đã thêm vào như sau, nhưng nó không được biên dịch: cung cấpCompile ('javax.servlet: servlet-api: 2.5') ('javax.servlet: jstl: 1.1.2')
janetsmith

2
Spring Boot sẽ không hoạt động với Servlet 2.5 và thực sự chưa có nhiều hỗ trợ cho JSP. Tôi không thực sự là một học sinh lớp, vì vậy tôi không biết bạn đang cố gắng làm gì. Có gì sai với "biên dịch"? Nó có hoạt động không nếu bạn chỉ phụ thuộc vào "spring-boot-starter-web"? (Tôi không nghĩ những câu hỏi này có liên quan đến câu hỏi ban đầu, vì vậy có lẽ bạn nên đăng lại với những câu hỏi mới?)
Dave Syer

Tôi đã thêm một bộ lọc bằng cách triển khai giao diện Bộ lọc, tuy nhiên Eclipse không thể tìm thấy giao diện. Vì vậy, tôi đang cố gắng tìm ra cách thêm nó vào classpath để biên dịch.
janetsmith

1
Vâng, tất nhiên bạn cần phải có Filtertrên đường dẫn của bạn. Thông thường tôi sẽ chỉ sử dụng spring-boot-starter-webđể kéo theo tất cả các phụ thuộc có liên quan (ví dụ ở đây ).
Dave Syer

Như các chi tiết phản hồi khác, bạn cũng có thể chú thích lớp Bộ lọc của mình với @Component và nó sẽ được đăng ký tự động (cho tất cả các URL).
Jakub Holý

72

Có ba cách để thêm bộ lọc của bạn,

  1. Chú thích bộ lọc của bạn với một trong các bản mẫu mùa xuân, chẳng hạn như @Component
  2. Đăng ký @Beanvới Filterloại trong mùa xuân@Configuration
  3. Đăng ký @Beanvới FilterRegistrationBeanloại trong mùa xuân@Configuration

# 1 hoặc # 2 sẽ làm nếu bạn muốn bộ lọc của mình áp dụng cho tất cả các yêu cầu mà không cần tùy chỉnh, hãy sử dụng # 3 nếu không. Bạn không cần chỉ định quét thành phần cho # 1 để hoạt động miễn là bạn đặt lớp bộ lọc của mình trong cùng hoặc gói phụ của SpringApplicationlớp. Đối với # 3, việc sử dụng cùng với # 2 chỉ cần thiết khi bạn muốn Spring quản lý lớp bộ lọc của mình, chẳng hạn như có phụ thuộc có dây tự động. Nó hoạt động tốt đối với tôi đối với bộ lọc mới mà không cần bất kỳ chế độ tự động / tiêm phụ thuộc nào.

Mặc dù kết hợp # 2 và # 3 hoạt động tốt, tôi đã ngạc nhiên khi nó không kết thúc với hai bộ lọc áp dụng hai lần. Tôi đoán là Spring kết hợp hai hạt như một khi nó gọi cùng một phương thức để tạo ra cả hai. Trong trường hợp bạn muốn sử dụng số 3 một mình với tính năng tự động, bạn có thể AutowireCapableBeanFactory. Sau đây là một ví dụ,

private @Autowired AutowireCapableBeanFactory beanFactory;

    @Bean
    public FilterRegistrationBean myFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        Filter myFilter = new MyFilter();
        beanFactory.autowireBean(myFilter);
        registration.setFilter(myFilter);
        registration.addUrlPatterns("/myfilterpath/*");
        return registration;
    }

Câu trả lời tuyệt vời. Cảm ơn bạn đã chi tiết tất cả các tùy chọn và cũng bao gồm cách tự động cho bạn Filtertrong khi sử dụngFilterRegistrationBean
sbk

Câu trả lời chính xác. Đây chính xác là những gì tôi đã làm
haykart

Điều này cũng được mô tả ở đây: baeldung.com/spring-boot-add-filter
Jakub Holý

31

CẬP NHẬT: 2017-12-16:

Có 2 cách đơn giản để thực hiện việc này trong Spring Boot 1.5.8.RELEASE, không cần XML.

Cách thứ nhất: Nếu bạn không có bất kỳ mẫu URL không gian nào, bạn có thể sử dụng @Component như thế này: (Mã đầy đủ và chi tiết có tại đây https://www.surasint.com/spring-boot-filter/ )

@Component
public class ExampleFilter implements Filter{
   ...
}

Cách thứ hai: Nếu bạn muốn sử dụng các mẫu url, bạn có thể sử dụng @WebFilter như thế này: (Mã đầy đủ và chi tiết có tại đây https://www.surasint.com/spring-boot-filter-urlpotype/ )

@WebFilter(urlPatterns = "/api/count")
public class ExampleFilter implements Filter{
 ...
}

Nhưng bạn cũng cần thêm chú thích @ServletComponentScan trong lớp @SpringBootApplication của bạn:

@ServletComponentScan
@SpringBootApplication
public class MyApplication extends SpringBootServletInitializer {
...
}

Lưu ý rằng @Component là chú thích của Spring, nhưng @WebFilter thì không. @WebFilter là chú thích 3 của Servlet.

Cả hai cách, bạn chỉ cần phụ thuộc Spring Boot cơ bản trong pom.xml (không cần jasper nhúng tomcat rõ ràng)

    <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.8.RELEASE</version>
    </parent>

    <groupId>com.surasint.example</groupId>
    <artifactId>spring-boot-04</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

CẢNH BÁO: Cách đầu tiên, nếu Bộ điều khiển trong Spring Boot trở lại tệp tin JSP, yêu cầu sẽ chuyển qua bộ lọc hai lần.

Trong khi, theo cách thứ hai, yêu cầu sẽ chỉ vượt qua bộ lọc một lần.

Tôi thích cách thứ hai vì nó giống với hành vi mặc định hơn trong đặc tả Servlet ( https://docs.oracle.com/cd/E19879-01/819-3669/6n5sg7b0b/index.html )

Bạn có thể xem thêm nhật ký kiểm tra tại đây https://www.surasint.com/spring-boot-webfilter-instead-of-component/


Tôi đã thấy Filtergiao diện được gọi nhiều lần trong khi khởi chạy applicationContext. Có cách nào để thực hiện nó chỉ một lần?
Pra_A

@PAA bạn có nghĩa là từ ví dụ của tôi?
Surasin Tancharoen

20

Đây là một ví dụ về lớp Bộ lọc tùy chỉnh của tôi:

package com.dawson.controller.filter;

import org.springframework.stereotype.Component;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;


@Component
public class DawsonApiFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        if (req.getHeader("x-dawson-nonce") == null || req.getHeader("x-dawson-signature") == null) {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setContentType("application/json");
            httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST, "Required headers not specified in the request");
            return;
        }
        chain.doFilter(request, response);
    }
}

Và tôi đã thêm nó vào cấu hình khởi động Spring bằng cách thêm nó vào lớp Cấu hình như sau:

package com.dawson.configuration;

import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
import com.dawson.controller.filter.DawsonApiFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

@SpringBootApplication
public class ApplicationConfiguration {
    @Bean
    public FilterRegistrationBean dawsonApiFilter() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(new DawsonApiFilter());
// In case you want the filter to apply to specific URL patterns only
        registration.addUrlPatterns("/dawson/*");
        return registration;
    }
}

14

Từ tài liệu mùa xuân,

Các thùng chứa servlet nhúng - Thêm một Servlet, Bộ lọc hoặc Trình nghe vào một ứng dụng

Để thêm một Servlet, Filter hoặc Servlet * Listener cung cấp định nghĩa @Bean cho nó.

Ví dụ:

@Bean
public Filter compressFilter() {
    CompressingFilter compressFilter = new CompressingFilter();
    return compressFilter;
}

Thêm @Beancấu hình này vào @Configurationlớp của bạn và bộ lọc sẽ được đăng ký khi khởi động.

Ngoài ra, bạn có thể thêm Servlets, Bộ lọc và Trình nghe bằng cách quét đường dẫn lớp,

Các lớp chú thích @WebServlet, @WebFilter và @WebListener có thể được đăng ký tự động với một thùng chứa servlet nhúng bằng cách chú thích một lớp @Configuration với @ServletComponentScan và chỉ định (các) gói chứa các thành phần mà bạn muốn đăng ký. Theo mặc định, @ServletComponentScan sẽ quét từ gói của lớp chú thích.



7

Nếu bạn sử dụng Spring Boot + Spring Security, bạn có thể làm điều đó trong cấu hình bảo mật.

Trong ví dụ dưới đây, tôi đang thêm bộ lọc tùy chỉnh trước UsernamePasswordAuthenticationFilter (xem tất cả các bộ lọc Spring Security mặc định và thứ tự của chúng ).

@EnableWebSecurity
class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired FilterDependency filterDependency;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .addFilterBefore(
                new MyFilter(filterDependency),
                UsernamePasswordAuthenticationFilter.class);
    }
}

Và lớp lọc

class MyFilter extends OncePerRequestFilter  {
    private final FilterDependency filterDependency;

    public MyFilter(FilterDependency filterDependency) {
        this.filterDependency = filterDependency;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
        HttpServletResponse response,
        FilterChain filterChain)
        throws ServletException, IOException {
       // filter
       filterChain.doFilter(request, response);
    }
}

5

Sử dụng chú thích @WebFilter, nó có thể được thực hiện như sau:

@WebFilter(urlPatterns = {"/*" })
public class AuthenticationFilter implements Filter{

    private static Logger logger = Logger.getLogger(AuthenticationFilter.class);

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest arg0, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

         logger.info("checking client id in filter");
        HttpServletRequest request = (HttpServletRequest) arg0;
        String clientId = request.getHeader("clientId");
        if (StringUtils.isNotEmpty(clientId)) {
            chain.doFilter(request, response);
        } else {
            logger.error("client id missing.");
        }
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub

    }

}

3
Đồng thời thêm @ServletComponentScan
Justas

5

Chúng tôi có khoảng bốn tùy chọn khác nhau để đăng ký bộ lọc bằng Spring .

Đầu tiên, chúng ta có thể tạo Bộ lọc triển khai đậu mùa xuân hoặc mở rộng httpFilter :

@Component
public class MyFilter extends HttpFilter {

    @Override
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) 
        throws IOException, ServletException {
        // Implementation details...

        chain.doFilter(request, response);
    }
}

Thứ hai, chúng ta có thể tạo một bean Spring mở rộng GenericFilterBean :

@Component
public class MyFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
  throws IOException, ServletException {
    //Implementation details...

        chain.doFilter(currentRequest, servletResponse);
    }
}

Ngoài ra, chúng ta có thể sử dụng lớp FilterRegistrationBean :

@Configuration
public class FilterConfiguration {

    private final MyFilter myFilter;

    @Autowired
    public FilterConfiguration(MyFilter myFilter) {
        this.myFilter = myFilter;
    }

    @Bean
    public FilterRegistrationBean<MyFilter> myFilterRegistration() {
        FilterRegistrationBean<DateLoggingFilter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(myFilter);
        filterRegistrationBean.setUrlPatterns(Collections.singletonList("/*"));
        filterRegistrationBean.setDispatcherTypes(DispatcherType.REQUEST);
        filterRegistrationBean.setOrder(Ordered.LOWEST_PRECEDENCE - 1);
        return filterRegistrationBean;
    }
}

Và cuối cùng chúng ta có thể sử dụng @WebFilter chú thích với @ServletComponentScan :

@WebFilter(urlPatterns = "/*", dispatcherTypes = {DispatcherType.REQUEST})
public class MyFilter extends HttpFilter {

    @Override
    protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
  throws IOException, ServletException {
        // Implementation details...

        chain.doFilter(request, response);
    }
}

Nên sử dụng bộ lọc nào và tại sao?
Pra_A

3

Đó là một lời khuyên hơn là trả lời, nhưng nếu bạn đang sử dụng Spring MVC trong ứng dụng web của mình thì ý tưởng tốt là sử dụng Spring HandlerInterceptor thay vì Filter

Nó có thể thực hiện cùng một công việc, nhưng cũng có thể - Có thể hoạt động với ModelAndView - Các phương thức của nó có thể được gọi trước và sau khi xử lý yêu cầu hoặc sau khi hoàn thành yêu cầu.
- Nó có thể dễ dàng kiểm tra

1 Triển khai giao diện HandlerInterceptor và thêm chú thích @Component vào lớp của bạn

@Component
public class SecurityInterceptor implements HandlerInterceptor {

    private static Logger log = LoggerFactory.getLogger(SecurityInterceptor.class);

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        request.getSession(true);
        if(isLoggedIn(request))
            return true;

        response.getWriter().write("{\"loggedIn\":false}");
        return false;
    }

    private boolean isLoggedIn(HttpServletRequest request) {
        try {
            UserSession userSession = (UserSession) request.getSession(true).getAttribute("userSession");
            return userSession != null && userSession.isLoggedIn();
        } catch(IllegalStateException ex) {
            return false;
        }
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {

    }
}

2 Định cấu hình Thiết bị đánh chặn của bạn

@Configuration
public class WebConfig implements WebMvcConfigurer {

    private HandlerInterceptor securityInterceptor;

    @Autowired
    public void setSecurityInterceptor(HandlerInterceptor securityInterceptor) {
        this.securityInterceptor = securityInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(securityInterceptor).addPathPatterns("/**").excludePathPatterns("/login", "/logout");
    }

}

Đơn giản và thanh lịch! Cảm ơn
MrMins

3

Bộ lọc này cũng sẽ giúp bạn cho phép truy cập nguồn gốc chéo

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCORSFilter implements Filter {

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

            HttpServletResponse response = (HttpServletResponse) res;
            HttpServletRequest request = (HttpServletRequest) req;
            response.setHeader("Access-Control-Allow-Origin", "*");
            response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
            response.setHeader("Access-Control-Max-Age", "20000");
            response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, Content-Type, Authorization, credential, X-XSRF-TOKEN");

            if("OPTIONS".equalsIgnoreCase(request.getMethod())) {
                response.setStatus(HttpServletResponse.SC_OK);
            } else {
                chain.doFilter(req, res);
            }
    }


    public void destroy() {}

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub

    }

}

2

Bạn có thể sử dụng @WebFilter javax.servlet.annotation.WebFilter trên một lớp thực hiện javax.servlet.Filter

@WebFilter(urlPatterns = "/*")
public class MyFilter implements Filter {}

Sau đó sử dụng @ServletComponentScan để đăng ký


2

Tôi đã thấy rất nhiều câu trả lời ở đây nhưng tôi đã không thử bất kỳ câu trả lời nào. Tôi vừa tạo bộ lọc như trong đoạn mã sau.

import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(urlPatterns = "/Admin")
@Configuration
public class AdminFilter implements Filter{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse  servletResponse, FilterChain filterChain) throws IOException, ServletException      {
    System.out.println("happened");

    }

    @Override
    public void destroy() {

    }
}

Và đã bỏ qua ứng dụng Spring Boot còn lại.


2

Bạn cần 2 điều chính: - Thêm vào @ServletComponentScanLớp chính của bạn - bạn có thể thêm một gói có tên bộ lọc bên trong nó, bạn tạo một FilterLớp có các mục sau:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class RequestFilter implements Filter {

 // whatever field you have

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
    HttpServletResponse response = (HttpServletResponse) res;
    HttpServletRequest request = (HttpServletRequest) req;

 // whatever implementation you want

        try {
            chain.doFilter(req, res);
        } catch(Exception e) {
            e.printStackTrace();
        }

}

public void init(FilterConfig filterConfig) {}

public void destroy() {}
}

1

bạn cũng có thể tạo bộ lọc bằng cách sử dụng @WebFilter và thực hiện Bộ lọc, nó sẽ làm được.

 @Configuration
        public class AppInConfig 
        {
        @Bean
      @Order(1)
      public FilterRegistrationBean aiFilterRegistration() {
            FilterRegistrationBean registration = new FilterRegistrationBean();
            registration.setFilter(new TrackingFilter());
            registration.addUrlPatterns("/**");
            registration.setOrder(1);
            return registration;
        } 
    @Bean(name = "TrackingFilter")
        public Filter TrackingFilter() {
            return new TrackingFilter();
        }   
    }

1

Các bộ lọc như tên đề xuất được sử dụng để thực hiện lọc theo yêu cầu đối với tài nguyên hoặc phản hồi từ tài nguyên hoặc cả hai. Spring Boot cung cấp một vài tùy chọn để đăng ký các bộ lọc tùy chỉnh trong ứng dụng Spring Boot. Hãy xem xét các lựa chọn khác nhau.

1. Xác định bộ lọc khởi động mùa xuân và thứ tự gọi

Triển khai giao diện Bộ lọc để tạo bộ lọc mới trong Spring Boot.

@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CustomFilter implements Filter {

 private static final Logger LOGGER = LoggerFactory.getLogger(CustomFilter.class);

 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
  LOGGER.info("########## Initiating Custom filter ##########");
 }

 @Override
 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

  HttpServletRequest request = (HttpServletRequest) servletRequest;
  HttpServletResponse response = (HttpServletResponse) servletResponse;

  LOGGER.info("Logging Request  {} : {}", request.getMethod(), request.getRequestURI());

  //call next filter in the filter chain
  filterChain.doFilter(request, response);

  LOGGER.info("Logging Response :{}", response.getContentType());
 }

 @Override
 public void destroy() {
  // TODO: 7/4/18
 }
}

Hãy nhanh chóng xem xét một số điểm quan trọng trong đoạn mã trên

  • Bộ lọc được đăng ký bởi chú thích @Component .
  • Để kích hoạt các bộ lọc theo đúng thứ tự, chúng tôi cần sử dụng chú thích @Order .

    @Component
    @Order(1)
    public class CustomFirstFilter implements Filter {
    
    }
    @Component
    @Order(2)
    public class CustomSecondFilter implements Filter {
    
    }

Trong đoạn mã trên, CustomFirstFilter sẽ chạy trước CustomSecondFilter.

Con số càng thấp, độ ưu tiên càng cao

2. Mẫu URL

Nếu ánh xạ dựa trên quy ước không đủ linh hoạt, chúng ta có thể sử dụng FilterRegistrationBean để kiểm soát hoàn toàn ứng dụng. Ở đây, không sử dụng chú thích @Component cho lớp bộ lọc mà đăng ký bộ lọc bằng FilterRegistrationBean .

 public class CustomURLFilter implements Filter {

 private static final Logger LOGGER = LoggerFactory.getLogger(CustomURLFilter.class);

 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
  LOGGER.info("########## Initiating CustomURLFilter filter ##########");
 }

 @Override
 public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

  HttpServletRequest request = (HttpServletRequest) servletRequest;
  HttpServletResponse response = (HttpServletResponse) servletResponse;

  LOGGER.info("This Filter is only called when request is mapped for /customer resource");

  //call next filter in the filter chain
  filterChain.doFilter(request, response);
 }

 @Override
 public void destroy() {

 }
}

Đăng ký Bộ lọc tùy chỉnh bằng FilterRegistrationBean .

@Configuration
public class AppConfig {

 @Bean
 public FilterRegistrationBean < CustomURLFilter > filterRegistrationBean() {
  FilterRegistrationBean < CustomURLFilter > registrationBean = new FilterRegistrationBean();
  CustomURLFilter customURLFilter = new CustomURLFilter();

  registrationBean.setFilter(customURLFilter);
  registrationBean.addUrlPatterns("/greeting/*");
  registrationBean.setOrder(2); //set precedence
  return registrationBean;
 }
}

1

    @WebFilter(urlPatterns="/*")
    public class XSSFilter implements Filter {

        private static final org.apache.log4j.Logger LOGGER = LogManager.getLogger(XSSFilter.class);

        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            LOGGER.info("Initiating XSSFilter... ");

        }

        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
            HttpServletRequest req = (HttpServletRequest) request;
            HttpRequestWrapper requestWrapper = new HttpRequestWrapper(req);
            chain.doFilter(requestWrapper, response);
        }

        @Override
        public void destroy() {
            LOGGER.info("Destroying XSSFilter... ");
        }

    }

Bạn cần triển khai Bộ lọc và cần được chú thích bằng @WebFilter (urlPotypes = "/ *")

Và trong lớp Ứng dụng hoặc Cấu hình, bạn cần thêm @ServletComponentScan Bằng cách này, bộ lọc của bạn sẽ được đăng ký.


Điều này @WebFilterchỉ kể từ Servlet 3.0. Vì vậy, nó có thể không hoạt động đúng trong 2,5
ha9u63ar

1

Bước 1: Tạo thành phần bộ lọc bằng cách thực hiện giao diện Bộ lọc.

@Component
public class PerformanceFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {

            ......
            ......
    }

}

Bước 2: Đặt bộ lọc này cho các mẫu uri bằng FilterRegistrationBean.

@Configuration
public class FilterConfig {
    @Bean
    public FilterRegistrationBean<PerformanceFilter> perfFilter() {
        FilterRegistrationBean<PerformanceFilter> registration = new FilterRegistrationBean<>();
        registration.setFilter(new PerformanceFilter());
        registration.addUrlPatterns("/*");
        return registration;
    }
}

Bạn có thể tham khảo liên kết này cho ứng dụng hoàn chỉnh.


0

Đầu tiên, thêm @ServletComponentScanvào lớp SpringBootApplication của bạn.

@ServletComponentScan
public class Application {

Thứ hai, tạo tệp bộ lọc mở rộng Bộ lọc hoặc lớp bộ lọc của bên thứ ba và thêm @WebFiltervào tệp này như sau:

@Order(1) //optional
@WebFilter(filterName = "XXXFilter", urlPatterns = "/*",
    dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD},
    initParams = {@WebInitParam(name = "confPath", value = "classpath:/xxx.xml")})
public class XXXFilter extends Filter{

0

Tôi thấy câu trả lời của @Vasily Komarov. Cách tiếp cận tương tự, nhưng sử dụng lớp HandlerInterceptorAd CHƯƠNG trừu tượng thay vì sử dụng HandlerInterceptor .

Đây là một ví dụ...

@Component
public class CustomInterceptor extends HandlerInterceptorAdapter {
   @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
    }
}

@Configuration
public class InterceptorConfig extends WebMvcConfigurerAdapter {

    @Autowired
    private CustomInterceptor customInterceptor ;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(customInterceptor );
    }

}

0

Như bạn đã biết, Spring Boot là một cách tuyệt vời để phát triển WebApp hoặc StandAppApp với cấu hình tối thiểu và Thiết lập có ý kiến.

Đây là cách tôi đã đạt được Phát triển Bộ lọc Web trong ứng dụng Spring Boot

Thông số kỹ thuật SpringBootApp của tôi: -

Phiên bản Spring Boot: 2.0.4.RELEASE
Phiên bản Java: 8.0
Đặc điểm kỹ thuật của Servlet: Servlet 3.0 (Bắt buộc và quan trọng)

Tôi đã khai báo Bộ lọc Web của mình theo cách sau, tuân thủ Thông số kỹ thuật của Servlet 3.0

nhập mô tả hình ảnh ở đây Đây là cách lập trình để xác định Bộ lọc thay thế cho các định nghĩa dựa trên web.xml.

Chú thích "@Webfilter" sẽ được xử lý bởi bộ chứa trong quá trình triển khai, lớp Bộ lọc được tìm thấy sẽ được tạo theo cấu hình và được áp dụng cho các mẫu URL, javax.servlet.Servlets và javax.servlet.DispatcherTypes.

Để tránh hoàn toàn Web.xml và để đạt được WebApp "Có thể triển khai": -

Để triển khai Ứng dụng khởi động mùa xuân dưới dạng "WAR truyền thống", lớp ứng dụng nên mở rộng SpringBootServletInitializer.

LƯU Ý :: SpringBootServletInitializer là một "Triển khai lập trình" của tệp web.xml có tham chiếu đến các đặc tả của Servlet 3.0+, yêu cầu triển khai WebApplicationInitializer.

Do đó, SpringBootApplication không yêu cầu "web.xml" làm lớp Ứng dụng của nó (sau khi mở rộng SpringBootServletInitializer) quét cho
- @WebFilter,
- @WebListener và
- @WebServlet.

Chú thích @ServletComponentScan

Chú thích này cho phép quét các gói cơ sở cho các thành phần web được chú thích bằng @WebFilter, @WebListener và @WebServlet.

Do thực tế là các thùng chứa nhúng không hỗ trợ các chú thích @WebServlet, @WebFilter và @WebListener, Spring Boot, phụ thuộc rất nhiều vào các thùng chứa nhúng, đã giới thiệu chú thích mới này @ServletComponentScan để hỗ trợ một số lọ phụ thuộc sử dụng 3 chú thích này.

Quét chỉ được thực hiện khi sử dụng bộ chứa Servlet nhúng.

Sau đây là Định nghĩa lớp ứng dụng khởi động mùa xuân của tôi: -

nhập mô tả hình ảnh ở đây

Trình khởi tạo Servlet tùy chỉnh: -

Ở đây: Tôi đã định nghĩa một Lớp tùy chỉnh: "ServletInitializer" mở rộng Lớp: SpringBootServletInitializer.

Như đã giải thích trước đó, SpringBootServletInitializer chịu trách nhiệm quét các chú thích: -
- @WebFilter,
- @WebListener và
- @WebServlet.

Và do đó, lớp ứng dụng Spring Boot nên

  • Hoặc mở rộng lớp: SpringBootServletInitializer HOẶC
  • mở rộng Lớp tùy chỉnh mở rộng lớp: SpringBootServletInitializer

nhập mô tả hình ảnh ở đây


-6

Các bộ lọc chủ yếu được sử dụng trong các tệp logger, nó thay đổi tùy theo logger mà bạn sử dụng trong dự án Lemme giải thích cho log4j2:

<Filters>
                <!-- It prevents error -->
                <ThresholdFilter level="error" onMatch="DENY" onMismatch="NEUTRAL"/>
                <!-- It prevents debug -->
                <ThresholdFilter level="debug" onMatch="DENY" onMismatch="NEUTRAL" />
                <!-- It allows all levels except debug/trace -->
                <ThresholdFilter level="info" onMatch="ACCEPT" onMismatch="DENY" /> 
            </Filters>

Các bộ lọc được sử dụng để hạn chế dữ liệu và tôi đã sử dụng bộ lọc ngưỡng hơn nữa để hạn chế các mức dữ liệu trong luồng tôi đã đề cập đến các mức có thể bị hạn chế ở đó. Để biết thêm thông tin của bạn, hãy xem thứ tự cấp độ của log4j2 - Cấp độ Log4J: ALL> TRACE> DEBUG> INFO> WARN> ERROR> FATAL> OFF


FilterRegistrationBeannhư đã đề cập trong câu hỏi dành cho javax.servlet.Filter, câu trả lời này nói vềorg.apache.logging.log4j.core.Filter
Steve Buzonas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.