[java] Spring Boot에서 필터 클래스를 추가하는 방법은 무엇입니까?

Filter스프링 부트에 클래스 (웹 애플리케이션 용)에 대한 주석이 있는지 궁금합니다 . 아마도 @Filter?

프로젝트에 사용자 정의 필터를 추가하고 싶습니다.

Spring Boot Reference Guide 에 대해 언급
FilterRegistrationBean했지만 사용법을 잘 모르겠습니다.



답변

타사 필터를 설정하려면을 사용할 수 있습니다 FilterRegistrationBean. 예를 들어 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>

이것들은 @Configuration파일 의 두 개의 콩이 될 것입니다

@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();
}

위의 내용은 spring-boot 1.2.3으로 테스트되었습니다.


답변

다음은 Spring Boot MVC 애플리케이션에 사용자 정의 필터를 포함시키는 한 가지 방법의 예입니다. 구성 요소 스캔에 패키지를 포함시켜야합니다.

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 {}

}


답변

서블릿 필터를 나타내는 특수 주석이 없습니다. @Bean유형 Filter(또는 FilterRegistrationBean)을 선언하면 됩니다. 모든 응답에 사용자 정의 헤더를 추가하는 예는 Boot의 자체 EndpointWebMvcAutoConfiguration ;

선언 만하면 Filter모든 요청에 ​​적용됩니다. 당신은 또한을 추가하는 경우 FilterRegistrationBean에는 추가로 개별 서블릿 및 적용 할 URL 패턴을 지정할 수 있습니다.

노트 :

Spring Boot 1.4부터 FilterRegistrationBean 부터는 더 이상 사용되지 않으며 단순히 패키지를 org.springframework.boot.context.embedded.FilterRegistrationBean에서org.springframework.boot.web.servlet.FilterRegistrationBean


답변

필터를 추가하는 방법에는 세 가지가 있습니다.

  1. 다음과 같은 Spring 스테레오 타입 중 하나로 필터에 주석을 답니다. @Component
  2. 레지스터 A @BeanFilter봄 유형@Configuration
  3. 레지스터 A @BeanFilterRegistrationBean봄 유형@Configuration

필터를 사용자 정의하지 않고 모든 요청에 ​​적용하려면 # 1 또는 # 2가 수행하고 그렇지 않으면 # 3을 사용하십시오. 필터 클래스를 패키지 클래스와 동일하거나 하위 패키지에 배치하는 한 # 1의 구성 요소 스캔을 지정하지 않아도됩니다.SpringApplication . # 3의 경우 # 2와 함께 사용하면 Spring에서 필터 클래스를 자동 유선 종속성과 같은 필터 클래스로 관리하려는 경우에만 필요합니다. 의존성 자동 배선 / 주입이 필요없는 새로운 필터를 사용하는 것이 좋습니다.

# 2와 # 3을 결합해도 효과가 있지만 두 개의 필터를 두 번 적용하지 않는 것에 놀랐습니다. 내 생각에 Spring은 두 개의 Bean을 생성하기 위해 동일한 메소드를 호출 할 때 두 개의 Bean을 하나로 결합합니다. 인증과 함께 # 3 만 사용하려는 경우을 수행 할 수 있습니다 AutowireCapableBeanFactory. 다음은 예입니다.

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;
    }


답변

업데이트 : 2017-12-16 :

Spring Boot 1.5.8.RELEASE에는 XML이 필요없는 간단한 두 가지 방법이 있습니다.

첫 번째 방법 :
Spacific URL 패턴이없는 경우 @Component를 다음과 같이 사용할 수 있습니다 (전체 코드 및 세부 정보는 https://www.surasint.com/spring-boot-filter/ )

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

두 번째 방법 :
URL 패턴을 사용하려면 다음과 같이 @WebFilter를 사용할 수 있습니다 (전체 코드 및 세부 정보는 https://www.surasint.com/spring-boot-filter-urlpattern/ )

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

그러나 @SpringBootApplication 클래스에 @ServletComponentScan 주석을 추가해야합니다.

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

@Component는 Spring의 주석이지만 @WebFilter는 주석이 아닙니다. @WebFilter는 서블릿 3 주석입니다.

두 가지 방법 모두 pom.xml에 기본 스프링 부트 종속성이 필요합니다 (명백한 바람둥이 내장 재스퍼가 필요 없음)

    <?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>

경고: 첫 번째 방법은 Spring Boot의 Controller가 JSP 파일로 돌아 가면 요청이 필터를 두 번 전달하는 것입니다.

두 번째 방법으로 요청은 필터를 한 번만 전달합니다.

서블릿 사양의 기본 동작과 더 비슷하기 때문에 두 번째 방법을 선호합니다 ( https://docs.oracle.com/cd/E19879-01/819-3669/6n5sg7b0b/index.html )

https://www.surasint.com/spring-boot-webfilter-instead-of-component/에서 더 많은 테스트 로그를 볼 수 있습니다


답변

다음은 내 사용자 정의 필터 클래스의 예입니다.

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);
    }
}

그리고 다음과 같이 Configuration 클래스에 추가하여 Spring 부팅 구성에 추가했습니다.

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;
    }
}


답변

Spring 문서에서

임베디드 서블릿 컨테이너-애플리케이션에 서블릿, 필터 또는 리스너 추가

서블릿, 필터 또는 서블릿 * Listener를 추가하려면 @Bean
정의를 제공하십시오.

예 :

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

@Bean구성을 @Configuration클래스에 추가하면 시작시 필터가 등록됩니다.

또한 클래스 경로 스캐닝을 사용하여 서블릿, 필터 및 리스너를 추가 할 수 있습니다.

@WebServlet, @WebFilter 및 @WebListener 어노테이션이있는 클래스는 @ServletComponentScan으로 @Configuration 클래스에 주석을 달고 등록하려는 컴포넌트가 포함 된 패키지를 지정하여 임베디드 서블릿 컨테이너에 자동으로 등록 할 수 있습니다. 기본적으로 @ServletComponentScan은 주석이 달린 클래스의 패키지에서 스캔합니다.