【问题标题】:HandlerMethod given a HttpRequest?HandlerMethod 给定一个 HttpRequest?
【发布时间】:2011-05-06 06:44:53
【问题描述】:

我有一个拦截器,我想在其中基于控制器方法(不在控制器类)上的注释执行一些拦截逻辑。假设只想限制某些用户对该控制器方法的访问。有没有办法在HandlerInterceptor中获取Handler方法(是的不是handler类)?

【问题讨论】:

    标签: spring-mvc


    【解决方案1】:

    恐怕不会。您必须将所需的方法分组到一个(或几个)类中,并根据类而不是方法进行检查。

    我猜你可以自己解析注解并匹配路径,或者尝试看看 spring 在它的类中做了什么,但这会更复杂和容易出错。

    你可以试试(但我没用过,所以我不知道它是否有效)你方法上的@Interceptors注解(saw it here

    【讨论】:

    • 是的,我想你是对的。我们有一个新要求,需要大量重构才能将它们分组:(
    • 博文链接使用类级别注释,这不是问题。如果我尝试解析注释并匹配路径,那将是一团糟。还必须考虑路径变量,控制器的 url 前缀。
    • 可以,但是方法也支持注解
    【解决方案2】:

    您现在可以在 Spring 3.1 中执行此操作,如下所示:

    public class ApiSecurityInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            HandlerMethod method = (HandlerMethod) handler;
            Api methodAnnotation = method.getMethodAnnotation(Api.class);
    
            if (methodAnnotation != null) {
                // this method is an @Api, we check the credentials
                // you can do other things with annotation parameters at this point too
            }
        }
    }
    

    然后映射到servlet-config.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    ...
    <mvc:interceptors>
        <bean class="com.orderpipe.prototype.server.web.interceptors.ApiSecurityInterceptor"/>
    </mvc:interceptors>
    

    然后在你的实际控制器中:

    @Controller
    @RequestMapping(value = "/api-service")
    public class AccountApiController {
    
        @Api(type=CredentialType.OAUTH)
        @RequestMapping(value="get", method = RequestMethod.GET)
        public String get(Model model) {
            // secured method via oauth, for example
            // in a simpler example, you'd not have the parameter for credential type.
        }
    
    }
    

    我使用它来实现特殊的 servlet 路径,这些路径实现了与普通应用程序不同的安全机制,例如 /api 使用 oAuth 凭据。

    【讨论】:

    • 感谢您的回答,但是您是否测试过您的 Inteceptor? java.lang.ClassCastException: com.test.web.SomeController cannot be cast to org.springframework.web.method.HandlerMethod at com.test.web.interceptor.SomeInterceptor.preHandle(RestSecurityInterceptor.java:29) Spring 3.1 中的 handler 参数似乎仍然是一个控制器。
    • 参见static.springsource.org/spring/docs/3.1.x/… 的注释:“当使用 RequestMappingHandlerMapping 时,实际的处理程序是 HandlerMethod 的一个实例,它标识将被调用的特定控制器方法。”
    • 另外值得一提的是,如果您使用 WebMvcConfigurerAdapter 或 WebMvcConfigurationSupport 添加拦截器(请参阅static.springsource.org/spring/docs/3.1.x/javadoc-api/org/…),那么处理程序将始终是 HandlerMethod 的实例。
    【解决方案3】:

    我也有同样的需要。

    我认为 Spring MVC 提倡使用控制器方法来处理请求的不一致之处,但是 HandlerInterceptor 接口不提供将处理请求的处理程序方法作为参数;只有控制器对象。

    请求在方法级别处理,您需要拦截的是方法执行,为了有效地执行此操作,您需要访问方法元信息,例如,在方法级别声明的自定义注释或其论点。

    HandlerInterceptor.preHandle 签名应该是:

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handlerInstance, Method handlerMethod) throws Exception;

    这样您就可以执行以下操作:

    hadlerMethod.getAnnotation(MyCustomAnnotation.class);

    知道了吗?

    就我而言,我想实现索引参数映射; STRIPES FRAMEWORK 拥有的东西(或闪存范围)。

    我是否必须借助 AspectJ 来实现我的横切功能?令人失望!

    【讨论】:

      【解决方案4】:

      首先,这违反了 MVC 架构模式。 MVC架构是一种架构模式,希望

      将“域逻辑”(用户的应用程序逻辑)与用户界面(输入和呈现)隔离开来,允许独立开发、测试和维护每个(关注点分离)。

      here

      而且controller里面有一个很棒的工作。它渴望解耦,专注于设计等等。希望软件开发者不要放弃GRASP:/

      【讨论】:

      • 但是像安全这样的横切关注点怎么样。此外,拦截器为您提供处理程序对象,但不提供处理程序方法。我认为这与架构模式无关。
      • 我无意冒犯你。你可能做某事总是有“方法”。上一个答案是正确的。但我只是想就这个话题说点什么。
      • 是的,我也没有那样做。但我真的觉得这不合逻辑。
      猜你喜欢
      • 2019-09-29
      • 2020-04-04
      • 2019-08-10
      • 1970-01-01
      • 1970-01-01
      • 2012-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多