【问题标题】:Spring mvc filter for some controllers一些控制器的 Spring mvc 过滤器
【发布时间】:2016-02-25 08:28:00
【问题描述】:

我需要处理到达某些 Spring 控制器的所有请求,以获取一些请求者信息或抛出安全过滤器等异常。

我想知道 Spring 中是否有一些内置的东西,比如控制器的过滤器(我不是所有控制器都需要它,而只需要某个人)。 我不想通过 url 请求应用此过滤器,而是使用类/方法扩展或注释。

这是我的实际解决方案:

@Controller
public class MyFilteredController extends FilterController {

    @RequestMapping("/filtered")
    public void test1(HttpServletRequest req){
        InfoBean infobean=filter(req);
        //... controller job
    }

}

使用过滤器方法扩展类的控制器。

public abstract FilterController{
    protected InfoBean filter(HttpServletRequest req){
        //... filter job
        return infobean;
    }
}

【问题讨论】:

    标签: java spring spring-mvc controller


    【解决方案1】:

    我不想通过 url 请求应用此过滤器,而是使用 类/方法扩展或注释

    您可以为此目的注册HandlerInterceptor。例如,您可以使用以下代码将过滤器应用于所有带有 SomeAnnotation 注释的处理程序方法:

    public class CustomHandlerIntercepter extends HandlerInterceptorAdapter {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            if (handler instanceof HandlerMethod) {
                HandlerMethod handlerMethod = (HandlerMethod) handler;
    
                SomeAnnotation annotation = handlerMethod.getMethodAnnotation(SomeAnnotation.class);
                if (annotation != null) {
                    // do stuff
                }
            }
            return true;
        }
    }
    

    另外,你应该在WebConfig注册你的拦截器:

    @EnableWebMvc
    @Configuration
    public class WebConfig extends WebMvcConfigurerAdapter {
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new CustomHandlerIntercepter());
        }
    }
    

    您可以在spring reference documentation 中阅读有关拦截器的更多信息。

    【讨论】:

    • "//do stuff" 也表示像@Services这样链接spring bean?
    • 如果你想访问spring托管的组件和服务,你应该把这个拦截器变成Component和Autowire它们成为拦截器。
    • 好的,很好!最后一件事,我可以访问 handlerMethod 参数吗?
    【解决方案2】:

    看看SpringSandwichhttp://springsandwich.com/

    它允许您将过滤器(实际上是 Spring 拦截器)直接设置为控制器注释。与普通 servlet 过滤器不同,您还可以完全访问 Spring 上下文。

    披露:我是这个框架的作者 :)

    【讨论】:

    • SpringSandwich 似乎比其他方法更好。代码更有条理。谢谢。我试试看。
    • 抱歉,我该如何访问三明治过滤器类中的@RequestParam 属性
    • @HeisenBerg req.getParameter("my-param") 怎么样
    【解决方案3】:

    【讨论】:

      【解决方案4】:

      使用 SpringDispatcherServlet 的一切都是基于 URL 的,我认为你不能通过控制器来做到这一点。

      您将需要使用过滤器,请查看此处的 API https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/filter/package-summary.html 您可能想要使用 OncePerRequestFilter。

      public class MyFilter extends OncePerRequestFilter{
      
          @Override
          protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
                  throws ServletException, IOException {
              // TODO Auto-generated method stub
      
          }
      
      }
      

      然后您需要在 web.xml 中添加过滤器

          <filter>
              <filter-name>requestFilter</filter-name>
              <filter-class>com.greg.MyFilter</filter-class>
          </filter>
          <filter-mapping>
              <filter-name>errorHandlerFilter</filter-name>
              <url-pattern>/*</url-pattern>
          </filter-mapping>
      

      现在是 hacky 一点,如果你想在这里获取 Spring bean,你可以创建一个带有静态的 Bridge 类。

      public class Bridge {
      
          private static PaymentService paymentService;
      
          public PaymentService getPaymentService() {
              return paymentService;
          }
      
          public void setPaymentService(PaymentService paymentService) {
              Bridge.paymentService = paymentService;
          }
      
      }
      

      如果你想在这个类中注入一些spring bean

      <bean id="paymentService" class="net.isban.example.service.PaymentService" />
      
          <bean class="net.isban.example.util.Bridge">
              <property name="paymentService" ref="paymentService" />
          </bean>
      

      然后在您的过滤器中(不是弹簧类)。

      PaymentService paymentService = new Bridge().getPaymentService();
      

      很高兴有人向我展示了一种不那么老套的方法。

      【讨论】:

      • 我不能使用这样的过滤器,因为我需要一些 Spring 上下文对象,例如 @Service、@Repository 等。这就是为什么我想要在控制器中使用过滤器。
      • @Tobia 请阅读我的回答,我已经专门向您展示了如何通过 Bridge 类将 bean 放入您的过滤器,该类从非弹簧(过滤器)连接到弹簧容器(@Service 等) .
      猜你喜欢
      • 2023-04-02
      • 2017-09-23
      • 1970-01-01
      • 2017-09-21
      • 2023-03-26
      • 2016-02-08
      • 1970-01-01
      • 2018-06-14
      • 1970-01-01
      相关资源
      最近更新 更多