新浪有还一天了咋没最新云集品消息一天前

Spring拦截器中通过request获取到该请求对应Controller中的method对象 - 青葱岁月 - ITeye技术网站
博客分类:
背景:项目使用Spring 3.1.0.RELEASE,从dao到Controller层全部是基于注解配置。我的需求是想在自定义的Spring拦截器中通过request获取到该请求对应于Controller中的目标method方法对象。Controller和拦截器代码如下:
AdminController
@Controller
@RequestMapping("/admin")
public class AdminController {
* init:初始页面. &br/&
* @author chenzhou
* @param request 请求
* @param response 响应
* @return 登陆页
* @since JDK 1.6
@RequestMapping("/init")
public ModelAndView init(HttpServletRequest request,
HttpServletResponse response){
Map&String, Object& model = new HashMap&String, Object&();
List&Role& roleList = this.adminService.getRoleList();
model.put("roleList", roleList);
return new ModelAndView(this.getLoginPage(), model);
LoginInterceptor
public class LoginInterceptor extends HandlerInterceptorAdapter {
* This implementation always returns &code&true&/code&.
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
* This implementation is empty.
public void postHandle(
HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView)
throws Exception {
* This implementation is empty.
public void afterCompletion(
HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
servlet xml配置文件定义:
&bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" /&
&bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/&
&bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"&
&property name="interceptors"&
&bean class="com.chenzhou.examples.erm.util.interceptor.LoginInterceptor"/&
&/property&
我的需求是想在preHandle方法中通过request获取该请求访问的目标Controller中的方法对象。之前找了很久也没有找到比较好的方案,就采取了最老土的通过比较requestURL和Controller类和方法上的RequestMappingURL来进行获取,这样也能勉强实现,但是这种方式我自己都觉得特别恶心。首先,这种方式需要使用反射来获取Controller中的所有方法,然后遍历method数组,逐个进行RequestMappingURL的比对,效率低下。其次,如果RequestMapping定义了类似于@RequestMapping("/{id}")这种动态参数url,则无法进行比较。
因为上面这种方式不好,我就一直想找一个更好的方案。不得已只能向人求助,第一个就想到了Iteye上对于Spring研究得很熟悉的龙年兄,我相信经常上iteye的博友们对龙年兄应该都很熟悉。龙年兄给了我一个方案,就是通过把handler对象转换为HandlerMethod类型,然后直接getMethod,代码如下:
* This implementation always returns &code&true&/code&.
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
System.out.println("*********************preHandle********************");
System.out.println(handler.getClass());
HandlerMethod handlerMethod = (HandlerMethod)
System.out.println(handlerMethod.getMethod());
注:HandlerMethod类是Spring 3.1.0.RELEASE版本中才有的,之前我使用的Spring 3.0.6.RELEASE版本,里面是找不到这个类的
根据龙年兄提供的方法,测试之后报错,报错信息如下:
*********************preHandle********************
class com.chenzhou.examples.erm.web.AdminController
16:28:25 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet erm threw exception
java.lang.ClassCastException: com.chenzhou.examples.erm.web.AdminController cannot be cast to org.springframework.web.method.HandlerMethod
at com.chenzhou.examples.erm.util.interceptor.LoginInterceptor.preHandle(LoginInterceptor.java:37)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:891)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
根据错误提示可以看出是HandlerMethod handlerMethod = (HandlerMethod)这一步报错了,根据System.out.println(handler.getClass());打印的结果可以得知handler是该请求访问的Controller类,无法转换成HandlerMethod对象。这次还是龙年兄帮我找出了原因,解决方案是使用
&bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"& 替换 &bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"/&
因为DefaultAnnotationHandlerMapping只能返回Controller对象,不会映射到Controller中的方法级别。替换之后servlet xml配置如下:
&bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" /&
&bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/&
&bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"&
&property name="interceptors"&
&bean class="com.chenzhou.examples.erm.util.interceptor.LoginInterceptor"/&
&/property&
重启tomcat测试之后发现再次报错,报了另外一个错误,具体信息如下:
16:39:39 org.apache.catalina.core.StandardWrapperValve invoke
严重: Servlet.service() for servlet erm threw exception
javax.servlet.ServletException: No adapter for handler [public org.springframework.web.servlet.ModelAndView com.chenzhou.examples.erm.web.AdminController.init(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)]: Does your handler implement a supported interface like Controller?
这一次,请求根本没有到达拦截器容器就已经报错了,错误提示的意思是找不到handler对象对应的Adapter类。我在RequestMappingHandlerMapping类对应的spring-webmvc-3.1.0.RELEASE.jar 包里找到了该类对应的Adapter类:RequestMappingHandlerAdapter,然后在servlet xml中进行了配置:
&bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator" /&
&bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/&
&bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"&
&property name="interceptors"&
&bean class="com.chenzhou.examples.erm.util.interceptor.LoginInterceptor"/&
&/property&
&bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter"/&
然后重新启动tomcat后访问http://localhost:8080/erm/admin/init 结果正常,控制台日志信息如下:
*********************preHandle********************
class org.springframework.web.method.HandlerMethod
public org.springframework.web.servlet.ModelAndView com.chenzhou.examples.erm.web.AdminController.init(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
从日志信息可以看出,handler对象在经过类型转换后转换成了HandlerMethod类型,通过handler.getMethod方法,获取到了该请求访问的方法为com.chenzhou.examples.erm.web.AdminController.init
注:非常感谢jinnianshilongnian 开涛兄的帮助。
浏览 68231
3.0& 没有对应的 handlerMethod 类& ,具体解决办法请参考我的博客三个拦截器处理三个注解搞定基于注解的权限控制,适用性比较通用于Springmvc web项目
楼主,你这样处理,是不是就是为了解决,SPRING AOP不能针对CONTROLLER生效的问题,求回复!也可以这么说吧,当时是为了做权限控制发现aop对Controller不生效,后来就采用了拦截器的方式。
谢谢lz,我google了好久 不客气
感谢楼主无私分享,google了好久了。谢谢鼓励
楼主的这种分享方式真心不错,分享知识,也是一种艺术。这种方式的分享让人受益很大。谢谢鼓励!
针对springmvc3.0版本AnnotationMethodHandlerAdapter可以试下下面方法:Class handlerClass = ClassUtils.getUserClass(handler);
ServletHandlerMethodResolver resolver = new ServletHandlerMethodResolver(handlerClass);
Method handlerMethod = methodResolver.resolveHandlerMethod(request);呵呵,抱歉没注意到ServletHandlerMethodResolver是一个内部私有类
& 上一页 1
chenzhou123520
浏览: 2116785 次
来自: 北京
大家都用过SVN吧,也就是这样的乐观锁机制。大家可以联想起来就 ...
写的很好,赞~!
org.springframework.web.servle ...
赞!!!刚好需要分享即可 +1积分
第1章 概述
第2章 Spring MVC拦截器的实现
第3章 拦截器的使用场景
第4章 拦截器与过滤器的对比及课程总结
Copyright (C)
All Rights Reserved | 京ICP备 号-2springMVC中关于拦截器的两种配置有什么不同?
第一种配置方法:
&bean id=&handlerInterceptor1&
class=&cn.javass.chapter5.web.interceptor.HandlerInterceptor1&/&
&bean id=&handlerInterceptor2&
class=&cn.javass.chapter5.web.interceptor.HandlerInterceptor2&/&
&bean class=&org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping&&
&property name=&interceptors&&
&ref bean=&handlerInterceptor1&/&
&ref bean=&handlerInterceptor2&/&
&/property&
&/bean& 第二种配置方法:
&mvc:interceptors&
&bean class=&cn.javass.chapter5.web.interceptor.HandlerInterceptor1& /&
&bean class=&cn.javass.chapter5.web.interceptor.HandlerInterceptor2& /&
&/mvc:interceptors& 第二种配置方法看上去很简洁,还有没有其它优点呢?还想知道以&mvc:xxxxx&开头的标签配置方法是不是针对SpringMVC所特有的?
引用来自“千斤难买春秋醉”的评论 mvc是spring3之后的一个新的命名空间,推荐用第二种。
&mvc:annotation-driven&/& 是一种简写形式,替代了很多配置。
不过你的mvc:interceptors写的有点奇怪。。。你不配置拦截路径吗?
& & &mvc:interceptors& & & & & &mvc:interceptor& & & & & & & &mvc:mapping path=&/admin/**&/& & & & & & & &bean class=&tk.gbl.web.filter.AdminInterceptor&/& & & & & &/mvc:interceptor& & & &/mvc:interceptors&
(**代表admin子路径也拦截,否则只拦截admin/下的)
谢谢你的解答,受教了!
我还是喜欢传统配置方法,不喜欢mvc开头得标签。
用第二种吧,我一直都在用
&mvc:interceptor&
&mvc:mapping path=&/manage/**&/&
&mvc:exclude-mapping path=&/manage/goLogin.*&/&
&mvc:exclude-mapping path=&/manage/login.*&/&
&mvc:exclude-mapping path=&/manage/logout.*&/&
&bean class=&com.xx.ManageInterceptor&/&
&/mvc:interceptor&
mvc是spring3之后的一个新的命名空间,推荐用第二种。
&mvc:annotation-driven&/& 是一种简写形式,替代了很多配置。
不过你的mvc:interceptors写的有点奇怪。。。你不配置拦截路径吗?
& & &mvc:interceptors& & & & & &mvc:interceptor& & & & & & & &mvc:mapping path=&/admin/**&/& & & & & & & &bean class=&tk.gbl.web.filter.AdminInterceptor&/& & & & & &/mvc:interceptor& & & &/mvc:interceptors&
(**代表admin子路径也拦截,否则只拦截admin/下的)
GOGO我是来打酱油的!
用第二种的原因是因为用了&mvc:annotation-driven&,&mvc:annotation-driven&会自动注入BeanNameUrlHandlerMapping,而且官方也不推荐手动注入BeanNameUrlHandlerMapping这个方法
结果:请用第二种,不过第二种写法是不是有点奇怪?
--- 共有 1 条评论 ---
谢谢你的解答!确实没注意到拦截路径。Java过滤器与SpringMVC拦截器之间的关系与区别_Java_ThinkSAAS
Java过滤器与SpringMVC拦截器之间的关系与区别
Java过滤器与SpringMVC拦截器之间的关系与区别
内容来源: 网络
今天学习和认识了一下,过滤器和SpringMVC的拦截器的区别,学到了不少的东西,以前一直以为拦截器就是过滤器实现的,现在想想还真是一种错误啊,而且看的比较粗浅,没有一个全局而又细致的认识,由于已至深夜,时间原因,我就把一些网友的观点重点摘录下来,大家仔细看后也一定会有一个比较新的认识(在此非常感谢那些大牛们的无私奉献,分享他们的经验与心得,才能让像我这样的小白有机会站一下你们这些巨人的肩膀,才能少走些弯路)。
  过滤器和拦截器的区别:
  ①拦截器是基于java的反射机制的,而过滤器是基于函数回调。
  ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
  ③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
  ④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
  ⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。
  ⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。
  写了点测试代码,顺便整理一下思路,搞清楚这几者之间的顺序:
  1.过滤器是JavaEE标准,采用函数回调的方式进行。是在请求进入容器之后,还未进入Servlet之前进行预处理,并且在请求结束返回给前端这之间进行后期处理。
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("before...");
chain.doFilter(request, response);
System.out.println("after...");
  chain.doFilter(request, response);这个方法的调用作为分水岭。事实上调用Servlet的doService()方法是在chain.doFilter(request, response);这个方法中进行的。
  2.拦截器是被包裹在过滤器之中的。
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("preHandle");
return true;
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("postHandle");
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
System.out.println("afterCompletion");
  a.preHandle()这个方法是在过滤器的chain.doFilter(request, response)方法的前一步执行,也就是在 [System.out.println("before...")][chain.doFilter(request, response)]之间执行。
  b.preHandle()方法之后,在return ModelAndView之前进行,可以操控Controller的ModelAndView内容。
  c.afterCompletion()方法是在过滤器返回给前端前一步执行,也就是在[chain.doFilter(request, response)][System.out.println("after...")]之间执行。
  3.SpringMVC的机制是由同一个Servlet来分发请求给不同的Controller,其实这一步是在Servlet的service()方法中执行的。所以过滤器、拦截器、service()方法,dispatc()方法的执行顺序应该是这样的,大致画了个图:其实非常好测试,自己写一个过滤器,一个拦截器,然后在这些方法中都加个断点,一路F8下去就得出了结论。
  总结:拦截器功在对请求权限鉴定方面确实很有用处,在我所参与的这个项目之中,第三方的远程调用每个请求都需要参与鉴定,所以这样做非常方便,而且他是很独立的逻辑,这样做让业务逻辑代码很干净。和框架的其他功能一样,原理很简单,使用起来也很简单,大致看了下SpringMVC这一部分的源码,其实还是比较容易理解的。
  我们项目中仅仅用到了preHandle这个方法,而未用其他的,框架提供了一个已经实现了拦截器接口的适配器类HandlerInterceptorAdapter,继承这个类然后重写一下需要用到的方法就行了,可以少几行代码,这种方式Java中很多地方都有体现。
以上部分是摘自,参考了一下这个帖子:/blog/1750680
大家还可以参考一下这个电子书的截图:
PHP开发框架
开发工具/编程工具
服务器环境
ThinkSAAS商业授权:
ThinkSAAS为用户提供有偿个性定制开发服务
ThinkSAAS将为商业授权用户提供二次开发指导和技术支持
让ThinkSAAS更好,把建议拿来。
开发客服微信

我要回帖

更多关于 最新云集品消息一天前 的文章

 

随机推荐