【问题标题】:Spring MVC: how to get a handler method for a requestSpring MVC:如何获取请求的处理程序方法
【发布时间】:2016-06-29 14:26:36
【问题描述】:

我正在尝试根据带有 Spring @RequestMapping 注释的方法上的注释来实现一些逻辑。

所以我的方法中有一个HttpServletRequest 实例,我想问spring“给我一个方法,将调用它来处理这个请求”,所以我可以使用反射API来询问我的注释是否存在或不是,所以我可以改变处理。

有没有什么简单的方法可以从 Spring MVC 中获取这些信息?

【问题讨论】:

  • 你想做的很糟糕。也就是说,与其自己调用该方法,不如在您的 servlet 中构建一个请求分派器并将请求分派到所需的 url。
  • 你做错了。相反,您应该使用 AOP,以便对使用您的注解进行注解的方法的所有调用都通过将执行处理的 Aspect。下面是一个示例,它拦截了对带有 @Authenticated 注释的方法的所有调用,如果当前用户未通过身份验证,则抛出异常:gist.github.com/jnizet/10ba6b0b6023e0d8ac228d2450d96193
  • “我的方法中有一个 HttpServletRequest 实例” 哪个方法?听起来您在方法 X 中,想知道方法 X 是否有注释 Y。
  • 目的很简单。自定义 CSRF 保护注释。 Spring 安全请求匹配器只为您提供 HttpRequest 对象,而不是目标,因此您需要以某种方式查找它......这可以通过 RequestMappingHandlerMapping 来完成(但这是第二个问题,因为 Spring 安全性严格绑定到 ROOT 上下文 -所以 RequestMappingHandlerMapping 对子网络上下文毫无用处......所以这就是为什么这个问题)

标签: java spring spring-mvc


【解决方案1】:

我想你有一个处理方法,比如:

@SomeAnnotation
@RequestMapping(...)
public Something doHandle(...) { ... }

并且您想为所有使用@SomeAnnotation 注释的处理程序方法添加一些预处理逻辑。代替您提出的方法,您可以实现 HandlerInterceptor 并将您的预处理逻辑放入 preHandle 方法中:

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

        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            SomeAnnotation someAnnotation = handlerMethod.getMethodAnnotation(SomeAnnotation.class);
            if (someAnnotation != null) {
                // Put your logic here
            }
        }

        return true; // return false if you want to abort the execution chain
    }
}

别忘了在你的网络配置中注册你的拦截器:

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

【讨论】:

  • 有没有办法将处理程序对象注入@ModelAttribute 方法?我不想为此创建拦截器。
  • @deantoni AFAIK 不,没有
  • 我同意这个解决方案,但你不必使用getMethodAnnotation和检查null,你可以使用hasMethodAnnotation(Class<A> annotationType),它返回直接的布尔值
【解决方案2】:

在@ali-dehgani 的回答的帮助下,我有了一个更灵活的实现,不需要注册拦截器。您确实需要传递绑定到该方法的请求对象。

private boolean isHandlerMethodAnnotated(HttpServletRequest request ) {
        WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
        Map<String, HandlerMapping> handlerMappingMap = BeanFactoryUtils.beansOfTypeIncludingAncestors(webApplicationContext, HandlerMapping.class, true, false);
        try {
            HandlerMapping handlerMapping = handlerMappingMap.get(RequestMappingHandlerMapping.class.getName());
            HandlerExecutionChain handlerExecutionChain = handlerMapping.getHandler(request);
            Object handler = handlerExecutionChain.getHandler();
            if(handler instanceof HandlerMethod){
                Annotation methodAnnotation = ((HandlerMethod) handler).getMethodAnnotation(MyAnnotation.class);
                return methodAnnotation!=null;
            }
        } catch (Exception e) {
            logger.warn(e);
        }
        return false;
    }

【讨论】:

    猜你喜欢
    • 2014-10-23
    • 2019-06-20
    • 2015-04-28
    • 2018-10-31
    • 2011-08-03
    • 1970-01-01
    • 1970-01-01
    • 2012-08-02
    • 1970-01-01
    相关资源
    最近更新 更多